简体   繁体   中英

JPA service layer transactions

I have MVC layered app using JPA 2, Hibernate (without Spring or any additional framework).

Now transactions are achieved only on DAO layer like this:

public class AccountDao {
    private EntityManagerFactory emf;

    public AccountDao(EntityManagerFactory emf) {
        this.emf = emf;
    }

    public void saveAccount(Account account) {
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        try {
            em.persist(account);
            em.getTransaction().commit();
        } catch (Exception ex) {
            em.getTransaction().rollback();
        } finally {
            em.close();
        }
    }
}

But what I want is to obtain transaction on service layer:

public class AccountService {
    private AccountDao accountDao;
    private UserDao userDao;

    //needed the method to be in transaction
    public void transferUserAccount(){
        User user = // ...
        userDao.saveUser(user);

        Account account = //
        accountDao.saveAccount(account);
        //rest logic that has to be executed atomically
    }
}

One of possible solution is to wrap code inside transferUserAccount() method in another try/catch/finally with em.getTransaction().begin() (or create custom @Transactional annotation that will do that under the hood), but I am not sure how JPA handles nested transactions. Also such solution exposes the DAO specific things like entity manager into service layer.

Anyway, is the solution with nested transaction within transferUserAccount() is appropriate?

Are there any other solutions to handle such cases? Thanks in advance!

If you do not want to leak the transaction management into your service, I would suggest to further split the DAO such that the DAO has two DAOs/repositories-attributes (one for User , one for Account ), create the transaction in the DAO-method and pass the EntityManager down to the User - and Account -DAO/repository.

Another option would be to create a method transferAccount(Account account, user from, user to) within AccountDao , create the transaction there, perform all your logic and then call userDao.save(from, em) , userDao.save(to, em) and save(account, em) from there.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM