I found really strange behavior in a relatively simple use case, maybe I can’t figure it out due to not deep knowledge of spring @Transactional nature, but it’s quite interesting.
I have a simple custom dao that extends the spring class of JpaDaoSupport and contains a standard save method:
@Transactional public User save(User user) { getJpaTemplate().persist(user); return user; }
If it worked fine until I add a new method to the same class: User getSuperUser (), this method should return the user with isAdmin == true, and if there is no superuser in db, the method should create it. Here's how it looked:
public User createSuperUser() { User admin = null; try { admin = (User) getJpaTemplate().execute(new JpaCallback() { public Object doInJpa(EntityManager em) throws PersistenceException { return em.createQuery("select u from UserImpl u where u.admin = true").getSingleResult(); } }); } catch (EmptyResultDataAccessException ex) { User admin = new User('login', 'password'); admin.setAdmin(true); save(admin);
As you can see, the code is strange, and I was very confused when I found out that no transaction was created and committed when the save (admin) method was called, and no new user was created, despite the @Transactional annotation.
As a result, a situation arises: when the save () method is called from outside the UserDAO class - the @Transactional annotation counts and the user is successfully created, but if save () calls from the dao class from another method - the @Transactional annotation is ignored.
This is how I modified the save () method to make it always create a transaction.
public User save(User user) { getJpaTemplate().execute(new JpaCallback() { public Object doInJpa(EntityManager em) throws PersistenceException { em.getTransaction().begin(); em.persist(user); em.getTransaction().commit(); return null; } }); return user; }
As you can see, I manually call begin and commit. Any ideas?
java spring aop hibernate jpa
abovesun
source share