IntroductionTransactions can be managed using the @Transactional, @UserTransactional, and @SharkTransactional annotations. We can use these annotations only in classes managed by the application context. - @Transactional - creates a Hibernate transaction
- @SharkTransactional - creates a SharkTransaction
- @UserTransactional - creates a UserTransaction
Info |
---|
| It is recommended to use annotations to manage transactions in classes marked with @Service annotation |
In classes that are not managed by the application context, we can also call our code blocks inside a single transaction using the appropriate wrapper methods from the TransactionWrapper class (from version 3.2.76). In earlier versions, use the TransactionTemplate directly. Tip |
---|
Keep in mind that all the database operations we perform in a task should take place inside a single transaction. This will make our code transactional and faster to execute. |
Usage examples using annotations
Code Block |
---|
language | java |
---|
title | Performing several operations in a single transaction |
---|
| @Service
public class CustomServiceImpl
implements CustomService
{
@Autowired
private StructureService structureService;
@Transactional
public void addPositionAndOu()
{
Position p = new Position( "name", "symbol" );
OrganizationalUnit ou = new OrganizationalUnit();
ou.setName( "name" );
ou.setSymbol( "symbol" );
structureService.createPosition( p );
structureService.createOrganizationalUnit( ou );
}
public void addPositionAndOuNonTransactional()
{
Position p = new Position( "name", "symbol" );
OrganizationalUnit ou = new OrganizationalUnit();
ou.setName( "name" );
ou.setSymbol( "symbol" );
structureService.createPosition( p );
structureService.createOrganizationalUnit( ou );
}
}
|
In the above example, the function without the @Transactional annotation will create separate transactions for each save function, while in the function marked @Transactional, both operations will run on the same transaction. Manual transaction managementIf you need to execute a block of code inside an active hibernate or shark transaction and have access to sessions and transactions, then you should use the TransactionWrapper class. Code Block |
---|
language | java |
---|
title | Perform operations inside hibernate transactions |
---|
| TransactionWrapper.get().doInHibernateTransaction( ( session ) -> {
QueryExecutor qe = ComponentFactory.getQueryExecutor();
SQLQuery sql = qe.createSQLQuery( ... );
...
sql.executeUpdate();
}); |
Code Block |
---|
language | java |
---|
title | Perform operations inside a shark transaction |
---|
| TransactionWrapper.get().doInSharkTransaction( ( sharkTransaction ) -> {
ActivityService activityService = ServiceFactory.getActivityService();
Map<String, Object> activityContext = activityService.getActivityContext( processId, activityId );
activityContext.put( "id_zmiennej", "nowa_wartość" );
activityService.setActivityContext( processId, activityId, activityContext );
}); |
The code can also return any result. Manual transaction management below version 3.2.76 (from version 3.2.76 onward, use the previous point)It is possible to manually manage transactions in cases where we need more control or need them in a code area where we cannot use the annotations described above. For this purpose, you can use the TransactionManagerFactory class. Code Block |
---|
language | java |
---|
title | Transaction management via TransactionTemplate |
---|
|
TransactionTemplate tt = new TransactionTemplate( TransactionManagerFactory.getHibernateTransactionManager() );
tt.execute( new TransactionCallbackWithoutResult()
{
@Override
protected void doInTransactionWithoutResult( TransactionStatus status )
{
QueryExecutor qe = ComponentFactory.getQueryExecutor();
SQLQuery sql = qe.createSQLQuery( ... );
...
sql.executeUpdate();
}
} ); |
If you need to access the Session object from Hibernate, you should use TransactionTemplate as follows: Code Block |
---|
language | java |
---|
title | Transaction management with access to Session |
---|
|
TransactionTemplate tt = new TransactionTemplate( TransactionManagerFactory.getHibernateTransactionManager() );
tt.execute( new SessionAwareTransactionCallbackWithoutResult()
{
@Override
public void doWithSession( Session session )
{
session.delete( ... );
}
} ); |
Code Block |
---|
language | java |
---|
title | Transaction management via TransactionTemplate |
---|
| final SharkTransactionManager mgr= TransactionManagerFactory.getSharkTransactionManager();
TransactionTemplate tt = new TransactionTemplate( mgr );
tt.execute( new TransactionCallbackWithoutResult()
{
@Override
protected void doInTransactionWithoutResult( TransactionStatus status )
{
SharkTransaction sharkTransaction = mgr.getSharkTransaction();
...
}
} ); |
Code Block |
---|
language | java |
---|
title | Manual transaction management |
---|
| SharkTransactionManager mgr = TransactionManagerFactory.getSharkTransactionManager();
TransactionStatus txStatus = null;
try
{
txStatus = mgr.getTransaction( new DefaultTransactionDefinition() );
SharkTransaction sharkTransaction = mgr.getSharkTransaction();
...//performing operations on a transaction
mgr.commit( txStatus );
}
catch ( Exception ex )
{
mgr.rollback( txStatus );
} |
SharkTransactionTemplateThe com.suncode.pwfl.transaction.support.SharkTransactionTemplate class facilitates Shark transaction management in a readable and secure way. Tip |
---|
Wherever we need a Shark transaction you should use the SharkTransactionTemplate class because of its easier use. Transaction code handling can be complicated and needs to be handled carefully. |
If the code using the transaction returns a result, the call will look like this: Code Block |
---|
SharkTransactionTemplate tx = new SharkTransactionTemplate();
int result = tx.execute( new SharkTransactionCallback<Integer>()
{
@Override
public Integer doInSharkTransaction( SharkTransaction transaction, TransactionStatus status )
throws Exception
{
// use of transactions
return 1;
}
} ); |
In case you call a procedure that does not return any result, you can use another callback SharkTransactionCallbackWithoutResult : Code Block |
---|
SharkTransactionTemplate tx = new SharkTransactionTemplate();
tx.execute( new SharkTransactionCallbackWithoutResult()
{
@Override
public void doInSharkTransactionWithoutResult( SharkTransaction transaction, TransactionStatus status )
throws Exception
{
// use of transactions
}
} ); |
Info |
---|
The default SharkTransactionTemplate configuration uses the current transaction, if available, or opens a new one. |
Useful resources: |