Reputation: 3452
I am learning to use JPA. And I'm a little confused.
According JPA EntityManager manages transactions. But a design pattern is to inject the EntityManager in DAOs. So how is possible that are different EntityManager to the same transaction?
This is the case I want to solve
I have the DAOs defined
@Repository
JPARepository1 {
@PersistenceContext
protected EntityManager em;
....
.
@Repository
JPARepository2 {
@PersistenceContext
protected EntityManager em;
....
I have a Service
@Service
public class ServiceImpl1 {
@Autowired
private JPARepository1 repo1;
@Autowired
private JPARepository2 repo2;
public void mainMethod(){
Object o= transactionalMethod1();
try{
transactionalMethod2(o);
}catch (Exception e){
transactionalMethod3(o);
}
}
private Object transactionalMethod1(){
....
}
private void transactionalMethod2(Object o){
....
}
private void transactionalMethod3(Object o){
....
}
Then from @Controller I will invoke mainMethod(). What would be the right way to do transactional to transactionalMethod1, transactionalMethod2 and transactionalMethod3,within the same Service and using the same Repository's. I would like it if there is an exeption in transactionalMethod2, this abort the transaction, but keep the transactions of transactionalMethod1 and transactionalMethod3 Thanks, sorry for my English
Upvotes: 0
Views: 172
Reputation: 552
Usually you configure one EntityManager, so the wired manager is always the same, the one you configured. The instance of this manager though, is different in every wiring.
So, every transaction in your service uses a different instance of the EntityManager and thus every transaction invoked is seperated from each other.
As so, an exception in transactionalMethod2
doesn't necessarily affects the transactionalMethod1
and transactionalMethod3
What would be the right way to do transactional to transactionalMethod1, transactionalMethod2 and transactionalMethod3,within the same Service and using the same Repository's.
Now, you have two options to do service methods transactions
1) You could annotate your whole @Service
like that:
@Service
@Transactional
public class ServiceImpl1 {
....
so every method declared here is also a transaction.
2) You could annotate each method as @Transactional
:
@Transactional
private Object transactionalMethod1(){
....
}
@Transactional
private void transactionalMethod2(Object o){
....
}
@Transactional
private void transactionalMethod3(Object o){
....
}
If you want to use a single repository just @Autowired
a single one and use it in your @Transactional
method. E.g:
@Service
@Transactional
public class ServiceImpl1 {
@Autowired
private JPARepository1 repo1;
public void mainMethod(){
Object o= transactionalMethod1();
try{
transactionalMethod2(o);
}catch (Exception e){
transactionalMethod3(o);
}
}
private Object transactionalMethod1(){
return repo1.findOne();
}
private void transactionalMethod2(Object o){
repo1.create(o);
}
private void transactionalMethod3(Object o){
repo1.delete(o)
}
Upvotes: 2