HHH-10510 - Root cause not properly extracted when transaction commit fails
This commit is contained in:
parent
2dc6bd591b
commit
fd6aadcd2a
|
@ -63,11 +63,12 @@ public class TransactionImpl implements EntityTransaction {
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
Throwable wrappedException;
|
Throwable wrappedException;
|
||||||
if ( e instanceof PersistenceException ) {
|
if ( e instanceof PersistenceException ) {
|
||||||
if ( e.getCause() instanceof HibernateException ) {
|
Throwable cause = e.getCause() == null ? e : e.getCause();
|
||||||
wrappedException = entityManager.convert( (HibernateException) e.getCause() );
|
if ( cause instanceof HibernateException ) {
|
||||||
|
wrappedException = entityManager.convert( (HibernateException) cause );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
wrappedException = e.getCause();
|
wrappedException = cause;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( e instanceof HibernateException ) {
|
else if ( e instanceof HibernateException ) {
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.jpa.test.transaction;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationHandler;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Proxy;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.EntityManagerFactory;
|
||||||
|
import javax.persistence.PersistenceException;
|
||||||
|
|
||||||
|
import org.hibernate.cfg.Environment;
|
||||||
|
import org.hibernate.dialect.Dialect;
|
||||||
|
import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
|
||||||
|
import org.hibernate.jpa.boot.spi.Bootstrap;
|
||||||
|
import org.hibernate.jpa.test.PersistenceUnitDescriptorAdapter;
|
||||||
|
import org.hibernate.jpa.test.SettingsGenerator;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
public class TransactionCommitFailureTest {
|
||||||
|
|
||||||
|
public static final String COMMIT_FAILURE = "Commit failed!";
|
||||||
|
|
||||||
|
private static final AtomicBoolean transactionFailureTrigger = new AtomicBoolean( false );
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConfiguredInterceptor() {
|
||||||
|
Map settings = basicSettings();
|
||||||
|
EntityManagerFactory emf = Bootstrap.getEntityManagerFactoryBuilder( new PersistenceUnitDescriptorAdapter(), settings ).build();
|
||||||
|
EntityManager em = emf.createEntityManager();
|
||||||
|
|
||||||
|
try {
|
||||||
|
em.getTransaction().begin();
|
||||||
|
transactionFailureTrigger.set( true );
|
||||||
|
em.getTransaction().commit();
|
||||||
|
}
|
||||||
|
catch ( Exception e ) {
|
||||||
|
assertEquals(PersistenceException.class, e.getCause().getClass());
|
||||||
|
assertEquals(COMMIT_FAILURE, e.getCause().getMessage());
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if ( em.getTransaction() != null && em.getTransaction().isActive() ) {
|
||||||
|
em.getTransaction().rollback();
|
||||||
|
}
|
||||||
|
em.close();
|
||||||
|
emf.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Map basicSettings() {
|
||||||
|
return SettingsGenerator.generateSettings(
|
||||||
|
Environment.HBM2DDL_AUTO, "create-drop",
|
||||||
|
Environment.USE_NEW_ID_GENERATOR_MAPPINGS, "true",
|
||||||
|
Environment.DIALECT, Dialect.getDialect().getClass().getName(),
|
||||||
|
Environment.CONNECTION_PROVIDER, ProxyConnectionProvider.class.getName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ProxyConnectionProvider extends DriverManagerConnectionProviderImpl {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Connection getConnection() throws SQLException {
|
||||||
|
Connection delegate = super.getConnection();
|
||||||
|
return (Connection) Proxy.newProxyInstance(
|
||||||
|
this.getClass().getClassLoader(),
|
||||||
|
new Class[]{Connection.class},
|
||||||
|
new ConnectionInvocationHandler(delegate));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ConnectionInvocationHandler implements InvocationHandler {
|
||||||
|
|
||||||
|
private final Connection delegate;
|
||||||
|
|
||||||
|
public ConnectionInvocationHandler(Connection delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||||
|
if("commit".equals( method.getName() )) {
|
||||||
|
if ( transactionFailureTrigger.get() ) {
|
||||||
|
throw new PersistenceException( COMMIT_FAILURE );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if("rollback".equals( method.getName() )) {
|
||||||
|
if ( transactionFailureTrigger.get() ) {
|
||||||
|
transactionFailureTrigger.set( false );
|
||||||
|
throw new PersistenceException( "Rollback failed!" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return method.invoke(delegate, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue