Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save aburmeis/5abb8a474da4d551a398d6a0d6854088 to your computer and use it in GitHub Desktop.
Save aburmeis/5abb8a474da4d551a398d6a0d6854088 to your computer and use it in GitHub Desktop.
Arango Spring Data documentation add-on for transactions (#80)
layout title
default
Spring Data ArangoDB - Transactions

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.

Restrictions

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.

Declarative Transaction Management

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);
    }
}

Programmatic Transaction Management

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);
@aburmeis
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment