HHH-14503 - Migration of tests from jpa/test to orm/test/jpa

Signed-off-by: Jan Schatteman <jschatte@redhat.com>
This commit is contained in:
Jan Schatteman 2021-04-27 19:17:52 +02:00 committed by Andrea Boriero
parent 9bbad43e75
commit 4a59e2d002
14 changed files with 516 additions and 519 deletions

View File

@ -1,85 +0,0 @@
/*
* 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.util.List;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.orm.test.jpa.transaction.SynchronizationTypeTest;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.Jpa;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
/**
* @author Andrea Boriero
*/
@Jpa(
annotatedClasses = { JtaReusingEntityTransactionTest.TestEntity.class },
integrationSettings = {
@Setting(name = org.hibernate.jpa.AvailableSettings.TRANSACTION_TYPE, value = "JTA"),
@Setting(name = org.hibernate.cfg.AvailableSettings.CONNECTION_PROVIDER, value = "org.hibernate.testing.jta.JtaAwareConnectionProviderImpl"),
},
nonStringValueSettingProviders = { SynchronizationTypeTest.JtaPlatformNonStringValueSettingProvider.class }
)
public class JtaReusingEntityTransactionTest {
@Test
public void entityTransactionShouldBeReusableTest(EntityManagerFactoryScope scope) {
EntityManager em = createEntityManager( scope );
EntityTransaction transaction = null;
try {
transaction = em.getTransaction();
em.persist( new TestEntity() );
transaction.begin();
transaction.commit();
transaction.begin();
em.persist( new TestEntity() );
transaction.commit();
}
finally {
if ( transaction != null && transaction.isActive() ) {
transaction.rollback();
}
em.close();
}
em = createEntityManager( scope );
try {
transaction = em.getTransaction();
transaction.begin();
List<TestEntity> results = em.createQuery( "from TestEntity" ).getResultList();
assertThat( results.size(), is( 2 ) );
transaction.commit();
}
finally {
if ( transaction != null && transaction.isActive() ) {
transaction.rollback();
}
em.close();
}
}
private EntityManager createEntityManager(EntityManagerFactoryScope scope) {
return scope.getEntityManagerFactory().createEntityManager();
}
@Entity(name = "TestEntity")
public static class TestEntity {
@Id
@GeneratedValue
private Long id;
}
}

View File

