Я не совсем понимаю, почему вы так усложняете свой метод обслуживания.Вы просто должны быть в состоянии сделать это следующим образом
@Transactional
public void insertUser(User user) {
entityManager.persist( user );
}
Если есть точки, где вам нужен доступ к нативному Hibernate Session
, вы можете просто развернуть и использовать Session
прямо так:
@Transactional
public void doSomethingFancyWithASession() {
Session session = entityManager.unwrap( Session.class );
// use session as needed
}
Здесь подразумевается, что Spring предоставляет вам уже работающий экземпляр EntityManager
, используя аннотацию @PersistenceContext
.Этот экземпляр будет безопасно использоваться текущим потоком, внутри которого выполняется ваш bean-компонент.
Во-вторых, при использовании @Transactional
это заставляет управление транзакциями Spring автоматически проверять, что EntityManager
привязан ктранзакция, будь то транзакция RESOURCE_LOCAL
или JTA
, основана на конфигурации вашей среды.
Вы столкнулись с проблемой из-за вызова #getCurrentSession()
.
ЧтоSpring создает EntityManager
, а затем внутри вашего метода при вызове #getCurrentSession()
вы просите Hibernate создать второй сеанс, который не связан с транзакцией, запущенной вашей аннотацией @Transactional
.Короче говоря, это сродни следующему:
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
Session aNewSession = entityManager.unwrap( Session.class )
.getFactory()
.getCurrentSession();
// at this point entityManager is scoped to a transaction
// aNewSession is not scoped to any transaction
// this also likely uses 2 connections to the database which is a waste
Так что следуйте парадигме, которую я упоминал выше, и вам больше не придется сталкиваться с проблемой.Вам никогда не нужно вызывать #getCurrentSession()
или #openSession()
в среде Spring, если вы правильно разрешаете Spring вводить ваш экземпляр EntityManager
для вас.