Using transaction in Spring 3.0 in Spring + JPA + Hibernate
I currently using Spring + JPA + hibernate in a project. Then i decide my design pattern in model dan DAO implementation. I have a abstract for all my transaction purpose class. Every class( as a service) that perform a single update/create/delete task must inherits from this abstract class.
public class GlobalAbstractTransaction {
public abstract void validation(DTO param);
public abstract void process(DTO param);
public void execute(DTO param){
validation(param);
process(param);
}
}
Then i have another class (subclass of class above)
@Service
@Transactional //using spring annotation for transactional support
public cl开发者_如何学Pythonass SomeTransaction extends GlobalAbstractTransaction
implements ITransaction {
//implements abstract method
public void validation(DTO param){
}
//implements abstract method
public void process(DTO param){
}
}
The BusinessTransaction is an interface that have one method
public interface ITransaction {
public execute(DTO param);
}
Noted that I put @Transactional (with default Propagation.REQUIRED) at class SomeTransaction want to make sure that this class is in a Transaction.
When using in IntegrationTest
@Autowired //default by name
ITransaction someTransaction;
@Test
public void testInsert(){
DTO someDTO = new DTO();
//apply value for DTO
someTransaction.execute(someDTO);
}
The result is there is no transaction occured. And the someTransaction.execute which only perform inserting data to database task, was not running well.
And then I move the @Transactional annotation from SomeTransaction, to GlobalAbstractTransaction so the code would be like this.
Modified GlobalAbstractTransaction
public class GlobalAbstractTransaction {
public abstract void validation(DTO param);
public abstract void process(DTO param);
@Transactional //added here
public void execute(DTO param){
validation(param);
process(param);
}
}
Modified SomeTransaction
@Service
//transactional annotation removed
public class SomeTransaction extends GlobalAbstractTransaction
implements ITransaction {
//implements abstract method
public void validation(DTO param){
}
//implements abstract method
public void process(DTO param){
}
}
Then, the test work, data is inserted to database.
- Anybody could explain why this is happening. I can't add @Transactional at SomeTransaction.execute, because it already defined in GlobalAbstractTransaction. Can I add @Transactional add class level instead ?
SomeTransaction is planned as Service, inside the service I autowired a DAO implementation using autowiring (I don't put any @Transactional at DAO level), that's what most people recommends. I just annotaed DAO implementation as @Repository, the service class as @Service. (note that in my service only perform one task, InsertingService, UpdatingService, DeletingService will be separated in three classes). I'm planning to add another layer for Service Facade ([http://java.dzone.com/articles/jpa-implementation-patterns-3][1]) see link for reference. So i create a class
public class ServiceFacadeBean { public void executeTransaction(String name){
} }
I'm intended to using in the application like this.
@Autowired //injected using Spring autowiring
ServiceFacadeBean serviceFacadeBean;
serviceFacadeBean.execute("com.mycompany.SomeTransaction");
In the implementation of the execute I want to use reflection using "com.mycompany.SomeTransaction" to create instance. but I always get NullPointerException
Class clazz = Class.forName("com.mycompany.SomeTransaction");
clazz.newInstance() <--- get null
And I'm intended that 1 service class, only perform 1 transaction task such as Inserting to database. What to best practices for putting @Transactional, or anyone have good links that really explaining well bout Transaction issue using Spring transaction
Anyone have experience on this, or have any better design pattern solutions? Thanks
I have contacts to a software company in Jakarta that is using exactly the same architecture as you are implementing. They have BusinessTransactions that perform a single task and receives a single DTO as a parameter. The beans are also managed using Spring 3.0, persistence is done with JPA 2 and Hibernate as well. Concerning your NullPointerExecution you should not use reflection neither your ServiceFacadeBean but let your BusinessTransactions be named beans like that:
@Service("SomeTransaction")
//transactional annotation removed
public class SomeTransaction extends AbstractTransaction
implements ITransaction {
....
}
Whenever you need to execute this transaction you inject it like that:
@Autowired
@Qualifier("SomeTransaction")
ITransaction someTransaction;
public doSomething() {
DTO dto = new DTO();
dto.putString("id", "948392943");
someTransaction.execute(dto);
}
PS: Is there any way to contact you as I am traveling in Jakarta right now. Would be very interesting to share IT experience directly with you.
精彩评论