@ -1,158 +0,0 @@
/*
* 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 javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.Id;
import javax.persistence.Version;
import org.hibernate.Session;
import org.hibernate.engine.transaction.spi.TransactionObserver;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.resource.jdbc.spi.JdbcSessionOwner;
import org.hibernate.testing.TestForIssue;
import org.junit.Test;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
/**
* @author Andrea Boriero
*/
public class TransactionRollbackTest extends BaseEntityManagerFunctionalTestCase {
@Override
public Class[] getAnnotatedClasses() {
return new Class[] {
Shipment.class
};
}
@Test
@TestForIssue( jiraKey = "HHH-11407")
public void checkRollBackTransactionIsExecutedOnceWhenACommitFails() throws Exception {
EntityManager em = createEntityManager();
try {
final Session session = em.unwrap( Session.class );
final OperationCollectorObserver transactionObserver = new OperationCollectorObserver();
( (JdbcSessionOwner) session ).getTransactionCoordinator().addObserver( transactionObserver );
em.getTransaction().begin();
// given two inserted records
em.persist( new Shipment( "shipment-1", "INITIAL" ) );
em.persist( new Shipment( "shipment-2", "INITIAL" ) );
em.flush();
em.clear();
try {
// when provoking a duplicate-key exception
em.persist( new Shipment( "shipment-1", "INITIAL" ) );
em.getTransaction().commit();
fail( "Expected exception was not raised" );
}
catch (Exception e) {
// Nothing to do
}
assertThat( transactionObserver.getUnSuccessfulAfterCompletion(), is( 1 ) );
em.clear();
em.getTransaction().begin();
Shipment shipment = em.find( Shipment.class, "shipment-1" );
if ( shipment != null ) {
em.remove( shipment );
}
shipment = em.find( Shipment.class, "shipment-2" );
if ( shipment != null ) {
em.remove( shipment );
}
em.getTransaction().commit();
}
finally {
em.close();
}
}
@Entity(name = "Shipment")
public class Shipment {
@Id
private String id;
@Version
private long version;
private String state;
Shipment() {
}
public Shipment(String id, String state) {
this.id = id;
this.state = state;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public long getVersion() {
return version;
}
public void setVersion(long version) {
this.version = version;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
private class OperationCollectorObserver implements TransactionObserver {
int unSuccessfulAfterCompletion;
@Override
public void afterBegin() {
// Nothing to do
}
@Override
public void beforeCompletion() {
// Nothing to do
}
@Override
public void afterCompletion(boolean successful, boolean delayed) {
if ( !successful ) {
unSuccessfulAfterCompletion++;
}
}
public int getUnSuccessfulAfterCompletion() {
return unSuccessfulAfterCompletion;
}
}
}

View File

@ -4,11 +4,10 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * 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; package org.hibernate.orm.test.jpa.transaction;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
import javax.persistence.Entity; import javax.persistence.Entity;
@ -26,44 +25,48 @@ import javax.transaction.Status;
import javax.transaction.TransactionManager; import javax.transaction.TransactionManager;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl; import org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl;
import org.hibernate.internal.SessionImpl; import org.hibernate.internal.SessionImpl;
import org.hibernate.jpa.AvailableSettings; import org.hibernate.jpa.test.transaction.Book;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.jta.TestingJtaBootstrap;
import org.hibernate.testing.jta.TestingJtaPlatformImpl; import org.hibernate.testing.jta.TestingJtaPlatformImpl;
import org.junit.After; import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.junit.Test; import org.hibernate.testing.orm.junit.Jpa;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is; import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.Assert.assertTrue;
/** /**
* @author Andrea Boriero * @author Andrea Boriero
*/ */
public class CloseEntityManagerWithActiveTransactionTest extends BaseEntityManagerFunctionalTestCase { @Jpa(
@Override annotatedClasses = {
protected void addConfigOptions(Map options) { Book.class,
super.addConfigOptions( options ); CloseEntityManagerWithActiveTransactionTest.Container.class,
TestingJtaBootstrap.prepare( options ); CloseEntityManagerWithActiveTransactionTest.Box.class,
options.put( AvailableSettings.TRANSACTION_TYPE, "JTA" ); CloseEntityManagerWithActiveTransactionTest.Muffin.class,
options.put( org.hibernate.cfg.AvailableSettings.JPA_TRANSACTION_COMPLIANCE, "true" ); CloseEntityManagerWithActiveTransactionTest.SmallBox.class
} },
integrationSettings = {
@Setting(name = AvailableSettings.CONNECTION_PROVIDER, value = "org.hibernate.testing.jta.JtaAwareConnectionProviderImpl"),
@Setting(name = AvailableSettings.JPA_TRANSACTION_TYPE, value = "JTA"),
@Setting(name = AvailableSettings.JPA_TRANSACTION_COMPLIANCE, value = "true")
},
nonStringValueSettingProviders = { JtaPlatformNonStringValueSettingProvider.class }
)
public class CloseEntityManagerWithActiveTransactionTest {
@Override @AfterEach
public Class[] getAnnotatedClasses() { public void tearDown(EntityManagerFactoryScope scope) throws Exception {
return new Class[] {
Book.class, Container.class, Box.class, Muffin.class, SmallBox.class
};
}
@After
public void tearDown() throws Exception {
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
EntityManager em = getOrCreateEntityManager(); EntityManager em = scope.getEntityManagerFactory().createEntityManager();
try { try {
em.createQuery( "delete from Muffin" ).executeUpdate(); em.createQuery( "delete from Muffin" ).executeUpdate();
em.createQuery( "delete from Box" ).executeUpdate(); em.createQuery( "delete from Box" ).executeUpdate();
@ -71,8 +74,8 @@ public class CloseEntityManagerWithActiveTransactionTest extends BaseEntityManag
} }
catch (Exception e) { catch (Exception e) {
final TransactionManager transactionManager = TestingJtaPlatformImpl.INSTANCE.getTransactionManager(); final TransactionManager transactionManager = TestingJtaPlatformImpl.INSTANCE.getTransactionManager();
if ( transactionManager.getTransaction() != null && transactionManager.getTransaction() if ( transactionManager.getTransaction() != null &&
.getStatus() == Status.STATUS_ACTIVE ) { transactionManager.getTransaction().getStatus() == Status.STATUS_ACTIVE ) {
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().rollback(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().rollback();
} }
throw e; throw e;
@ -86,9 +89,9 @@ public class CloseEntityManagerWithActiveTransactionTest extends BaseEntityManag
@Test @Test
@TestForIssue(jiraKey = "HHH-10942") @TestForIssue(jiraKey = "HHH-10942")
public void testPersistThenCloseWithAnActiveTransaction() throws Exception { public void testPersistThenCloseWithAnActiveTransaction(EntityManagerFactoryScope scope) throws Exception {
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
EntityManager em = getOrCreateEntityManager(); EntityManager em = scope.getEntityManagerFactory().createEntityManager();
try { try {
Box box = new Box(); Box box = new Box();
box.setColor( "red-and-white" ); box.setColor( "red-and-white" );
@ -109,7 +112,7 @@ public class CloseEntityManagerWithActiveTransactionTest extends BaseEntityManag
em.close(); em.close();
} }
} }
em = getOrCreateEntityManager(); em = scope.getEntityManagerFactory().createEntityManager();
try { try {
final List results = em.createQuery( "from Box" ).getResultList(); final List results = em.createQuery( "from Box" ).getResultList();
assertThat( results.size(), is( 1 ) ); assertThat( results.size(), is( 1 ) );
@ -120,10 +123,10 @@ public class CloseEntityManagerWithActiveTransactionTest extends BaseEntityManag
} }
@Test @Test
@TestForIssue( jiraKey = "HHH-11166") @TestForIssue(jiraKey = "HHH-11166")
public void testMergeThenCloseWithAnActiveTransaction() throws Exception { public void testMergeThenCloseWithAnActiveTransaction(EntityManagerFactoryScope scope) throws Exception {
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
EntityManager em = getOrCreateEntityManager(); EntityManager em = scope.getEntityManagerFactory().createEntityManager();
try { try {
Box box = new Box(); Box box = new Box();
box.setColor( "red-and-white" ); box.setColor( "red-and-white" );
@ -132,7 +135,7 @@ public class CloseEntityManagerWithActiveTransactionTest extends BaseEntityManag
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit();
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
em = getOrCreateEntityManager(); em = scope.getEntityManagerFactory().createEntityManager();
Muffin muffin = new Muffin(); Muffin muffin = new Muffin();
muffin.setKind( "blueberry" ); muffin.setKind( "blueberry" );
@ -157,7 +160,7 @@ public class CloseEntityManagerWithActiveTransactionTest extends BaseEntityManag
em.close(); em.close();
} }
} }
em = getOrCreateEntityManager(); em = scope.getEntityManagerFactory().createEntityManager();
try { try {
final List<Box> boxes = em.createQuery( "from Box" ).getResultList(); final List<Box> boxes = em.createQuery( "from Box" ).getResultList();
assertThat( boxes.size(), is( 1 ) ); assertThat( boxes.size(), is( 1 ) );
@ -169,21 +172,21 @@ public class CloseEntityManagerWithActiveTransactionTest extends BaseEntityManag
} }
@Test @Test
@TestForIssue( jiraKey = "HHH-11269") @TestForIssue(jiraKey = "HHH-11269")
public void testMergeWithDeletionOrphanRemovalThenCloseWithAnActiveTransaction() throws Exception { public void testMergeWithDeletionOrphanRemovalThenCloseWithAnActiveTransaction(EntityManagerFactoryScope scope) throws Exception {
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
EntityManager em = getOrCreateEntityManager(); EntityManager em = scope.getEntityManagerFactory().createEntityManager();
try { try {
Muffin muffin = new Muffin(); Muffin muffin = new Muffin();
muffin.setKind( "blueberry" ); muffin.setKind( "blueberry" );
SmallBox box = new SmallBox(muffin); SmallBox box = new SmallBox( muffin );
box.setColor( "red-and-white" ); box.setColor( "red-and-white" );
em.persist( box ); em.persist( box );
em.close(); em.close();
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit();
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
em = getOrCreateEntityManager(); em = scope.getEntityManagerFactory().createEntityManager();
box.emptyBox(); box.emptyBox();
@ -206,11 +209,11 @@ public class CloseEntityManagerWithActiveTransactionTest extends BaseEntityManag
em.close(); em.close();
} }
} }
em = getOrCreateEntityManager(); em = scope.getEntityManagerFactory().createEntityManager();
try { try {
final List<SmallBox> boxes = em.createQuery( "from SmallBox" ).getResultList(); final List<SmallBox> boxes = em.createQuery( "from SmallBox" ).getResultList();
assertThat( boxes.size(), is( 1 ) ); assertThat( boxes.size(), is( 1 ) );
assertTrue( boxes.get( 0 ).isEmpty()); assertTrue( boxes.get( 0 ).isEmpty() );
} }
finally { finally {
em.close(); em.close();
@ -218,10 +221,10 @@ public class CloseEntityManagerWithActiveTransactionTest extends BaseEntityManag
} }
@Test @Test
@TestForIssue( jiraKey = "HHH-11166") @TestForIssue(jiraKey = "HHH-11166")
public void testUpdateThenCloseWithAnActiveTransaction() throws Exception { public void testUpdateThenCloseWithAnActiveTransaction(EntityManagerFactoryScope scope) throws Exception {
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
EntityManager em = getOrCreateEntityManager(); EntityManager em = scope.getEntityManagerFactory().createEntityManager();
try { try {
Box box = new Box(); Box box = new Box();
box.setColor( "red-and-white" ); box.setColor( "red-and-white" );
@ -230,7 +233,7 @@ public class CloseEntityManagerWithActiveTransactionTest extends BaseEntityManag
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit();
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
em = getOrCreateEntityManager(); em = scope.getEntityManagerFactory().createEntityManager();
box = em.find( Box.class, box.getId() ); box = em.find( Box.class, box.getId() );
Muffin muffin = new Muffin(); Muffin muffin = new Muffin();
muffin.setKind( "blueberry" ); muffin.setKind( "blueberry" );
@ -252,7 +255,7 @@ public class CloseEntityManagerWithActiveTransactionTest extends BaseEntityManag
em.close(); em.close();
} }
} }
em = getOrCreateEntityManager(); em = scope.getEntityManagerFactory().createEntityManager();
try { try {
final List<Box> boxes = em.createQuery( "from Box" ).getResultList(); final List<Box> boxes = em.createQuery( "from Box" ).getResultList();
assertThat( boxes.size(), is( 1 ) ); assertThat( boxes.size(), is( 1 ) );
@ -264,10 +267,10 @@ public class CloseEntityManagerWithActiveTransactionTest extends BaseEntityManag
} }
@Test @Test
@TestForIssue( jiraKey = "HHH-11166") @TestForIssue(jiraKey = "HHH-11166")
public void testRemoveThenCloseWithAnActiveTransaction() throws Exception { public void testRemoveThenCloseWithAnActiveTransaction(EntityManagerFactoryScope scope) throws Exception {
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
EntityManager em = getOrCreateEntityManager(); EntityManager em = scope.getEntityManagerFactory().createEntityManager();
try { try {
Box box = new Box(); Box box = new Box();
box.setColor( "red-and-white" ); box.setColor( "red-and-white" );
@ -279,7 +282,7 @@ public class CloseEntityManagerWithActiveTransactionTest extends BaseEntityManag
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit();
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
em = getOrCreateEntityManager(); em = scope.getEntityManagerFactory().createEntityManager();
box = em.find( Box.class, box.getId() ); box = em.find( Box.class, box.getId() );
em.remove( box ); em.remove( box );
@ -299,7 +302,7 @@ public class CloseEntityManagerWithActiveTransactionTest extends BaseEntityManag
em.close(); em.close();
} }
} }
em = getOrCreateEntityManager(); em = scope.getEntityManagerFactory().createEntityManager();
try { try {
final List<Box> boxes = em.createQuery( "from Box" ).getResultList(); final List<Box> boxes = em.createQuery( "from Box" ).getResultList();
assertThat( boxes.size(), is( 0 ) ); assertThat( boxes.size(), is( 0 ) );
@ -311,9 +314,9 @@ public class CloseEntityManagerWithActiveTransactionTest extends BaseEntityManag
@Test @Test
@TestForIssue(jiraKey = "HHH-11099") @TestForIssue(jiraKey = "HHH-11099")
public void testCommitReleasesLogicalConnection() throws Exception { public void testCommitReleasesLogicalConnection(EntityManagerFactoryScope scope) throws Exception {
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
EntityManager em = getOrCreateEntityManager(); EntityManager em = scope.getEntityManagerFactory().createEntityManager();
try { try {
Box box = new Box(); Box box = new Box();
box.setColor( "red-and-white" ); box.setColor( "red-and-white" );
@ -396,30 +399,30 @@ public class CloseEntityManagerWithActiveTransactionTest extends BaseEntityManag
@Entity(name = "SmallBox") @Entity(name = "SmallBox")
public static class SmallBox extends Container { public static class SmallBox extends Container {
@OneToOne(cascade = {CascadeType.MERGE, @OneToOne(cascade = {
CascadeType.MERGE,
CascadeType.REMOVE, CascadeType.REMOVE,
CascadeType.REFRESH, CascadeType.REFRESH,
CascadeType.PERSIST CascadeType.PERSIST
}, orphanRemoval = true) }, orphanRemoval = true)
private Muffin muffin; private Muffin muffin;
public SmallBox(){} public SmallBox() {
}
public SmallBox(Muffin muffin) { public SmallBox(Muffin muffin) {
this.muffin = muffin; this.muffin = muffin;
} }
public void emptyBox(){ public void emptyBox() {
muffin = null; muffin = null;
} }
public boolean isEmpty(){ public boolean isEmpty() {
return muffin == null; return muffin == null;
} }
} }
@Entity(name = "Muffin") @Entity(name = "Muffin")
public static class Muffin { public static class Muffin {
@ -447,10 +450,4 @@ public class CloseEntityManagerWithActiveTransactionTest extends BaseEntityManag
this.kind = kind; this.kind = kind;
} }
} }
@FunctionalInterface
public interface Action{
void execute();
}
} }

View File

@ -6,7 +6,6 @@
*/ */
package org.hibernate.orm.test.jpa.transaction; package org.hibernate.orm.test.jpa.transaction;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction; import javax.persistence.EntityTransaction;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
@ -14,9 +13,9 @@ import org.hibernate.testing.orm.junit.Jpa;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.Assert.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.Assert.assertSame; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.jupiter.api.Assertions.assertSame;
/** /**
* @author Andrea Boriero * @author Andrea Boriero

View File

@ -8,8 +8,7 @@ package org.hibernate.orm.test.jpa.transaction;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import org.hibernate.jpa.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.jpa.test.transaction.Book;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
@ -24,11 +23,11 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
*/ */
@Jpa( @Jpa(
integrationSettings = { integrationSettings = {
@Setting(name = AvailableSettings.TRANSACTION_TYPE, value = "JTA"), @Setting(name = AvailableSettings.JPA_TRANSACTION_TYPE, value = "JTA"),
@Setting(name = org.hibernate.cfg.AvailableSettings.CONNECTION_PROVIDER, value = "org.hibernate.testing.jta.JtaAwareConnectionProviderImpl"), @Setting(name = org.hibernate.cfg.AvailableSettings.CONNECTION_PROVIDER, value = "org.hibernate.testing.jta.JtaAwareConnectionProviderImpl"),
@Setting( name = org.hibernate.cfg.AvailableSettings.JPA_TRANSACTION_COMPLIANCE, value = "true") @Setting( name = org.hibernate.cfg.AvailableSettings.JPA_TRANSACTION_COMPLIANCE, value = "true")
}, },
nonStringValueSettingProviders = { SynchronizationTypeTest.JtaPlatformNonStringValueSettingProvider.class } nonStringValueSettingProviders = { JtaPlatformNonStringValueSettingProvider.class }
) )
public class JtaGetTransactionThrowsExceptionTest { public class JtaGetTransactionThrowsExceptionTest {

View File

@ -0,0 +1,27 @@
/*
* 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.orm.test.jpa.transaction;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.testing.jta.TestingJtaPlatformImpl;
import org.hibernate.testing.orm.jpa.NonStringValueSettingProvider;
/**
* @author Jan Schatteman
*/
public class JtaPlatformNonStringValueSettingProvider extends NonStringValueSettingProvider {
@Override
public String getKey() {
return AvailableSettings.JTA_PLATFORM;
}
@Override
public Object getValue() {
return TestingJtaPlatformImpl.INSTANCE;
}
}

View File

@ -0,0 +1,73 @@
/*
* 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.orm.test.jpa.transaction;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.EntityTransaction;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.Jpa;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.Test;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author Andrea Boriero
*/
@Jpa(
annotatedClasses = { JtaReusingEntityTransactionTest.TestEntity.class },
integrationSettings = {
@Setting(name = org.hibernate.cfg.AvailableSettings.CONNECTION_PROVIDER, value = "org.hibernate.testing.jta.JtaAwareConnectionProviderImpl"),
@Setting(name = org.hibernate.cfg.AvailableSettings.JPA_TRANSACTION_TYPE, value = "JTA")
},
nonStringValueSettingProviders = { JtaPlatformNonStringValueSettingProvider.class }
)
public class JtaReusingEntityTransactionTest {
@Test
public void entityTransactionShouldBeReusableTest(EntityManagerFactoryScope scope) {
scope.inEntityManager(
entityManager -> {
EntityTransaction transaction = null;
try {
transaction = entityManager.getTransaction();
entityManager.persist( new TestEntity() );
transaction.begin();
transaction.commit();
transaction.begin();
entityManager.persist( new TestEntity() );
transaction.commit();
}
finally {
if ( transaction != null && transaction.isActive() ) {
transaction.rollback();
}
}
}
);
scope.inTransaction(
entityManager -> {
List<TestEntity> results = entityManager.createQuery( "from TestEntity" ).getResultList();
assertThat( results.size(), is( 2 ) );
}
);
}
@Entity(name = "TestEntity")
public static class TestEntity {
@Id
@GeneratedValue
private Long id;
}
}

View File

@ -15,15 +15,13 @@ import javax.persistence.criteria.CriteriaUpdate;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper; import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
import org.hibernate.jpa.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.jpa.test.transaction.Book; import org.hibernate.jpa.test.transaction.Book;
import org.hibernate.jpa.test.transaction.Book_; import org.hibernate.jpa.test.transaction.Book_;
import org.hibernate.jpa.test.transaction.TransactionJoiningTest;
import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl; import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.jta.TestingJtaPlatformImpl; import org.hibernate.testing.jta.TestingJtaPlatformImpl;
import org.hibernate.testing.orm.jpa.NonStringValueSettingProvider;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.ExtraAssertions; import org.hibernate.testing.orm.junit.ExtraAssertions;
import org.hibernate.testing.orm.junit.Jpa; import org.hibernate.testing.orm.junit.Jpa;
@ -46,26 +44,14 @@ import static org.junit.jupiter.api.Assertions.fail;
@Jpa( @Jpa(
annotatedClasses = { Book.class }, annotatedClasses = { Book.class },
integrationSettings = { integrationSettings = {
@Setting(name = AvailableSettings.TRANSACTION_TYPE, value = "JTA"), @Setting(name = AvailableSettings.JPA_TRANSACTION_TYPE, value = "JTA"),
@Setting(name = org.hibernate.cfg.AvailableSettings.CONNECTION_PROVIDER, value = "org.hibernate.testing.jta.JtaAwareConnectionProviderImpl"), @Setting(name = org.hibernate.cfg.AvailableSettings.CONNECTION_PROVIDER, value = "org.hibernate.testing.jta.JtaAwareConnectionProviderImpl"),
}, },
nonStringValueSettingProviders = { SynchronizationTypeTest.JtaPlatformNonStringValueSettingProvider.class } nonStringValueSettingProviders = { JtaPlatformNonStringValueSettingProvider.class }
) )
public class SynchronizationTypeTest { public class SynchronizationTypeTest {
public static class JtaPlatformNonStringValueSettingProvider extends NonStringValueSettingProvider {
@Override
public String getKey() {
return org.hibernate.cfg.AvailableSettings.JTA_PLATFORM;
}
@Override
public Object getValue() {
return TestingJtaPlatformImpl.INSTANCE;
}
}
@Test @Test
public void testUnSynchronizedExplicitJoinHandling(EntityManagerFactoryScope scope) throws Exception { public void testUnSynchronizedExplicitJoinHandling(EntityManagerFactoryScope scope) throws Exception {

View File

@ -4,9 +4,8 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * 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; package org.hibernate.orm.test.jpa.transaction;
import java.util.Map;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.PersistenceException; import javax.persistence.PersistenceException;
@ -18,67 +17,81 @@ import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper; import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
import org.hibernate.internal.SessionImpl; import org.hibernate.internal.SessionImpl;
import org.hibernate.jpa.AvailableSettings; import org.hibernate.jpa.test.transaction.Book;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.orm.test.jpa.transaction.TransactionJoinHandlingChecker;
import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl; import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.jta.TestingJtaBootstrap;
import org.hibernate.testing.jta.TestingJtaPlatformImpl; import org.hibernate.testing.jta.TestingJtaPlatformImpl;
import org.hibernate.testing.junit4.ExtraAssertions; import org.hibernate.testing.orm.junit.ExtraAssertions;
import org.junit.Test; import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.Jpa;
import org.hibernate.testing.orm.junit.Setting;
import static org.junit.Assert.assertFalse; import org.junit.jupiter.api.Test;
import static org.junit.Assert.assertTrue; import org.junit.jupiter.api.Assertions;
import static org.junit.Assert.fail;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
/** /**
* Largely a copy of {@link org.hibernate.test.jpa.txn.JtaTransactionJoiningTest} * Largely a copy of {@link org.hibernate.test.jpa.txn.JtaTransactionJoiningTest}
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class TransactionJoiningTest extends BaseEntityManagerFunctionalTestCase { @Jpa(
@Override annotatedClasses = {
protected void addConfigOptions(Map options) { Book.class
super.addConfigOptions( options ); },
TestingJtaBootstrap.prepare( options ); integrationSettings = {
options.put( AvailableSettings.TRANSACTION_TYPE, "JTA" ); @Setting(name = org.hibernate.cfg.AvailableSettings.CONNECTION_PROVIDER, value = "org.hibernate.testing.jta.JtaAwareConnectionProviderImpl"),
} @Setting(name = org.hibernate.cfg.AvailableSettings.JPA_TRANSACTION_TYPE, value = "JTA")
},
nonStringValueSettingProviders = { JtaPlatformNonStringValueSettingProvider.class }
)
public class TransactionJoiningTest {
@Test @Test
public void testExplicitJoining() throws Exception { public void testExplicitJoining(EntityManagerFactoryScope scope) throws Exception {
assertFalse( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) ); assertFalse( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) );
EntityManager entityManager = entityManagerFactory().createEntityManager( SynchronizationType.UNSYNCHRONIZED ); EntityManager entityManager = scope.getEntityManagerFactory()
TransactionJoinHandlingChecker.validateExplicitJoiningHandling( entityManager ); .createEntityManager( SynchronizationType.UNSYNCHRONIZED );
try {
TransactionJoinHandlingChecker.validateExplicitJoiningHandling( entityManager );
}
finally {
entityManager.close();
}
} }
@Test @Test
@SuppressWarnings("EmptyCatchBlock") public void testExplicitJoiningTransactionRequiredException(EntityManagerFactoryScope scope) {
public void testExplicitJoiningTransactionRequiredException() throws Exception {
// explicitly calling EntityManager#joinTransaction outside of an active transaction should cause // explicitly calling EntityManager#joinTransaction outside of an active transaction should cause
// a TransactionRequiredException to be thrown // a TransactionRequiredException to be thrown
EntityManager entityManager = entityManagerFactory().createEntityManager(); EntityManager entityManager = scope.getEntityManagerFactory().createEntityManager();
assertFalse("setup problem", JtaStatusHelper.isActive(TestingJtaPlatformImpl.INSTANCE.getTransactionManager())); assertFalse( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ), "setup problem" );
try { try {
entityManager.joinTransaction(); Assertions.assertThrows(
fail( "Expected joinTransaction() to fail since there is no active JTA transaction" ); TransactionRequiredException.class,
entityManager::joinTransaction,
"Expected joinTransaction() to fail since there is no active JTA transaction"
);
} }
catch (TransactionRequiredException expected) { finally {
entityManager.close();
} }
} }
@Test @Test
public void testImplicitJoining() throws Exception { public void testImplicitJoining(EntityManagerFactoryScope scope) throws Exception {
// here the transaction is started before the EM is opened... // here the transaction is started before the EM is opened...
assertFalse( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) ); assertFalse( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) );
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
EntityManager entityManager = entityManagerFactory().createEntityManager(); EntityManager entityManager = scope.getEntityManagerFactory().createEntityManager();
SharedSessionContractImplementor session = entityManager.unwrap( SharedSessionContractImplementor.class ); SharedSessionContractImplementor session = entityManager.unwrap( SharedSessionContractImplementor.class );
ExtraAssertions.assertTyping( JtaTransactionCoordinatorImpl.class, session.getTransactionCoordinator() ); ExtraAssertions.assertTyping( JtaTransactionCoordinatorImpl.class, session.getTransactionCoordinator() );
@ -101,11 +114,11 @@ public class TransactionJoiningTest extends BaseEntityManagerFunctionalTestCase
@Test @Test
@TestForIssue(jiraKey = "HHH-10807") @TestForIssue(jiraKey = "HHH-10807")
public void testIsJoinedAfterMarkedForRollbackImplict() throws Exception { public void testIsJoinedAfterMarkedForRollbackImplicit(EntityManagerFactoryScope scope) throws Exception {
assertFalse( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) ); assertFalse( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) );
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
EntityManager entityManager = entityManagerFactory().createEntityManager(); EntityManager entityManager = scope.getEntityManagerFactory().createEntityManager();
SharedSessionContractImplementor session = entityManager.unwrap( SharedSessionContractImplementor.class ); SharedSessionContractImplementor session = entityManager.unwrap( SharedSessionContractImplementor.class );
ExtraAssertions.assertTyping( JtaTransactionCoordinatorImpl.class, session.getTransactionCoordinator() ); ExtraAssertions.assertTyping( JtaTransactionCoordinatorImpl.class, session.getTransactionCoordinator() );
@ -123,20 +136,25 @@ public class TransactionJoiningTest extends BaseEntityManagerFunctionalTestCase
assertTrue( transactionCoordinator.isJoined() ); assertTrue( transactionCoordinator.isJoined() );
assertTrue( entityManager.isJoinedToTransaction() ); assertTrue( entityManager.isJoinedToTransaction() );
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().rollback(); try {
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().rollback();
entityManager.close(); entityManager.close();
assertFalse( entityManager.isOpen() ); assertFalse( entityManager.isOpen() );
assertFalse( session.isOpen() ); assertFalse( session.isOpen() );
}
finally {
// ensure the entityManager is closed in case the rollback call fails
entityManager.close();
}
} }
@Test @Test
@TestForIssue(jiraKey = "HHH-10807") @TestForIssue(jiraKey = "HHH-10807")
public void testIsJoinedAfterMarkedForRollbackExplicit() throws Exception { public void testIsJoinedAfterMarkedForRollbackExplicit(EntityManagerFactoryScope scope) throws Exception {
assertFalse( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) ); assertFalse( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) );
EntityManager entityManager = entityManagerFactory().createEntityManager( SynchronizationType.UNSYNCHRONIZED ); EntityManager entityManager = scope.getEntityManagerFactory().createEntityManager( SynchronizationType.UNSYNCHRONIZED );
SharedSessionContractImplementor session = entityManager.unwrap( SharedSessionContractImplementor.class ); SharedSessionContractImplementor session = entityManager.unwrap( SharedSessionContractImplementor.class );
assertTrue( entityManager.isOpen() ); assertTrue( entityManager.isOpen() );
assertTrue( session.isOpen() ); assertTrue( session.isOpen() );
@ -157,19 +175,25 @@ public class TransactionJoiningTest extends BaseEntityManagerFunctionalTestCase
assertTrue( transactionCoordinator.isJoined() ); assertTrue( transactionCoordinator.isJoined() );
assertTrue( entityManager.isJoinedToTransaction() ); assertTrue( entityManager.isJoinedToTransaction() );
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().rollback(); try {
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().rollback();
entityManager.close(); entityManager.close();
assertFalse( entityManager.isOpen() ); assertFalse( entityManager.isOpen() );
assertFalse( session.isOpen() ); assertFalse( session.isOpen() );
}
finally {
// ensure the entityManager is closed in case the rollback call fails
entityManager.close();
}
} }
@Test @Test
public void testCloseAfterCommit() throws Exception { public void testCloseAfterCommit(EntityManagerFactoryScope scope) throws Exception {
assertFalse( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) ); assertFalse( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) );
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
EntityManager entityManager = entityManagerFactory().createEntityManager(); EntityManager entityManager = scope.getEntityManagerFactory().createEntityManager();
SharedSessionContractImplementor session = entityManager.unwrap( SharedSessionContractImplementor.class ); SharedSessionContractImplementor session = entityManager.unwrap( SharedSessionContractImplementor.class );
ExtraAssertions.assertTyping( JtaTransactionCoordinatorImpl.class, session.getTransactionCoordinator() ); ExtraAssertions.assertTyping( JtaTransactionCoordinatorImpl.class, session.getTransactionCoordinator() );
@ -181,21 +205,27 @@ public class TransactionJoiningTest extends BaseEntityManagerFunctionalTestCase
assertTrue( entityManager.isOpen() ); assertTrue( entityManager.isOpen() );
assertTrue( session.isOpen() ); assertTrue( session.isOpen() );
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit(); try {
assertTrue( entityManager.isOpen() ); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit();
assertTrue( session.isOpen() ); assertTrue( entityManager.isOpen() );
assertTrue( session.isOpen() );
entityManager.close(); entityManager.close();
assertFalse( entityManager.isOpen() ); assertFalse( entityManager.isOpen() );
assertFalse( session.isOpen() ); assertFalse( session.isOpen() );
}
finally {
// ensure the entityManager is closed in case the commit call fails
entityManager.close();
}
} }
@Test @Test
public void testImplicitJoiningWithExtraSynchronization() throws Exception { public void testImplicitJoiningWithExtraSynchronization(EntityManagerFactoryScope scope) throws Exception {
assertFalse( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) ); assertFalse( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) );
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
EntityManager entityManager = entityManagerFactory().createEntityManager(); EntityManager entityManager = scope.getEntityManagerFactory().createEntityManager();
SharedSessionContractImplementor session = entityManager.unwrap( SharedSessionContractImplementor.class ); SharedSessionContractImplementor session = entityManager.unwrap( SharedSessionContractImplementor.class );
ExtraAssertions.assertTyping( JtaTransactionCoordinatorImpl.class, session.getTransactionCoordinator() ); ExtraAssertions.assertTyping( JtaTransactionCoordinatorImpl.class, session.getTransactionCoordinator() );
@ -209,7 +239,7 @@ public class TransactionJoiningTest extends BaseEntityManagerFunctionalTestCase
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit();
} }
/** /**
* In certain JTA environments (JBossTM, etc.), a background thread (reaper) * In certain JTA environments (JBossTM, etc.), a background thread (reaper)
* can rollback a transaction if it times out. These timeouts are rare and * can rollback a transaction if it times out. These timeouts are rare and
@ -220,55 +250,51 @@ public class TransactionJoiningTest extends BaseEntityManagerFunctionalTestCase
*/ */
@Test @Test
@TestForIssue(jiraKey = "HHH-7910") @TestForIssue(jiraKey = "HHH-7910")
public void testMultiThreadTransactionTimeout() throws Exception { public void testMultiThreadTransactionTimeout(EntityManagerFactoryScope scope) throws Exception {
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
EntityManager em = entityManagerFactory().createEntityManager(); EntityManager em = scope.getEntityManagerFactory().createEntityManager();
final SessionImpl sImpl = em.unwrap( SessionImpl.class ); try {
final SessionImpl sImpl = em.unwrap( SessionImpl.class );
final CountDownLatch latch = new CountDownLatch( 1 ); final CountDownLatch latch = new CountDownLatch( 1 );
Thread thread = new Thread() { Thread thread = new Thread( () -> {
public void run() { ( (JtaTransactionCoordinatorImpl) sImpl.getTransactionCoordinator() ).getSynchronizationCallbackCoordinator()
((JtaTransactionCoordinatorImpl)sImpl.getTransactionCoordinator()).getSynchronizationCallbackCoordinator()
.afterCompletion( Status.STATUS_ROLLEDBACK ); .afterCompletion( Status.STATUS_ROLLEDBACK );
latch.countDown(); latch.countDown();
} );
thread.start();
latch.await();
boolean caught = false;
try {
em.persist( new Book( "The Book of Foo", 1 ) );
} }
}; catch (PersistenceException e) {
thread.start(); caught = e.getCause().getClass().equals( HibernateException.class );
}
assertTrue( caught );
latch.await(); // Ensure that the connection was closed by the background thread.
caught = false;
try {
em.createQuery( "from Book" ).getResultList();
}
catch (PersistenceException e) {
// HHH-9312
caught = true;
}
catch (Exception e) {
caught = true;
}
assertTrue( caught );
boolean caught = false; TestingJtaPlatformImpl.INSTANCE.getTransactionManager().rollback();
try {
em.persist( new Book( "The Book of Foo", 1 ) );
} }
catch ( PersistenceException e ) { finally {
caught = e.getCause().getClass().equals( HibernateException.class ); em.close();
} }
assertTrue( caught );
// Ensure that the connection was closed by the background thread.
caught = false;
try {
em.createQuery( "from Book" ).getResultList();
}
catch ( PersistenceException e ) {
// HHH-9312
caught = true;
}catch (Exception e){
caught = true;
}
assertTrue( caught );
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().rollback();
em.close();
}
@Override
public Class[] getAnnotatedClasses() {
return new Class[] {
Book.class
};
} }
} }

View File

@ -0,0 +1,161 @@
/*
* 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.orm.test.jpa.transaction;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Version;
import org.hibernate.Session;
import org.hibernate.engine.transaction.spi.TransactionObserver;
import org.hibernate.resource.jdbc.spi.JdbcSessionOwner;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.Jpa;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author Andrea Boriero
*/
@Jpa(annotatedClasses = {
TransactionRollbackTest.Shipment.class
})
public class TransactionRollbackTest {
@AfterEach
public void tearDown(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
entityManager.createQuery( "delete from Shipment" ).executeUpdate();
}
);
}
@Test
@TestForIssue( jiraKey = "HHH-11407")
public void checkRollBackTransactionIsExecutedOnceWhenACommitFails(EntityManagerFactoryScope scope) {
scope.inEntityManager(
entityManager -> {
final Session session = entityManager.unwrap( Session.class );
final OperationCollectorObserver transactionObserver = new OperationCollectorObserver();
( (JdbcSessionOwner) session ).getTransactionCoordinator().addObserver( transactionObserver );
entityManager.getTransaction().begin();
// given two inserted records
entityManager.persist( new Shipment( "shipment-1", "INITIAL" ) );
entityManager.persist( new Shipment( "shipment-2", "INITIAL" ) );
entityManager.flush();
entityManager.clear();
Assertions.assertThrows(
Exception.class,
() -> {
// when provoking a duplicate-key exception
entityManager.persist( new Shipment( "shipment-1", "INITIAL" ) );
entityManager.getTransaction().commit();
},
"Expected exception was not raised"
);
assertThat( transactionObserver.getUnSuccessfulAfterCompletion(), is( 1 ) );
entityManager.clear();
entityManager.getTransaction().begin();
Shipment shipment = entityManager.find( Shipment.class, "shipment-1" );
if ( shipment != null ) {
entityManager.remove( shipment );
}
shipment = entityManager.find( Shipment.class, "shipment-2" );
if ( shipment != null ) {
entityManager.remove( shipment );
}
entityManager.getTransaction().commit();
}
);
}
@Entity(name = "Shipment")
public class Shipment {
@Id
private String id;
@Version
private long version;
private String state;
Shipment() {
}
public Shipment(String id, String state) {
this.id = id;
this.state = state;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public long getVersion() {
return version;
}
public void setVersion(long version) {
this.version = version;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
private class OperationCollectorObserver implements TransactionObserver {
int unSuccessfulAfterCompletion;
@Override
public void afterBegin() {
// Nothing to do
}
@Override
public void beforeCompletion() {
// Nothing to do
}
@Override
public void afterCompletion(boolean successful, boolean delayed) {
if ( !successful ) {
unSuccessfulAfterCompletion++;
}
}
public int getUnSuccessfulAfterCompletion() {
return unSuccessfulAfterCompletion;
}
}
}

View File

@ -4,25 +4,23 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * 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; package org.hibernate.orm.test.jpa.transaction;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.transaction.RollbackException; import javax.transaction.RollbackException;
import javax.transaction.Status; import javax.transaction.Status;
import javax.transaction.SystemException; import javax.transaction.SystemException;
import java.util.Map;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.jpa.AvailableSettings;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.junit.Ignore; import org.junit.jupiter.api.Test;
import org.junit.Test;
import org.hibernate.testing.jta.TestingJtaBootstrap;
import org.hibernate.testing.jta.TestingJtaPlatformImpl; import org.hibernate.testing.jta.TestingJtaPlatformImpl;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.Jpa;
import org.hibernate.testing.orm.junit.Setting;
import static org.junit.Assert.fail; import static org.junit.jupiter.api.Assertions.fail;
/** /**
* Recreate test failure that occurs when three threads share the same entity manager and * Recreate test failure that occurs when three threads share the same entity manager and
@ -30,18 +28,19 @@ import static org.junit.Assert.fail;
* *
* @author Scott Marlow * @author Scott Marlow
*/ */
public class TransactionRolledBackInDifferentThreadTest extends BaseEntityManagerFunctionalTestCase { @Jpa(
@Override integrationSettings = {
protected void addConfigOptions(Map options) { @Setting(name = org.hibernate.cfg.AvailableSettings.CONNECTION_PROVIDER, value = "org.hibernate.testing.jta.JtaAwareConnectionProviderImpl"),
super.addConfigOptions( options ); @Setting(name = org.hibernate.cfg.AvailableSettings.JPA_TRANSACTION_TYPE, value = "JTA")
TestingJtaBootstrap.prepare( options ); },
options.put( AvailableSettings.TRANSACTION_TYPE, "JTA" ); nonStringValueSettingProviders = { JtaPlatformNonStringValueSettingProvider.class }
} )
public class TransactionRolledBackInDifferentThreadTest {
@Test @Test
public void testTransactionRolledBackInDifferentThreadFailure() throws Exception { public void testTransactionRolledBackInDifferentThreadFailure(EntityManagerFactoryScope scope) throws Exception {
/** /*
* The three test threads share the same entity manager. * The three test threads share the same entity manager.
* The main test thread creates an EntityManager, joins it to the transaction and ends the transaction. * The main test thread creates an EntityManager, joins it to the transaction and ends the transaction.
* Test thread 1 joins the EntityManager to its transaction, sets rollbackonly and ends the transaction. * Test thread 1 joins the EntityManager to its transaction, sets rollbackonly and ends the transaction.
@ -51,18 +50,18 @@ public class TransactionRolledBackInDifferentThreadTest extends BaseEntityManage
// main test thread // main test thread
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
final EntityManager em = entityManagerFactory().createEntityManager(); final EntityManager em = scope.getEntityManagerFactory().createEntityManager();
em.joinTransaction(); em.joinTransaction();
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit();
// will be set to the failing exception try {
final HibernateException[] transactionRolledBackInDifferentThreadException = new HibernateException[2]; TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit();
transactionRolledBackInDifferentThreadException[0] = transactionRolledBackInDifferentThreadException[1] = null;
// background test thread 1 // will be set to the failing exception
final Runnable run1 = new Runnable() { final HibernateException[] transactionRolledBackInDifferentThreadException = new HibernateException[2];
@Override transactionRolledBackInDifferentThreadException[0] = transactionRolledBackInDifferentThreadException[1] = null;
public void run() {
// background test thread 1
final Runnable run1 = () -> {
try { try {
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
em.joinTransaction(); em.joinTransaction();
@ -72,7 +71,7 @@ public class TransactionRolledBackInDifferentThreadTest extends BaseEntityManage
catch (javax.persistence.PersistenceException e) { catch (javax.persistence.PersistenceException e) {
if ( e.getCause() instanceof HibernateException && if ( e.getCause() instanceof HibernateException &&
e.getCause().getMessage().equals( "Transaction was rolled back in a different thread!" ) ) { e.getCause().getMessage().equals( "Transaction was rolled back in a different thread!" ) ) {
/** /*
* Save the exception for the main test thread to fail * Save the exception for the main test thread to fail
*/ */
e.printStackTrace(); // show the error first e.printStackTrace(); // show the error first
@ -81,7 +80,6 @@ public class TransactionRolledBackInDifferentThreadTest extends BaseEntityManage
} }
catch (RollbackException ignored) { catch (RollbackException ignored) {
// expected to see RollbackException: ARJUNA016053: Could not commit transaction. // expected to see RollbackException: ARJUNA016053: Could not commit transaction.
} }
catch (Throwable throwable) { catch (Throwable throwable) {
throwable.printStackTrace(); throwable.printStackTrace();
@ -94,20 +92,15 @@ public class TransactionRolledBackInDifferentThreadTest extends BaseEntityManage
} }
} }
catch (SystemException ignore) { catch (SystemException ignore) {
} }
} }
};
} // test thread 2
}; final Runnable run2 = () -> {
// test thread 2
final Runnable run2 = new Runnable() {
@Override
public void run() {
try { try {
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
/** /*
* the following call to em.joinTransaction() will throw: * the following call to em.joinTransaction() will throw:
* org.hibernate.HibernateException: Transaction was rolled back in a different thread! * org.hibernate.HibernateException: Transaction was rolled back in a different thread!
*/ */
@ -117,7 +110,7 @@ public class TransactionRolledBackInDifferentThreadTest extends BaseEntityManage
catch (javax.persistence.PersistenceException e) { catch (javax.persistence.PersistenceException e) {
if ( e.getCause() instanceof HibernateException && if ( e.getCause() instanceof HibernateException &&
e.getCause().getMessage().equals( "Transaction was rolled back in a different thread!" ) ) { e.getCause().getMessage().equals( "Transaction was rolled back in a different thread!" ) ) {
/** /*
* Save the exception for the main test thread to fail * Save the exception for the main test thread to fail
*/ */
e.printStackTrace(); // show the error first e.printStackTrace(); // show the error first
@ -135,45 +128,36 @@ public class TransactionRolledBackInDifferentThreadTest extends BaseEntityManage
} }
} }
catch (SystemException ignore) { catch (SystemException ignore) {
} }
} }
};
Thread thread = new Thread( run1, "test thread1" );
thread.start();
thread.join();
Thread thread2 = new Thread( run2, "test thread2" );
thread2.start();
thread2.join();
// show failure for exception caught in run2.run()
if ( transactionRolledBackInDifferentThreadException[0] != null
|| transactionRolledBackInDifferentThreadException[1] != null )
{
fail(
"failure in test thread 1 = " +
( transactionRolledBackInDifferentThreadException[0] != null ?
transactionRolledBackInDifferentThreadException[0].getMessage() :
"(none)" )
+ ", failure in test thread 2 = " +
( transactionRolledBackInDifferentThreadException[1] != null ?
transactionRolledBackInDifferentThreadException[1].getMessage() :
"(none)" )
);
} }
};
Thread thread = new Thread( run1, "test thread1" );
thread.start();
thread.join();
Thread thread2 = new Thread( run2, "test thread2" );
thread2.start();
thread2.join();
// show failure for exception caught in run2.run()
if ( transactionRolledBackInDifferentThreadException[0] != null
|| transactionRolledBackInDifferentThreadException[1] != null )
{
fail(
"failure in test thread 1 = " +
( transactionRolledBackInDifferentThreadException[0] != null ?
transactionRolledBackInDifferentThreadException[0].getMessage() :
"(none)" )
+ ", failure in test thread 2 = " +
( transactionRolledBackInDifferentThreadException[1] != null ?
transactionRolledBackInDifferentThreadException[1].getMessage() :
"(none)" )
);
} }
finally {
em.close(); em.close();
} }
@Override
public Class[] getAnnotatedClasses() {
return new Class[] {
};
} }
} }

View File

@ -63,18 +63,6 @@ public abstract class AbstractJtaBatchTest {
} ); } );
} }
public static class JtaPlatformNonStringValueSettingProvider extends NonStringValueSettingProvider {
@Override
public String getKey() {
return AvailableSettings.JTA_PLATFORM;
}
@Override
public Object getValue() {
return TestingJtaPlatformImpl.INSTANCE;
}
}
public static class ConnectionNonStringValueSettingProvider extends NonStringValueSettingProvider { public static class ConnectionNonStringValueSettingProvider extends NonStringValueSettingProvider {
@Override @Override
public String getKey() { public String getKey() {

View File

@ -21,6 +21,7 @@ import org.hibernate.engine.jdbc.batch.internal.BatchingBatch;
import org.hibernate.engine.jdbc.batch.spi.Batch; import org.hibernate.engine.jdbc.batch.spi.Batch;
import org.hibernate.engine.jdbc.batch.spi.BatchKey; import org.hibernate.engine.jdbc.batch.spi.BatchKey;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator; import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.orm.test.jpa.transaction.JtaPlatformNonStringValueSettingProvider;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.jta.TestingJtaPlatformImpl; import org.hibernate.testing.jta.TestingJtaPlatformImpl;
@ -55,7 +56,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
@Setting(name = AvailableSettings.STATEMENT_BATCH_SIZE, value = "50") @Setting(name = AvailableSettings.STATEMENT_BATCH_SIZE, value = "50")
}, },
nonStringValueSettingProviders = { nonStringValueSettingProviders = {
AbstractJtaBatchTest.JtaPlatformNonStringValueSettingProvider.class, JtaPlatformNonStringValueSettingProvider.class,
AbstractJtaBatchTest.ConnectionNonStringValueSettingProvider.class, AbstractJtaBatchTest.ConnectionNonStringValueSettingProvider.class,
JtaWithFailingBatchTest.BatchBuilderNonStringValueSettingProvider.class JtaWithFailingBatchTest.BatchBuilderNonStringValueSettingProvider.class
} }

View File

@ -10,9 +10,7 @@ import java.sql.PreparedStatement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.persistence.FlushModeType; import javax.persistence.FlushModeType;
import javax.transaction.NotSupportedException;
import javax.transaction.Status; import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.transaction.TransactionManager; import javax.transaction.TransactionManager;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
@ -22,6 +20,7 @@ import org.hibernate.engine.jdbc.batch.internal.BatchingBatch;
import org.hibernate.engine.jdbc.batch.spi.Batch; import org.hibernate.engine.jdbc.batch.spi.Batch;
import org.hibernate.engine.jdbc.batch.spi.BatchKey; import org.hibernate.engine.jdbc.batch.spi.BatchKey;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator; import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.orm.test.jpa.transaction.JtaPlatformNonStringValueSettingProvider;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.jta.TestingJtaPlatformImpl; import org.hibernate.testing.jta.TestingJtaPlatformImpl;
@ -55,7 +54,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
@Setting(name = AvailableSettings.STATEMENT_BATCH_SIZE, value = "50") @Setting(name = AvailableSettings.STATEMENT_BATCH_SIZE, value = "50")
}, },
nonStringValueSettingProviders = { nonStringValueSettingProviders = {
AbstractJtaBatchTest.JtaPlatformNonStringValueSettingProvider.class, JtaPlatformNonStringValueSettingProvider.class,
AbstractJtaBatchTest.ConnectionNonStringValueSettingProvider.class, AbstractJtaBatchTest.ConnectionNonStringValueSettingProvider.class,
JtaWithStatementsBatchTest.BatchBuilderNonStringValueSettingProvider.class JtaWithStatementsBatchTest.BatchBuilderNonStringValueSettingProvider.class
} }