diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java index cb448cbe85..a0137ca0ee 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java @@ -2107,7 +2107,7 @@ public boolean contains(Object object) { @Override public boolean contains(String entityName, Object object) { - checkOpen(); + checkOpenOrWaitingForAutoClose(); checkTransactionSynchStatus(); if ( object == null ) { diff --git a/hibernate-core/src/test/java/org/hibernate/test/idgen/foreign/ForeignGeneratorJtaTest.java b/hibernate-core/src/test/java/org/hibernate/test/idgen/foreign/ForeignGeneratorJtaTest.java index ba9d9f539d..245272b3e2 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/idgen/foreign/ForeignGeneratorJtaTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/idgen/foreign/ForeignGeneratorJtaTest.java @@ -6,35 +6,12 @@ */ package org.hibernate.test.idgen.foreign; -import java.io.Serializable; -import java.util.Date; -import java.util.HashSet; import java.util.Map; -import java.util.Set; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Embeddable; -import javax.persistence.EmbeddedId; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.MapsId; -import javax.persistence.OneToMany; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; import org.hibernate.cfg.Environment; -import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.jta.TestingJtaBootstrap; -import org.junit.Test; - -import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; /** * @author Vlad Mihalcea diff --git a/hibernate-core/src/test/java/org/hibernate/test/idgen/foreign/ForeignGeneratorResourceLocalTest.java b/hibernate-core/src/test/java/org/hibernate/test/idgen/foreign/ForeignGeneratorResourceLocalTest.java index 929ba9347d..66c789583e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/idgen/foreign/ForeignGeneratorResourceLocalTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/idgen/foreign/ForeignGeneratorResourceLocalTest.java @@ -15,6 +15,8 @@ import javax.persistence.Embeddable; import javax.persistence.EmbeddedId; import javax.persistence.Entity; +import javax.persistence.EntityManager; +import javax.persistence.EntityTransaction; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; @@ -36,15 +38,15 @@ /** * @author Vlad Mihalcea */ -@TestForIssue( jiraKey = "HHH-12738" ) +@TestForIssue(jiraKey = "HHH-12738") public class ForeignGeneratorResourceLocalTest extends BaseEntityManagerFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { return new Class[] { - Contract.class, - Customer.class, - CustomerContractRelation.class + Contract.class, + Customer.class, + CustomerContractRelation.class }; } @@ -128,12 +130,12 @@ public void addRelationImplicitFlushOneTx() throws Exception { entityManager.persist( customer ); customer = entityManager.createQuery( - "SELECT c " + - "FROM Customer c " + - " LEFT JOIN FETCH c.contractRelations " + - " WHERE c.id = :customerId", Customer.class ) - .setParameter( "customerId", customer.getId() ) - .getSingleResult(); + "SELECT c " + + "FROM Customer c " + + " LEFT JOIN FETCH c.contractRelations " + + " WHERE c.id = :customerId", Customer.class ) + .setParameter( "customerId", customer.getId() ) + .getSingleResult(); CustomerContractRelation relation = new CustomerContractRelation(); relation.setContractId( customer.getId() ); @@ -141,6 +143,62 @@ public void addRelationImplicitFlushOneTx() throws Exception { } ); } + @Test + public void addRelationImplicitFlushCloseEntityManager() throws Exception { + + Long contractId = doInJPA( this::entityManagerFactory, entityManager -> { + Contract contract = new Contract(); + + entityManager.persist( contract ); + return contract.getId(); + } ); + + Long customerId = doInJPA( this::entityManagerFactory, entityManager -> { + Customer customer = new Customer(); + + entityManager.persist( customer ); + return customer.getId(); + } ); + + EntityManager entityManager = null; + EntityTransaction txn = null; + try { + entityManager = entityManagerFactory().createEntityManager(); + txn = entityManager.getTransaction(); + txn.begin(); + + Customer customer = entityManager.createQuery( + "SELECT c " + + "FROM Customer c " + + " LEFT JOIN FETCH c.contractRelations " + + " WHERE c.id = :customerId", Customer.class ) + .setParameter( "customerId", customerId ) + .getSingleResult(); + + CustomerContractRelation relation = new CustomerContractRelation(); + relation.setContractId( contractId ); + customer.addContractRelation( relation ); + + //Close the EntityManager + entityManager.close(); + + //And, afterward commit the currently running Tx. + //This might happen in JTA environments where the Tx is committed by the JTA TM. + txn.commit(); + } + catch (Throwable t) { + if ( txn != null && txn.isActive() ) { + try { + txn.rollback(); + } + catch (Exception e) { + log.error( "Rollback failure", e ); + } + } + throw t; + } + } + @Entity(name = "Contract") @Table(name = "CONTRACT") public static class Contract { @@ -160,13 +218,12 @@ public void setId(Long id) { @Entity(name = "Customer") @Table(name = "CUSTOMER") public static class Customer { - @Id - @GeneratedValue - private Long id; - @OneToMany(mappedBy = "customer", fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.MERGE }, orphanRemoval = true, targetEntity = CustomerContractRelation.class) private final Set contractRelations = new HashSet<>(); + @Id + @GeneratedValue + private Long id; public Long getId() { return id;