В вашем коде нужно учесть множество вещей, хотя я не могу гарантировать, что они связаны с вашей проблемой.
Во-первых, создание вашей фабрики менеджеров сущностей и менеджера сущностей каждый раз, когда вы просто хотите сохранить сущность, слишком дорого. Кроме того, вы не закрываете свою фабрику менеджеров сущностей.
Правильный способ сделать это - создать фабрику управления сущностями и поддерживать ее доступной на протяжении всего срока службы вашего приложения. Каждый раз, когда вы начинаете разговор с вашим пользователем (то есть транзакцию), затем запрашиваете у него менеджера сущностей, используйте его для сохранения всего, что вы хотите сохранить, и затем закрываете менеджера сущностей.
Когда ваше приложение завершит работу, закройте фабрику менеджера сущностей.
Второй аспект, который вы могли бы принять во внимание, заключается в том, что определенные исключения уже подразумевают откат, например, любое исключение, выброшенное во время выполнения коммита. Поэтому, если вы попытаетесь выполнить второй откат, вы получите второе исключение, которое вы не обрабатываете.
Я не могу гарантировать, что что-то из этих изменений решит вашу проблему, но это, безусловно, хорошее начало.
Это, как говорится, для меня не очевидно из вашего кода, где вы сохраняете более чем одну сущность. Я думаю, требуется больше контекста.
Я бы предложил что-то вроде этого:
public class DataAccessLayer {
private EntityManagerFactory emf;
public DataAccessLayer (){
}
public synchronized void start(){
if(isStarted())
throw new IllegalStateException("Already started");
this.emf = Persistence.createEntityManagerFactory("AllmoviesPU");
}
public synchronized void stop(){
if(!isStarted())
throw new IllegalStateException("Not started");
this.emf.close();
this.emf = null;
}
public synchronized boolean isStarted(){
return this.emf != null;
}
public void doPersistenceStuff(InputData o){
if(!isStarted())
throw new IllegalStateException("Not started");
EntityManager em = emf.getEntityManager();
EntityTransaction t = entityManager.getTransaction();
try {
t.begin();
//do persistence stuff here
t.commit();
}
catch (RollbackException e) {
//transaction already rolledback
throw new MyPersistenceException(e);
}
catch (Exception e) {
t.rollback(); //manual rollback
throw new MyPersistenceException(e);
}
em.close()
}
}
И вы можете убедиться, что ЭДС закрыта, когда ваше приложение будет завершено (например, когда пользователь нажимает кнопку выхода или когда ваш сервер останавливается или завершает работу), вызывая метод stop () в экземпляре уровня доступа к данным.