layout | title |
---|---|
default |
Spring Data ArangoDB - Transactions |
Spring Data provides Transaction Management which is implemented by Spring Data ArangoDB using Stream Transactions. To enable Arango Transaction Management, a configuration class is needed:
Example
@Configuration
@EnableTransactionManagement
@Import(ArangoTransactionManagementConfigurer.class)
class TransactionConfiguration {
}
The configuration will expose a PlatformTransactionManager
as bean and allow to either declare transactions using
@Transactional
or programmatic using a special version of the TransactionTemplate
.
The Arango Transaction Management does neither support the isoation SERIALIZABLE
nor the propagation NESTED
.
Any transactions started within one existing transactions are using the same stream transaction and are comitted or rolled back at the end of the existing one.
Use Spring's annotation-driven transaction management by adding @Transactional
to classes and/or methods. A typical
approach is to make all public methods using read-only transactions by adding @Transactional(readOnly = true)
at
class level and overriding by additional @Transactional
on method level.
If the method is writing to multiple collections in multiple repository calls, you have to declare all collections that will be written using labels. This is required as a stream transaction has to know all collections written from the beginning.
Example
import com.arangodb.springframework.repository.ArangoRepository;
@Service
@Transactional(readOnly = true)
public class EntityService {
private ArangoRepository<Entity1, Long> repository1;
private ArangoRepository<Entity2, Long> repository2;
// read only transaction from class level, no explicit collections needed
public Entity1 getById(Long id) {
return repository1.findById(id).orElseThrow();
}
// transaction writing one collection need no explicit collection names
@Transactional
public Entity1 saveSingleCollection(Entity1 one) {
return repository1.save(one);
}
// transaction writing multiple collections need explicit collection names
@Transactional(label = {"Entities1", "Entities2"})
public void saveMultipleCollections(Entity1 one, Entity2 two) {
repository1.save(one);
repository2.save(two);
}
}
The TransactionTemplate
handles the transaction management offering a TransactionCallback
to passed to execute()
.
Using the subclass TransactionAttributeTemplate
also labels can easily be used.
Instead of setting the labels on the template, a TransactionAttribute
can be passed as second constructor parameter:
Examples
ArangoRepository<Entity1, Long> repository1 = ...;
ArangoRepository<Entity2, Long> repository2 = ...;
PlatformTransactionManager manager = ...;
TransactionAttributeTemplate template = new TransactionAttributeTemplate(manager);
template.setLabels(Arrays.asList("Entities1", "Entities2"));
template.execute(status -> {
repository1.findById(id).ifPresent(one -> {
Entity2 two = new Entity2();
repository2.save(two);
repository1.save(one);
}
});
or
PlatformTransactionManager manager = ...;
DefaultTransactionAttribute attributes = new DefaultTransactionAttribute();
attributes.setLabels(Arrays.asList("Entities1", "Entities2"));
TransactionTemplate template = new TransactionAttributeTemplate(manager, attributes);
See arangodb/spring-data#80