Lost transaction with JPA unique constraint?
I have a field with an unique constraint:
@Column(unique=true)
private String uriTitle;
When I try to save two entities with the same value, I get an exception - but another exception than I exected:
java.lang.IllegalStateException: <|Exception Description: No transaction is cu开发者_如何学Gorrently active
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.rollback(EntityTransactionImpl.java:122)
at com.example.persistence.TransactionFilter.doFilter(TransactionFilter.java:35)
The questionable filter method looks like this:
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();
}
}
... and the ThreadLocalEntityManager like this:
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();
}
}
I wrapped the call to save
with try ...catch
to handle the unique constraint violation, but that doesn't work:
try {
ThreadLocalEntityManager.get().persist(article); // article is constrained
}
catch(Throwable t) {
t.printStackTrace();
}
Any idea why there is no transaction? What is the correct way to handle a unique constraint violation?
Your transaction rolled back automatically due to DB constraint violation, therefore there is no transaction to rollback manually. To handle this case, you can write
catch (Throwable t) {
if (transaction.isActive())
transaction.rollback(); // line 35, mentioned in the exception
throw new RuntimeException(t);
}
You don't have any separation between transactions and GUI in your application. You will have problems with transaction handling in general.
精彩评论