Fix null embeddable with circular reference
This commit is contained in:
parent
b520752c8d
commit
a771d035c9
|
@ -8,6 +8,7 @@ package org.hibernate.sql.results.graph.embeddable;
|
||||||
|
|
||||||
import java.util.IdentityHashMap;
|
import java.util.IdentityHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
|
@ -30,6 +31,7 @@ import org.hibernate.sql.results.graph.collection.CollectionInitializer;
|
||||||
import org.hibernate.sql.results.graph.entity.AbstractEntityInitializer;
|
import org.hibernate.sql.results.graph.entity.AbstractEntityInitializer;
|
||||||
import org.hibernate.sql.results.graph.entity.EntityInitializer;
|
import org.hibernate.sql.results.graph.entity.EntityInitializer;
|
||||||
import org.hibernate.sql.results.internal.NullValueAssembler;
|
import org.hibernate.sql.results.internal.NullValueAssembler;
|
||||||
|
import org.hibernate.sql.results.internal.domain.CircularBiDirectionalFetchImpl;
|
||||||
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
|
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
|
||||||
import org.hibernate.type.descriptor.java.spi.EntityJavaTypeDescriptor;
|
import org.hibernate.type.descriptor.java.spi.EntityJavaTypeDescriptor;
|
||||||
|
|
||||||
|
@ -196,14 +198,17 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
|
||||||
);
|
);
|
||||||
|
|
||||||
boolean areAllValuesNull = true;
|
boolean areAllValuesNull = true;
|
||||||
for ( Map.Entry<StateArrayContributorMapping, DomainResultAssembler> entry : assemblerMap.entrySet() ) {
|
final Set<Map.Entry<StateArrayContributorMapping, DomainResultAssembler>> entries = assemblerMap.entrySet();
|
||||||
final Object contributorValue = entry.getValue().assemble(
|
final int size = entries.size();
|
||||||
|
for ( Map.Entry<StateArrayContributorMapping, DomainResultAssembler> entry : entries ) {
|
||||||
|
final DomainResultAssembler value = entry.getValue();
|
||||||
|
final Object contributorValue = value.assemble(
|
||||||
rowProcessingState,
|
rowProcessingState,
|
||||||
rowProcessingState.getJdbcValuesSourceProcessingState().getProcessingOptions()
|
rowProcessingState.getJdbcValuesSourceProcessingState().getProcessingOptions()
|
||||||
);
|
);
|
||||||
|
|
||||||
resolvedValues[ entry.getKey().getStateArrayPosition() ] = contributorValue;
|
resolvedValues[entry.getKey().getStateArrayPosition()] = contributorValue;
|
||||||
if ( contributorValue != null ) {
|
if ( contributorValue != null && ( !( value instanceof CircularBiDirectionalFetchImpl.CircularFetchAssembler ) || size == 1 ) ) {
|
||||||
areAllValuesNull = false;
|
areAllValuesNull = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,7 +174,7 @@ public class CircularBiDirectionalFetchImpl implements BiDirectionalFetch, Assoc
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class CircularFetchAssembler implements DomainResultAssembler {
|
public static class CircularFetchAssembler implements DomainResultAssembler {
|
||||||
private final NavigablePath circularPath;
|
private final NavigablePath circularPath;
|
||||||
private final JavaType javaTypeDescriptor;
|
private final JavaType javaTypeDescriptor;
|
||||||
private final ToOneAttributeMapping fetchable;
|
private final ToOneAttributeMapping fetchable;
|
||||||
|
|
|
@ -0,0 +1,225 @@
|
||||||
|
/*
|
||||||
|
* 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.annotations.derivedidentities.e1.b2;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import jakarta.persistence.CascadeType;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.FetchType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.NamedQueries;
|
||||||
|
import jakarta.persistence.NamedQuery;
|
||||||
|
import jakarta.persistence.OneToMany;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import jakarta.persistence.Temporal;
|
||||||
|
import jakarta.persistence.TemporalType;
|
||||||
|
import jakarta.persistence.Version;
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name = Customer.QUERY_ALL,
|
||||||
|
query = "select a from Customer a"),
|
||||||
|
@NamedQuery(name = Customer.QUERY_COUNT,
|
||||||
|
query = "select COUNT(a) from Customer a"),
|
||||||
|
@NamedQuery(name = Customer.QUERY_BY_CREDIT,
|
||||||
|
query = "SELECT c.id FROM Customer c WHERE c.creditLimit > :limit")
|
||||||
|
})
|
||||||
|
@Entity
|
||||||
|
@Table(name = "O_CUSTOMER")
|
||||||
|
public class Customer implements Serializable {
|
||||||
|
public static final String QUERY_ALL = "Customer.selectAll";
|
||||||
|
public static final String QUERY_COUNT = "Customer.count";
|
||||||
|
public static final String QUERY_BY_CREDIT = "Customer.selectByCreditLimit";
|
||||||
|
|
||||||
|
public static final String BAD_CREDIT = "BC";
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(name = "C_ID")
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
@Column(name = "C_FIRST")
|
||||||
|
private String firstName;
|
||||||
|
|
||||||
|
@Column(name = "C_LAST")
|
||||||
|
private String lastName;
|
||||||
|
|
||||||
|
@Column(name = "C_CONTACT")
|
||||||
|
private String contact;
|
||||||
|
|
||||||
|
@Column(name = "C_CREDIT")
|
||||||
|
private String credit;
|
||||||
|
|
||||||
|
@Column(name = "C_CREDIT_LIMIT")
|
||||||
|
private BigDecimal creditLimit;
|
||||||
|
|
||||||
|
@Column(name = "C_SINCE")
|
||||||
|
@Temporal(TemporalType.DATE)
|
||||||
|
private Calendar since;
|
||||||
|
|
||||||
|
@Column(name = "C_BALANCE")
|
||||||
|
private BigDecimal balance;
|
||||||
|
|
||||||
|
@Column(name = "C_YTD_PAYMENT")
|
||||||
|
private BigDecimal ytdPayment;
|
||||||
|
|
||||||
|
@OneToMany(targetEntity = CustomerInventory.class, mappedBy = "customer", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||||
|
private List<CustomerInventory> customerInventories;
|
||||||
|
|
||||||
|
@Version
|
||||||
|
@Column(name = "C_VERSION")
|
||||||
|
private int version;
|
||||||
|
|
||||||
|
protected Customer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Customer(
|
||||||
|
String first,
|
||||||
|
String last,
|
||||||
|
String contact,
|
||||||
|
String credit,
|
||||||
|
BigDecimal creditLimit,
|
||||||
|
BigDecimal balance,
|
||||||
|
BigDecimal YtdPayment) {
|
||||||
|
this.firstName = first;
|
||||||
|
this.lastName = last;
|
||||||
|
this.contact = contact;
|
||||||
|
this.since = Calendar.getInstance();
|
||||||
|
this.credit = credit;
|
||||||
|
this.creditLimit = creditLimit;
|
||||||
|
this.balance = balance;
|
||||||
|
this.ytdPayment = YtdPayment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer customerId) {
|
||||||
|
this.id = customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
return firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstName(String firstName) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastName(String lastName) {
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContact() {
|
||||||
|
return contact;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContact(String contact) {
|
||||||
|
this.contact = contact;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCredit() {
|
||||||
|
return credit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCredit(String credit) {
|
||||||
|
this.credit = credit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getCreditLimit() {
|
||||||
|
return creditLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreditLimit(BigDecimal creditLimit) {
|
||||||
|
this.creditLimit = creditLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Calendar getSince() {
|
||||||
|
return since;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSince(Calendar since) {
|
||||||
|
this.since = since;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getBalance() {
|
||||||
|
return balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBalance(BigDecimal balance) {
|
||||||
|
this.balance = balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void changeBalance(BigDecimal change) {
|
||||||
|
setBalance( balance.add( change ).setScale( 2, BigDecimal.ROUND_DOWN ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getYtdPayment() {
|
||||||
|
return ytdPayment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setYtdPayment(BigDecimal ytdPayment) {
|
||||||
|
this.ytdPayment = ytdPayment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<CustomerInventory> getInventories() {
|
||||||
|
if ( customerInventories == null ) {
|
||||||
|
customerInventories = new ArrayList<CustomerInventory>();
|
||||||
|
}
|
||||||
|
return customerInventories;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomerInventory addInventory(
|
||||||
|
Item item, int quantity,
|
||||||
|
BigDecimal totalValue) {
|
||||||
|
|
||||||
|
CustomerInventory inventory = new CustomerInventory( this, item, quantity, totalValue );
|
||||||
|
getInventories().add( inventory );
|
||||||
|
return inventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasSufficientCredit(BigDecimal amount) {
|
||||||
|
return !BAD_CREDIT.equals( getCredit() )
|
||||||
|
&& creditLimit != null
|
||||||
|
&& creditLimit.compareTo( amount ) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if ( this == o ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( o == null || getClass() != o.getClass() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return id == ( (Customer) o ).id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return new Integer( id ).hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.getFirstName() + " " + this.getLastName();
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +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.test.annotations.derivedidentities.e1.b2;
|
package org.hibernate.orm.test.annotations.derivedidentities.e1.b2;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
|
@ -4,7 +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.test.annotations.derivedidentities.e1.b2;
|
package org.hibernate.orm.test.annotations.derivedidentities.e1.b2;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
/*
|
||||||
|
* 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.annotations.derivedidentities.e1.b2;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A test.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:stale.pedersen@jboss.org">Stale W. Pedersen</a>
|
||||||
|
*/
|
||||||
|
@DomainModel(
|
||||||
|
annotatedClasses = {
|
||||||
|
Customer.class,
|
||||||
|
CustomerInventory.class,
|
||||||
|
CustomerInventoryPK.class,
|
||||||
|
Item.class
|
||||||
|
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@SessionFactory
|
||||||
|
public class IdClassGeneratedValueManyToOneTest {
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown(SessionFactoryScope scope){
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.createQuery( "delete from CustomerInventory" ).executeUpdate();
|
||||||
|
session.createQuery( "delete from Item" ).executeUpdate();
|
||||||
|
session.createQuery( "delete from Customer" ).executeUpdate();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testComplexIdClass(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
Customer c1 = new Customer(
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
"contact1",
|
||||||
|
"100",
|
||||||
|
new BigDecimal( 1000 ),
|
||||||
|
new BigDecimal( 1000 ),
|
||||||
|
new BigDecimal( 1000 )
|
||||||
|
);
|
||||||
|
session.persist( c1 );
|
||||||
|
session.flush();
|
||||||
|
session.clear();
|
||||||
|
|
||||||
|
Item boat = new Item();
|
||||||
|
boat.setId( "1" );
|
||||||
|
boat.setName( "cruiser" );
|
||||||
|
boat.setPrice( new BigDecimal( 500 ) );
|
||||||
|
boat.setDescription( "a boat" );
|
||||||
|
boat.setCategory( 42 );
|
||||||
|
|
||||||
|
session.persist( boat );
|
||||||
|
session.flush();
|
||||||
|
session.clear();
|
||||||
|
|
||||||
|
c1.addInventory( boat, 10, new BigDecimal( 5000 ) );
|
||||||
|
session.merge( c1 );
|
||||||
|
session.flush();
|
||||||
|
session.clear();
|
||||||
|
|
||||||
|
Customer c12 = (Customer) session.createQuery( "select c from Customer c" ).uniqueResult();
|
||||||
|
|
||||||
|
List<CustomerInventory> inventory = c12.getInventories();
|
||||||
|
|
||||||
|
assertEquals( 1, inventory.size() );
|
||||||
|
assertEquals( 10, inventory.get( 0 ).getQuantity() );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNullEmbedded(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
Customer c1 = new Customer(
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
"contact1",
|
||||||
|
"100",
|
||||||
|
new BigDecimal( 1000 ),
|
||||||
|
new BigDecimal( 1000 ),
|
||||||
|
new BigDecimal( 1000 )
|
||||||
|
);
|
||||||
|
session.persist( c1 );
|
||||||
|
session.flush();
|
||||||
|
session.clear();
|
||||||
|
|
||||||
|
final Customer customer = session.find( Customer.class, c1.getId() );
|
||||||
|
|
||||||
|
assertTrue( customer.getInventories().isEmpty() );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
* 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.test.annotations.derivedidentities.e1.b2;
|
package org.hibernate.orm.test.annotations.derivedidentities.e1.b2;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
|
@ -6,18 +6,23 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.idclass;
|
package org.hibernate.test.idclass;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
import static org.hibernate.orm.test.util.SchemaUtil.getColumnNames;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.hibernate.boot.spi.MetadataImplementor;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.IdClass;
|
import jakarta.persistence.IdClass;
|
||||||
import jakarta.persistence.ManyToOne;
|
import jakarta.persistence.ManyToOne;
|
||||||
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
import static org.hibernate.orm.test.util.SchemaUtil.getColumnNames;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that bootstrap doesn't throw an exception
|
* Test that bootstrap doesn't throw an exception
|
||||||
|
@ -27,29 +32,33 @@ import org.junit.Test;
|
||||||
* This test used to fail on bootstrap with the following error:
|
* This test used to fail on bootstrap with the following error:
|
||||||
* <p>
|
* <p>
|
||||||
* org.hibernate.MappingException: identifier mapping has wrong number of columns: org.hibernate.test.idclass.IdClassForNestedIdWithAssociationTest$NestedIdClassEntity type: component[idClassEntity,key3]
|
* org.hibernate.MappingException: identifier mapping has wrong number of columns: org.hibernate.test.idclass.IdClassForNestedIdWithAssociationTest$NestedIdClassEntity type: component[idClassEntity,key3]
|
||||||
* at org.hibernate.mapping.RootClass.validate(RootClass.java:273)
|
* at org.hibernate.mapping.RootClass.validate(RootClass.java:273)
|
||||||
* at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:359)
|
* at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:359)
|
||||||
* at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:307)
|
* at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:307)
|
||||||
* at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:471)
|
* at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:471)
|
||||||
* at org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase.buildResources(BaseNonConfigCoreFunctionalTestCase.java:165)
|
* at org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase.buildResources(BaseNonConfigCoreFunctionalTestCase.java:165)
|
||||||
* at org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase.startUp(BaseNonConfigCoreFunctionalTestCase.java:141)
|
* at org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase.startUp(BaseNonConfigCoreFunctionalTestCase.java:141)
|
||||||
* at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
|
* at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
|
||||||
* at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
|
* at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
|
||||||
* at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
|
* at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
|
||||||
* at java.base/java.lang.reflect.Method.invoke(Method.java:566)
|
* at java.base/java.lang.reflect.Method.invoke(Method.java:566)
|
||||||
* at org.hibernate.testing.junit4.TestClassMetadata.performCallbackInvocation(TestClassMetadata.java:205)
|
* at org.hibernate.testing.junit4.TestClassMetadata.performCallbackInvocation(TestClassMetadata.java:205)
|
||||||
*/
|
*/
|
||||||
|
@DomainModel(
|
||||||
|
annotatedClasses = {
|
||||||
|
IdClassForNestedIdWithAssociationTest.BasicEntity.class,
|
||||||
|
IdClassForNestedIdWithAssociationTest.IdClassEntity.class,
|
||||||
|
IdClassForNestedIdWithAssociationTest.NestedIdClassEntity.class
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@SessionFactory
|
||||||
@TestForIssue(jiraKey = "HHH-14918")
|
@TestForIssue(jiraKey = "HHH-14918")
|
||||||
public class IdClassForNestedIdWithAssociationTest extends BaseNonConfigCoreFunctionalTestCase {
|
public class IdClassForNestedIdWithAssociationTest {
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
|
||||||
return new Class[] { BasicEntity.class, IdClassEntity.class, NestedIdClassEntity.class };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void metadataTest() {
|
public void metadataTest(SessionFactoryScope scope) {
|
||||||
assertThat( getColumnNames( "NestedIdClassEntity", metadata() ) )
|
final MetadataImplementor metadata = scope.getMetadataImplementor();
|
||||||
|
assertThat( getColumnNames( "NestedIdClassEntity", metadata ) )
|
||||||
// Just check we're using copied IDs; otherwise the test wouldn't be able to reproduce HHH-14918.
|
// Just check we're using copied IDs; otherwise the test wouldn't be able to reproduce HHH-14918.
|
||||||
.containsExactlyInAnyOrder( "idClassEntity_basicEntity_key1", "idClassEntity_key2", "key3" );
|
.containsExactlyInAnyOrder( "idClassEntity_basicEntity_key1", "idClassEntity_key2", "key3" );
|
||||||
}
|
}
|
||||||
|
@ -58,8 +67,8 @@ public class IdClassForNestedIdWithAssociationTest extends BaseNonConfigCoreFunc
|
||||||
// but it feels wrong to have a test class with just an empty test method,
|
// but it feels wrong to have a test class with just an empty test method,
|
||||||
// so just check that persisting/loading works correctly.
|
// so just check that persisting/loading works correctly.
|
||||||
@Test
|
@Test
|
||||||
public void smokeTest() {
|
public void smokeTest(SessionFactoryScope scope) {
|
||||||
inTransaction( s -> {
|
scope.inTransaction( s -> {
|
||||||
BasicEntity basic = new BasicEntity( 1L );
|
BasicEntity basic = new BasicEntity( 1L );
|
||||||
s.persist( basic );
|
s.persist( basic );
|
||||||
IdClassEntity idClass = new IdClassEntity( basic, 2L );
|
IdClassEntity idClass = new IdClassEntity( basic, 2L );
|
||||||
|
@ -68,7 +77,7 @@ public class IdClassForNestedIdWithAssociationTest extends BaseNonConfigCoreFunc
|
||||||
s.persist( nestedIdClass );
|
s.persist( nestedIdClass );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
inTransaction( s -> {
|
scope.inTransaction( s -> {
|
||||||
NestedIdClassEntity nestedIdClass = s.get(
|
NestedIdClassEntity nestedIdClass = s.get(
|
||||||
NestedIdClassEntity.class,
|
NestedIdClassEntity.class,
|
||||||
new NestedIdClassEntity.NestedIdClassEntityId( 1L, 2L, 3L )
|
new NestedIdClassEntity.NestedIdClassEntityId( 1L, 2L, 3L )
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* 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.mapping;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.mapping.Table;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Column aliases utilize {@link Table#getUniqueInteger()} for naming. The
|
||||||
|
* unique integer used to be statically generated by the Table class, meaning
|
||||||
|
* it was dependent on mapping order. HHH-2448 made the alias names
|
||||||
|
* deterministic by having Configuration determine the unique integers on its
|
||||||
|
* second pass over the Tables tree map. AliasTest and
|
||||||
|
* {@link MappingReorderedAliasTest} ensure that the unique integers are the
|
||||||
|
* same, regardless of mapping ordering.
|
||||||
|
*
|
||||||
|
* @author Brett Meyer
|
||||||
|
*/
|
||||||
|
@DomainModel(
|
||||||
|
annotatedClasses = { Table1.class, Table2.class, ConfEntity.class, UserConfEntity.class, UserEntity.class }
|
||||||
|
)
|
||||||
|
@SessionFactory
|
||||||
|
public class AliasTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Column aliases utilize {@link Table#getUniqueInteger()} for naming. The unique integer used to be statically
|
||||||
|
* generated by the Table class, meaning it was dependent on mapping order. HHH-2448 made the alias names
|
||||||
|
* deterministic by having Configuration determine the unique integers on its second pass over the Tables tree map.
|
||||||
|
* AliasTest and {@link MappingReorderedAliasTest} ensure that the unique integers are the same, regardless of
|
||||||
|
* mapping ordering.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@TestForIssue(jiraKey = "HHH-2448")
|
||||||
|
public void testAliasOrdering(SessionFactoryScope scope) {
|
||||||
|
Iterator<Table> tables = scope.getMetadataImplementor().collectTableMappings().iterator();
|
||||||
|
Table table1 = null;
|
||||||
|
Table table2 = null;
|
||||||
|
while ( tables.hasNext() ) {
|
||||||
|
Table table = tables.next();
|
||||||
|
if ( table.getName().equals( "Table1" ) ) {
|
||||||
|
table1 = table;
|
||||||
|
}
|
||||||
|
else if ( table.getName().equals( "Table2" ) ) {
|
||||||
|
table2 = table;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue( table1.getUniqueInteger() < table2.getUniqueInteger() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue(jiraKey = "HHH-8371")
|
||||||
|
public final void testUnderscoreInColumnName(SessionFactoryScope scope) {
|
||||||
|
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
UserEntity user = new UserEntity();
|
||||||
|
user.setName( "foo" );
|
||||||
|
session.persist( user );
|
||||||
|
final ConfEntity conf = new ConfEntity();
|
||||||
|
conf.setConfKey( "counter" );
|
||||||
|
conf.setConfValue( "3" );
|
||||||
|
final UserConfEntity uc = new UserConfEntity();
|
||||||
|
uc.setUser( user );
|
||||||
|
uc.setConf( conf );
|
||||||
|
conf.getUserConf().add( uc );
|
||||||
|
session.persist( conf );
|
||||||
|
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.clear();
|
||||||
|
|
||||||
|
session.getTransaction().begin();
|
||||||
|
user = session.get( UserEntity.class, user.getId() );
|
||||||
|
|
||||||
|
try {
|
||||||
|
session.flush();
|
||||||
|
}
|
||||||
|
catch (HibernateException e) {
|
||||||
|
// original issue from HHH-8371
|
||||||
|
fail( "The explicit column name's underscore(s) were not considered during alias creation." );
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNotNull( user );
|
||||||
|
assertEquals( "foo", user.getName() );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,13 +6,13 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.mapping;
|
package org.hibernate.test.mapping;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Brett Meyer
|
* @author Brett Meyer
|
||||||
*/
|
*/
|
||||||
|
@DomainModel(
|
||||||
|
annotatedClasses = { Table2.class, Table1.class, ConfEntity.class, UserConfEntity.class, UserEntity.class }
|
||||||
|
)
|
||||||
public class MappingReorderedAliasTest extends AliasTest {
|
public class MappingReorderedAliasTest extends AliasTest {
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
|
||||||
return new Class<?>[] { Table2.class, Table1.class, ConfEntity.class, UserConfEntity.class, UserEntity.class };
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -5,7 +5,6 @@
|
||||||
* 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.orm.test.mapping;
|
package org.hibernate.orm.test.mapping;
|
||||||
|
|
||||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
|
|
|
@ -1,218 +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.test.annotations.derivedidentities.e1.b2;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.List;
|
|
||||||
import jakarta.persistence.CascadeType;
|
|
||||||
import jakarta.persistence.Column;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.FetchType;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.persistence.NamedQueries;
|
|
||||||
import jakarta.persistence.NamedQuery;
|
|
||||||
import jakarta.persistence.OneToMany;
|
|
||||||
import jakarta.persistence.Table;
|
|
||||||
import jakarta.persistence.Temporal;
|
|
||||||
import jakarta.persistence.TemporalType;
|
|
||||||
import jakarta.persistence.Version;
|
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
|
||||||
@NamedQueries({
|
|
||||||
@NamedQuery(name=Customer.QUERY_ALL,
|
|
||||||
query="select a from Customer a"),
|
|
||||||
@NamedQuery(name=Customer.QUERY_COUNT,
|
|
||||||
query="select COUNT(a) from Customer a"),
|
|
||||||
@NamedQuery(name=Customer.QUERY_BY_CREDIT,
|
|
||||||
query="SELECT c.id FROM Customer c WHERE c.creditLimit > :limit")
|
|
||||||
})
|
|
||||||
@Entity
|
|
||||||
@Table(name="O_CUSTOMER")
|
|
||||||
public class Customer implements Serializable {
|
|
||||||
public static final String QUERY_ALL = "Customer.selectAll";
|
|
||||||
public static final String QUERY_COUNT = "Customer.count";
|
|
||||||
public static final String QUERY_BY_CREDIT = "Customer.selectByCreditLimit";
|
|
||||||
|
|
||||||
public static final String BAD_CREDIT = "BC";
|
|
||||||
|
|
||||||
@Id
|
|
||||||
@Column(name="C_ID")
|
|
||||||
private int id;
|
|
||||||
|
|
||||||
@Column(name="C_FIRST")
|
|
||||||
private String firstName;
|
|
||||||
|
|
||||||
@Column(name="C_LAST")
|
|
||||||
private String lastName;
|
|
||||||
|
|
||||||
@Column(name="C_CONTACT")
|
|
||||||
private String contact;
|
|
||||||
|
|
||||||
@Column(name="C_CREDIT")
|
|
||||||
private String credit;
|
|
||||||
|
|
||||||
@Column(name="C_CREDIT_LIMIT")
|
|
||||||
private BigDecimal creditLimit;
|
|
||||||
|
|
||||||
@Column(name="C_SINCE")
|
|
||||||
@Temporal(TemporalType.DATE)
|
|
||||||
private Calendar since;
|
|
||||||
|
|
||||||
@Column(name="C_BALANCE")
|
|
||||||
private BigDecimal balance;
|
|
||||||
|
|
||||||
@Column(name="C_YTD_PAYMENT")
|
|
||||||
private BigDecimal ytdPayment;
|
|
||||||
|
|
||||||
@OneToMany(targetEntity=CustomerInventory.class, mappedBy="customer", cascade=CascadeType.ALL, fetch=FetchType.EAGER)
|
|
||||||
private List<CustomerInventory> customerInventories;
|
|
||||||
|
|
||||||
|
|
||||||
@Version
|
|
||||||
@Column(name = "C_VERSION")
|
|
||||||
private int version;
|
|
||||||
|
|
||||||
protected Customer() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public Customer(String first, String last,
|
|
||||||
String contact, String credit, BigDecimal creditLimit,
|
|
||||||
BigDecimal balance, BigDecimal YtdPayment) {
|
|
||||||
|
|
||||||
this.firstName = first;
|
|
||||||
this.lastName = last;
|
|
||||||
this.contact = contact;
|
|
||||||
this.since = Calendar.getInstance();
|
|
||||||
this.credit = credit;
|
|
||||||
this.creditLimit = creditLimit;
|
|
||||||
this.balance = balance;
|
|
||||||
this.ytdPayment = YtdPayment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(Integer customerId) {
|
|
||||||
this.id = customerId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFirstName() {
|
|
||||||
return firstName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFirstName(String firstName) {
|
|
||||||
this.firstName = firstName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLastName() {
|
|
||||||
return lastName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLastName(String lastName) {
|
|
||||||
this.lastName = lastName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getContact() {
|
|
||||||
return contact;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setContact(String contact) {
|
|
||||||
this.contact = contact;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCredit() {
|
|
||||||
return credit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCredit(String credit) {
|
|
||||||
this.credit = credit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getCreditLimit() {
|
|
||||||
return creditLimit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCreditLimit(BigDecimal creditLimit) {
|
|
||||||
this.creditLimit = creditLimit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Calendar getSince() {
|
|
||||||
return since;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSince(Calendar since) {
|
|
||||||
this.since = since;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getBalance() {
|
|
||||||
return balance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBalance(BigDecimal balance) {
|
|
||||||
this.balance = balance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void changeBalance(BigDecimal change) {
|
|
||||||
setBalance(balance.add(change).setScale(2, BigDecimal.ROUND_DOWN));
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getYtdPayment() {
|
|
||||||
return ytdPayment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setYtdPayment(BigDecimal ytdPayment) {
|
|
||||||
this.ytdPayment = ytdPayment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<CustomerInventory> getInventories() {
|
|
||||||
if (customerInventories == null){
|
|
||||||
customerInventories = new ArrayList<CustomerInventory>();
|
|
||||||
}
|
|
||||||
return customerInventories;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CustomerInventory addInventory(Item item, int quantity,
|
|
||||||
BigDecimal totalValue) {
|
|
||||||
|
|
||||||
CustomerInventory inventory = new CustomerInventory(this, item,
|
|
||||||
quantity, totalValue);
|
|
||||||
getInventories().add(inventory);
|
|
||||||
return inventory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getVersion() {
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasSufficientCredit(BigDecimal amount) {
|
|
||||||
return !BAD_CREDIT.equals(getCredit())
|
|
||||||
&& creditLimit != null
|
|
||||||
&& creditLimit.compareTo(amount) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o)
|
|
||||||
return true;
|
|
||||||
if (o == null || getClass() != o.getClass())
|
|
||||||
return false;
|
|
||||||
return id == ((Customer) o).id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return new Integer(id).hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return this.getFirstName() + " " + this.getLastName();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,84 +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.test.annotations.derivedidentities.e1.b2;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import org.hibernate.Session;
|
|
||||||
import org.hibernate.Transaction;
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A test.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:stale.pedersen@jboss.org">Stale W. Pedersen</a>
|
|
||||||
*/
|
|
||||||
public class IdClassGeneratedValueManyToOneTest extends BaseCoreFunctionalTestCase {
|
|
||||||
@Test
|
|
||||||
public void testComplexIdClass() {
|
|
||||||
Session s = openSession();
|
|
||||||
Transaction tx = s.beginTransaction();
|
|
||||||
|
|
||||||
Customer c1 = new Customer(
|
|
||||||
"foo", "bar", "contact1", "100", new BigDecimal( 1000 ), new BigDecimal( 1000 ), new BigDecimal( 1000 ));
|
|
||||||
s.persist( c1 );
|
|
||||||
s.flush();
|
|
||||||
s.clear();
|
|
||||||
|
|
||||||
// why does this cause a failure?
|
|
||||||
// Customer c2 = new Customer(
|
|
||||||
// "foo1", "bar1", "contact2", "200", new BigDecimal( 2000 ), new BigDecimal( 2000 ), new BigDecimal( 2000 ));
|
|
||||||
// s.persist( c2 );
|
|
||||||
// s.flush();
|
|
||||||
// s.clear();
|
|
||||||
|
|
||||||
Item boat = new Item();
|
|
||||||
boat.setId( "1" );
|
|
||||||
boat.setName( "cruiser" );
|
|
||||||
boat.setPrice( new BigDecimal( 500 ) );
|
|
||||||
boat.setDescription( "a boat" );
|
|
||||||
boat.setCategory( 42 );
|
|
||||||
|
|
||||||
s.persist( boat );
|
|
||||||
s.flush();
|
|
||||||
s.clear();
|
|
||||||
|
|
||||||
c1.addInventory( boat, 10, new BigDecimal( 5000 ) );
|
|
||||||
s.merge( c1 );
|
|
||||||
s.flush();
|
|
||||||
s.clear();
|
|
||||||
|
|
||||||
Customer c12 = ( Customer ) s.createQuery( "select c from Customer c" ).uniqueResult();
|
|
||||||
|
|
||||||
List<CustomerInventory> inventory = c12.getInventories();
|
|
||||||
|
|
||||||
assertEquals( 1, inventory.size() );
|
|
||||||
assertEquals( 10, inventory.get( 0 ).getQuantity() );
|
|
||||||
|
|
||||||
tx.rollback();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
assertTrue( true );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class[] getAnnotatedClasses() {
|
|
||||||
return new Class[] {
|
|
||||||
Customer.class,
|
|
||||||
CustomerInventory.class,
|
|
||||||
CustomerInventoryPK.class,
|
|
||||||
Item.class
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,106 +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.test.mapping;
|
|
||||||
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
|
||||||
import org.hibernate.Session;
|
|
||||||
import org.hibernate.mapping.Table;
|
|
||||||
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
|
||||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Column aliases utilize {@link Table#getUniqueInteger()} for naming. The
|
|
||||||
* unique integer used to be statically generated by the Table class, meaning
|
|
||||||
* it was dependent on mapping order. HHH-2448 made the alias names
|
|
||||||
* deterministic by having Configuration determine the unique integers on its
|
|
||||||
* second pass over the Tables tree map. AliasTest and
|
|
||||||
* {@link MappingReorderedAliasTest} ensure that the unique integers are the
|
|
||||||
* same, regardless of mapping ordering.
|
|
||||||
*
|
|
||||||
* @author Brett Meyer
|
|
||||||
*/
|
|
||||||
public class AliasTest extends BaseNonConfigCoreFunctionalTestCase {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Column aliases utilize {@link Table#getUniqueInteger()} for naming. The unique integer used to be statically
|
|
||||||
* generated by the Table class, meaning it was dependent on mapping order. HHH-2448 made the alias names
|
|
||||||
* deterministic by having Configuration determine the unique integers on its second pass over the Tables tree map.
|
|
||||||
* AliasTest and {@link MappingReorderedAliasTest} ensure that the unique integers are the same, regardless of
|
|
||||||
* mapping ordering.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
@TestForIssue( jiraKey = "HHH-2448" )
|
|
||||||
public void testAliasOrdering() {
|
|
||||||
Iterator<Table> tables = metadata().collectTableMappings().iterator();
|
|
||||||
Table table1 = null;
|
|
||||||
Table table2 = null;
|
|
||||||
while ( tables.hasNext() ) {
|
|
||||||
Table table = tables.next();
|
|
||||||
if ( table.getName().equals( "Table1" ) ) {
|
|
||||||
table1 = table;
|
|
||||||
}
|
|
||||||
else if ( table.getName().equals( "Table2" ) ) {
|
|
||||||
table2 = table;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assertTrue( table1.getUniqueInteger() < table2.getUniqueInteger() );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestForIssue( jiraKey = "HHH-8371" )
|
|
||||||
public final void testUnderscoreInColumnName() throws Throwable {
|
|
||||||
final Session s = openSession();
|
|
||||||
s.getTransaction().begin();
|
|
||||||
|
|
||||||
UserEntity user = new UserEntity();
|
|
||||||
user.setName( "foo" );
|
|
||||||
s.persist(user);
|
|
||||||
final ConfEntity conf = new ConfEntity();
|
|
||||||
conf.setConfKey("counter");
|
|
||||||
conf.setConfValue("3");
|
|
||||||
final UserConfEntity uc = new UserConfEntity();
|
|
||||||
uc.setUser(user);
|
|
||||||
uc.setConf(conf);
|
|
||||||
conf.getUserConf().add(uc);
|
|
||||||
s.persist(conf);
|
|
||||||
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.clear();
|
|
||||||
|
|
||||||
s.getTransaction().begin();
|
|
||||||
user = (UserEntity) s.get(UserEntity.class, user.getId());
|
|
||||||
|
|
||||||
try {
|
|
||||||
s.flush();
|
|
||||||
}
|
|
||||||
catch ( HibernateException e ) {
|
|
||||||
// original issue from HHH-8371
|
|
||||||
fail( "The explicit column name's underscore(s) were not considered during alias creation." );
|
|
||||||
}
|
|
||||||
|
|
||||||
assertNotNull( user );
|
|
||||||
assertEquals( user.getName(), "foo" );
|
|
||||||
|
|
||||||
s.getTransaction().commit();
|
|
||||||
s.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
|
||||||
return new Class<?>[] { Table1.class, Table2.class, ConfEntity.class, UserConfEntity.class, UserEntity.class };
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue