Потерянная транзакция с уникальным ограничением JPA? - PullRequest
0 голосов
/ 17 августа 2010

У меня есть поле с уникальным ограничением:

@Column(unique=true)
private String uriTitle;

Когда я пытаюсь сохранить два объекта с одинаковым значением, я получаю исключение - но другое исключение, которое я ожидал:

java.lang.IllegalStateException: <|Exception Description: No transaction is currently active
        at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.rollback(EntityTransactionImpl.java:122)
        at com.example.persistence.TransactionFilter.doFilter(TransactionFilter.java:35)

Метод сомнительного фильтра выглядит следующим образом:

public void doFilter(ServletRequest request, ServletResponse response,
          FilterChain chain)
          throws IOException, ServletException {
    EntityManager entityManager = ThreadLocalEntityManager.get();
    EntityTransaction transaction = entityManager.getTransaction();
    transaction.begin();
    try {
      chain.doFilter(request, response);
      transaction.commit();
    }
    catch (Throwable t) {
      transaction.rollback();  // line 35, mentioned in the exception
      throw new RuntimeException(t);
    }
    finally {
      entityManager.close();
      ThreadLocalEntityManager.reset();
    }
}

... и ThreadLocalEntityManager вот так:

public class ThreadLocalEntityManager {

    private static EntityManagerFactory entityManagerFactory = null;
    private static final ThreadLocal<EntityManager> entityManager =
        new ThreadLocal<EntityManager>() {
            @Override 
            protected EntityManager initialValue() {
                return entityManagerFactory.createEntityManager();
            }
        };

    private ThreadLocalEntityManager() {}

    public static synchronized void init(String persistenceUnit) {
        requireNotNull(persistenceUnit);
        requireState(entityManagerFactory == null, "'init' can be called only "
                        + "once.");
        entityManagerFactory =
                        Persistence.createEntityManagerFactory(persistenceUnit);
    }

    public static EntityManager get() {
        requireState(entityManagerFactory != null, "Call 'init' before calling "
                        + "'get'");
        return entityManager.get();
    }

    public static void reset() {
        entityManager.remove();
    }

}

Я обернул вызов save с помощью try ...catch для обработки уникального нарушения ограничения, но это не работает:

try {
    ThreadLocalEntityManager.get().persist(article); // article is constrained
}
catch(Throwable t) {
    t.printStackTrace();
}

Есть идеи, почему нет транзакции? Как правильно обработать уникальное нарушение ограничения?

Ответы [ 2 ]

2 голосов
/ 17 августа 2010

Ваша транзакция откатывается автоматически из-за нарушения ограничений БД, поэтому нет транзакции для отката вручную. Чтобы справиться с этим делом, вы можете написать

catch (Throwable t) {
  if (transaction.isActive()) 
    transaction.rollback();  // line 35, mentioned in the exception 
  throw new RuntimeException(t); 
}
0 голосов
/ 16 октября 2012

В вашем приложении нет разделения между транзакциями и графическим интерфейсом.У вас будут проблемы с обработкой транзакций в целом.

...