I'm working on a project where I want to use a very specific transaction propagation strategy. The database has two sets of tables, active and archive. Each set of tables is implemented with its own Entities and Interfaces that extend CrudRepository<T, ID>
. The goal is to have a set of entities inserted into the active tables and to have all the data in the active tables inserted into the archive tables in a single transaction. The entities in the tables are not the same, and will have different table structures.
Given two separate repositories similar to the form
public interface FooRepository extends CrudRepository<Foo, Integer>
public interface FooArchiveRepository extends CrudRepository<FooArchive, Integer>
and an implementation similar to
@Autowired FooRepository fooRepo;
@Autowired FooArchiveRepository fooArchiveRepo;
@Autowired BarService barService;
List<Foo> newData = barService.doThing();
fooRepo.saveAll(newData);
// fooData is a list of FooArchive from earlier
fooArchiveRepo.saveAll(fooData);
The goal is to have fooRepo.saveAll(newData)
and fooArchiveRepo.saveAll(fooData)
be guaranteed to execute in a single database transaction. Spring's default transaction propagation of Required
has different Transactional
methods execute in the same physical transaction - does that apply to all Transactional
methods within the Application Context, or only on a per-entity basis?
Spring provides support for synchronizing resources with transactions since the earliest versions. We often use it to synchronize transactions managed by multiple transaction managers. For example, we can synchronize a JMS commit with a JDBC commit.
"@Transactional" as itself on any isolation level doesn't enabling any locking. To achieve locking behaviour you should use "@Lock" annotation or use " for update" in your query.
You can only have one repository per entity... however, you can have multiple entities per table; thus, having multiple repositories per table.
Nested transactions in Spring are just JDBC / database savepoints. If you don't know what a savepoint is, have a look at this tutorial, for example. Note that savepoint support is dependent on your JDBC driver/database.
wrap the save calls into a new method and annotate the method with @Transactional
@Transactional
public void saveAll(){
fooRepo.saveAll(newData);
// fooData is a list of FooArchive from earlier
fooArchiveRepo.saveAll(fooData);
}
by default (PROPAGATION_REQUIRED) it will execute the inner transactions into the same transaction. Please see https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/images/tx_prop_required.png
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With