mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-18 17:15:02 +00:00
HHH-12738 - Session/EntityManager is closed in ForeignGenerator (JTA setup)
Add test case proving the issue does not replicate for either RESOURCE_LOCAL or JTA transactions
This commit is contained in:
parent
163cab99e2
commit
b3e0d363bd
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* 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.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
|
||||||
|
*/
|
||||||
|
@TestForIssue(jiraKey = "HHH-12738")
|
||||||
|
public class ForeignGeneratorJtaTest extends ForeignGeneratorResourceLocalTest {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addConfigOptions(Map options) {
|
||||||
|
TestingJtaBootstrap.prepare( options );
|
||||||
|
options.put( Environment.TRANSACTION_COORDINATOR_STRATEGY, "jta" );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,310 @@
|
|||||||
|
/*
|
||||||
|
* 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.test.idgen.foreign;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
|
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.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
@TestForIssue( jiraKey = "HHH-12738" )
|
||||||
|
public class ForeignGeneratorResourceLocalTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class[] {
|
||||||
|
Contract.class,
|
||||||
|
Customer.class,
|
||||||
|
CustomerContractRelation.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void addRelationImplicitFlush() 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();
|
||||||
|
} );
|
||||||
|
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
|
||||||
|
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 );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void addRelationExplicitFlush() 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();
|
||||||
|
} );
|
||||||
|
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
|
||||||
|
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 );
|
||||||
|
|
||||||
|
entityManager.flush();
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void addRelationImplicitFlushOneTx() throws Exception {
|
||||||
|
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
Contract contract = new Contract();
|
||||||
|
|
||||||
|
entityManager.persist( contract );
|
||||||
|
|
||||||
|
Customer customer = new Customer();
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
CustomerContractRelation relation = new CustomerContractRelation();
|
||||||
|
relation.setContractId( customer.getId() );
|
||||||
|
customer.addContractRelation( relation );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Contract")
|
||||||
|
@Table(name = "CONTRACT")
|
||||||
|
public static class Contract {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = 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<CustomerContractRelation> contractRelations = new HashSet<>();
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<CustomerContractRelation> getContractRelations() {
|
||||||
|
return contractRelations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean addContractRelation(CustomerContractRelation relation) {
|
||||||
|
if ( relation != null ) {
|
||||||
|
relation.setCustomer( this );
|
||||||
|
return contractRelations.add( relation );
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
public static class CustomerContractId implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1115591676841551563L;
|
||||||
|
|
||||||
|
@Column(name = "CUSTOMERID", nullable = false)
|
||||||
|
private Long customerId;
|
||||||
|
|
||||||
|
@Column(name = "CONTRACTID", nullable = false)
|
||||||
|
private Long contractId;
|
||||||
|
|
||||||
|
public Long getCustomerId() {
|
||||||
|
return customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomerId(Long customerId) {
|
||||||
|
this.customerId = customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getContractId() {
|
||||||
|
return contractId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContractId(Long contractId) {
|
||||||
|
this.contractId = contractId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ( ( contractId == null ) ? 0 : contractId.hashCode() );
|
||||||
|
result = prime * result + ( ( customerId == null ) ? 0 : customerId.hashCode() );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if ( this == obj ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( obj == null ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( getClass() != obj.getClass() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
CustomerContractId other = (CustomerContractId) obj;
|
||||||
|
if ( contractId == null ) {
|
||||||
|
if ( other.contractId != null ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( !contractId.equals( other.contractId ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( customerId == null ) {
|
||||||
|
if ( other.customerId != null ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( !customerId.equals( other.customerId ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "CustomerContractRelation")
|
||||||
|
@Table(name = "CUSTOMER_CONTRACT_RELATION")
|
||||||
|
public static class CustomerContractRelation {
|
||||||
|
@EmbeddedId
|
||||||
|
private final CustomerContractId id = new CustomerContractId();
|
||||||
|
|
||||||
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
|
@Column(nullable = true, name = "SIGNEDONDATE")
|
||||||
|
private Date signedOn;
|
||||||
|
|
||||||
|
@MapsId(value = "customerId")
|
||||||
|
@JoinColumn(name = "CUSTOMERID", nullable = false)
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
private Customer customer;
|
||||||
|
|
||||||
|
public CustomerContractId getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Customer getCustomer() {
|
||||||
|
return customer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomer(Customer customer) {
|
||||||
|
this.customer = customer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getSignedOn() {
|
||||||
|
return signedOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSignedOn(Date signedOn) {
|
||||||
|
this.signedOn = signedOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getCustomerId() {
|
||||||
|
return id.getCustomerId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomerId(Long customerId) {
|
||||||
|
id.setCustomerId( customerId );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getContractId() {
|
||||||
|
return id.getContractId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContractId(Long contractId) {
|
||||||
|
id.setContractId( contractId );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user