HHH-16040 New coercing assembler when types are different from expected

This commit is contained in:
Marco Belladelli 2023-01-25 18:26:52 +01:00 committed by Christian Beikov
parent 29077e67ab
commit 1064577687
17 changed files with 375 additions and 66 deletions

View File

@ -360,6 +360,7 @@ public class BasicAttributeMapping
// Lazy property. A valuesArrayPosition of -1 will lead to
// returning a domain result assembler that returns LazyPropertyInitializer.UNFETCHED_PROPERTY
final EntityMappingType containingEntityMapping = findContainingEntityMapping();
boolean coerceResultType = false;
if ( fetchTiming == FetchTiming.DELAYED
&& !( fetchParent instanceof EmbeddableResultGraphNode )
&& containingEntityMapping.getEntityPersister().getPropertyLaziness()[getStateArrayPosition()] ) {
@ -375,6 +376,10 @@ public class BasicAttributeMapping
final SqlSelection sqlSelection = resolveSqlSelection( fetchablePath, tableGroup, true, fetchParent, creationState );
valuesArrayPosition = sqlSelection.getValuesArrayPosition();
if ( sqlSelection.getExpressionType() != null) {
// if the expression type is different that the expected type coerce the value
coerceResultType = sqlSelection.getExpressionType().getSingleJdbcMapping().getJdbcJavaType() != getJdbcMapping().getJdbcJavaType();
}
}
return new BasicFetch<>(
@ -383,7 +388,8 @@ public class BasicAttributeMapping
fetchablePath,
this,
fetchTiming,
creationState
creationState,
coerceResultType
);
}

View File

@ -22,6 +22,7 @@ import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.metamodel.mapping.MappingType;
import org.hibernate.metamodel.mapping.SelectableConsumer;
import org.hibernate.metamodel.model.domain.NavigableRole;
@ -399,13 +400,16 @@ public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMa
assert tableGroup != null;
final SqlSelection sqlSelection = resolveSqlSelection( fetchablePath, tableGroup, false, fetchParent, creationState );
final JdbcMappingContainer selectionType = sqlSelection.getExpressionType();
return new BasicFetch<>(
sqlSelection.getValuesArrayPosition(),
fetchParent,
fetchablePath,
this,
FetchTiming.IMMEDIATE,
creationState
creationState,
// if the expression type is different that the expected type coerce the value
selectionType != null && selectionType.getSingleJdbcMapping().getJdbcJavaType() != getJdbcMapping().getJdbcJavaType()
);
}

View File

@ -22,6 +22,7 @@ import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.metamodel.mapping.ManagedMappingType;
import org.hibernate.metamodel.mapping.MappingType;
import org.hibernate.metamodel.mapping.ModelPart;
@ -316,17 +317,21 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
);
}
final JavaType<?> javaType = selectableMapping.getJdbcMapping().getJdbcJavaType();
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
sqlExpressionResolver.resolveSqlExpression( tableReference, selectableMapping ),
selectableMapping.getJdbcMapping().getJdbcJavaType(),
javaType,
fetchParent,
sqlAstCreationState.getCreationContext().getSessionFactory().getTypeConfiguration()
);
final JdbcMappingContainer selectionType = sqlSelection.getExpressionType();
return new BasicResult<>(
sqlSelection.getValuesArrayPosition(),
null,
selectableMapping.getJdbcMapping()
selectableMapping.getJdbcMapping(),
// if the expression type is different that the expected type coerce the value
selectionType != null && selectionType.getSingleJdbcMapping().getJdbcJavaType() != javaType
);
}

View File

@ -55,6 +55,28 @@ public class BasicFetch<T> implements Fetch, BasicResultGraphNode<T> {
);
}
public BasicFetch(
int valuesArrayPosition,
FetchParent fetchParent,
NavigablePath fetchablePath,
BasicValuedModelPart valuedMapping,
FetchTiming fetchTiming,
DomainResultCreationState creationState,
boolean coerceResultType) {
//noinspection unchecked
this(
valuesArrayPosition,
fetchParent,
fetchablePath,
valuedMapping,
(BasicValueConverter<T, ?>) valuedMapping.getJdbcMapping().getValueConverter(),
fetchTiming,
true,
creationState,
coerceResultType
);
}
public BasicFetch(
int valuesArrayPosition,
FetchParent fetchParent,
@ -84,6 +106,29 @@ public class BasicFetch<T> implements Fetch, BasicResultGraphNode<T> {
FetchTiming fetchTiming,
boolean canBasicPartFetchBeDelayed,
DomainResultCreationState creationState) {
this(
valuesArrayPosition,
fetchParent,
fetchablePath,
valuedMapping,
valueConverter,
fetchTiming,
canBasicPartFetchBeDelayed,
creationState,
false
);
}
public BasicFetch(
int valuesArrayPosition,
FetchParent fetchParent,
NavigablePath fetchablePath,
BasicValuedModelPart valuedMapping,
BasicValueConverter<T, ?> valueConverter,
FetchTiming fetchTiming,
boolean canBasicPartFetchBeDelayed,
DomainResultCreationState creationState,
boolean coerceResultType) {
this.navigablePath = fetchablePath;
this.fetchParent = fetchParent;
@ -100,11 +145,12 @@ public class BasicFetch<T> implements Fetch, BasicResultGraphNode<T> {
}
}
else {
this.assembler = new BasicResultAssembler<>(
valuesArrayPosition,
javaType,
valueConverter
);
if (coerceResultType) {
this.assembler = new CoercingResultAssembler<>( valuesArrayPosition, javaType, valueConverter );
}
else {
this.assembler = new BasicResultAssembler<>( valuesArrayPosition, javaType, valueConverter );
}
}
}

View File

@ -41,6 +41,22 @@ public class BasicResult<T> implements DomainResult<T>, BasicResultGraphNode<T>
);
}
public BasicResult(
int jdbcValuesArrayPosition,
String resultVariable,
JdbcMapping jdbcMapping,
boolean coerceResultType) {
//noinspection unchecked
this(
jdbcValuesArrayPosition,
resultVariable,
jdbcMapping.getJavaTypeDescriptor(),
jdbcMapping.getValueConverter(),
null,
coerceResultType
);
}
public BasicResult(
int jdbcValuesArrayPosition,
String resultVariable,
@ -85,11 +101,26 @@ public class BasicResult<T> implements DomainResult<T>, BasicResultGraphNode<T>
JavaType<T> javaType,
BasicValueConverter<T,?> valueConverter,
NavigablePath navigablePath) {
this( valuesArrayPosition, resultVariable, javaType, valueConverter, navigablePath, false );
}
public BasicResult(
int valuesArrayPosition,
String resultVariable,
JavaType<T> javaType,
BasicValueConverter<T,?> valueConverter,
NavigablePath navigablePath,
boolean coerceResultType) {
this.resultVariable = resultVariable;
this.javaType = javaType;
this.navigablePath = navigablePath;
this.assembler = new BasicResultAssembler<>( valuesArrayPosition, javaType, valueConverter );
if ( coerceResultType ) {
this.assembler = new CoercingResultAssembler<>( valuesArrayPosition, javaType, valueConverter );
}
else {
this.assembler = new BasicResultAssembler<>( valuesArrayPosition, javaType, valueConverter );
}
}
@Override

View File

@ -26,8 +26,8 @@ public class BasicResultAssembler<J> implements DomainResultAssembler<J> {
return new BasicResultAssembler<>( selection.getValuesArrayPosition(), javaType );
}
private final int valuesArrayPosition;
private final JavaType<J> assembledJavaType;
protected final int valuesArrayPosition;
protected final JavaType<J> assembledJavaType;
private final BasicValueConverter<J,?> valueConverter;
public BasicResultAssembler(

View File

@ -0,0 +1,38 @@
/*
* 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.sql.results.graph.basic;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
import org.hibernate.type.descriptor.java.JavaType;
/**
* A {@link BasicResultAssembler} which does type coercion to handle cases
* where the expression type and the expected result {@link JavaType} are different
* (e.g. same column mapped with differently typed properties).
*
* @author Marco Belladelli
*/
public class CoercingResultAssembler<J> extends BasicResultAssembler<J> {
public CoercingResultAssembler(
int valuesArrayPosition,
JavaType<J> assembledJavaType,
BasicValueConverter<J, ?> valueConverter) {
super( valuesArrayPosition, assembledJavaType, valueConverter );
}
/**
* Access to the row value, coerced to expected type
*/
@Override
public Object extractRawValue(RowProcessingState rowProcessingState) {
return assembledJavaType.coerce(
rowProcessingState.getJdbcValue( valuesArrayPosition ),
rowProcessingState.getSession()
);
}
}

View File

@ -92,4 +92,9 @@ public class PrimitiveCharacterArrayJavaType extends AbstractClassJavaType<char[
}
throw unknownWrap( value.getClass() );
}
@Override
public <X> char[] coerce(X value, CoercionContext coercionContext) {
return wrap( value, null );
}
}

View File

@ -90,6 +90,9 @@ public class StringJavaType extends AbstractClassJavaType<String> {
if (value instanceof String) {
return (String) value;
}
if (value instanceof char[]) {
return new String( (char[]) value );
}
if (value instanceof Reader) {
return DataHelper.extractString( (Reader) value );
}
@ -113,4 +116,8 @@ public class StringJavaType extends AbstractClassJavaType<String> {
}
}
@Override
public <X> String coerce(X value, CoercionContext coercionContext) {
return wrap( value, null );
}
}

View File

@ -42,6 +42,7 @@ import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
/**
* @author Marco Belladelli
@ -65,7 +66,7 @@ public class TreatPathTest {
term.setLength( 4 );
term.setLanguage( language );
term.setAnyProperty( stringProperty );
term.setSynonyms( new ArrayList<>( List.of( "ciao" ) ) );
term.setSynonyms( new ArrayList<>() );
term.setEmbeddableProperty( new EmbeddableType( "ciao" ) );
Linkage linkage = new Linkage();
linkage.setTerm( term );
@ -101,14 +102,7 @@ public class TreatPathTest {
@Test
public void testTreatPluralValue(EntityManagerFactoryScope scope) {
scope.inTransaction( entityManager -> {
try {
testCriteriaTreat( entityManager, "synonyms", List.of( "ciao" ) );
}
catch (Exception e) {
assertEquals( UnsupportedOperationException.class, e.getClass() );
}
} );
scope.inTransaction( entityManager -> testCriteriaTreat( entityManager, "synonyms", null, true ) );
}
@Test
@ -129,13 +123,17 @@ public class TreatPathTest {
}
private void testCriteriaTreat(EntityManager entityManager, String property, Object value) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Linkage> criteria = cb.createQuery( Linkage.class );
Root<Linkage> root = criteria.from( Linkage.class );
Path<LocalTerm> asLocalTerm = cb.treat( root.get( "term" ), LocalTerm.class );
Predicate predicate;
if ( value instanceof Collection<?> ) {
predicate = asLocalTerm.get( property ).in( value );
testCriteriaTreat( entityManager, property, value, false );
}
private void testCriteriaTreat(EntityManager entityManager, String property, Object value, boolean plural) {
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
final CriteriaQuery<Linkage> criteria = cb.createQuery( Linkage.class );
final Root<Linkage> root = criteria.from( Linkage.class );
final Path<LocalTerm> asLocalTerm = cb.treat( root.get( "term" ), LocalTerm.class );
final Predicate predicate;
if ( plural ) {
predicate = cb.isEmpty( asLocalTerm.get( property ) );
}
else {
predicate = cb.equal( asLocalTerm.get( property ), value );

View File

@ -7,6 +7,7 @@
package org.hibernate.orm.test.mapping.joincolumn;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.testing.orm.junit.DomainModel;
@ -23,6 +24,7 @@ import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -43,10 +45,10 @@ public class CharArrayToStringJoinColumnTest {
vehicle.setId( 1L );
vehicle.setStringProp( "2020" );
session.persist( vehicle );
VehicleInvoice invoice = new VehicleInvoice();
invoice.setId( "2020".toCharArray() );
invoice.setVehicle( vehicle );
vehicle.getInvoices().add( invoice );
session.persist( invoice );
} );
}
@ -62,13 +64,24 @@ public class CharArrayToStringJoinColumnTest {
@Test
public void testAssociation(SessionFactoryScope scope) {
scope.inTransaction( session -> {
List<VehicleInvoice> resultList = session.createQuery(
final VehicleInvoice vehicleInvoice = session.createQuery(
"from VehicleInvoice",
VehicleInvoice.class
).getResultList();
assertEquals( 1, resultList.size() );
assertEquals( 1L, resultList.get( 0 ).getVehicle().getId() );
assertEquals( "2020", resultList.get( 0 ).getVehicle().getStringProp() );
).getSingleResult();
assertEquals( 1L, vehicleInvoice.getVehicle().getId() );
assertEquals( "2020", vehicleInvoice.getVehicle().getStringProp() );
} );
}
@Test
public void testInverse(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final Vehicle vehicle = session.createQuery(
"from Vehicle",
Vehicle.class
).getSingleResult();
assertEquals( 1, vehicle.getInvoices().size() );
assertEquals( "2020", new String( vehicle.getInvoices().get( 0 ).getId() ) );
} );
}
@ -107,6 +120,13 @@ public class CharArrayToStringJoinColumnTest {
@Column(name = "string_col", nullable = false)
private String stringProp;
@OneToMany(mappedBy = "vehicle")
private List<VehicleInvoice> invoices;
public Vehicle() {
this.invoices = new ArrayList<>();
}
public Long getId() {
return id;
}
@ -122,6 +142,14 @@ public class CharArrayToStringJoinColumnTest {
public void setStringProp(String stringProp) {
this.stringProp = stringProp;
}
public List<VehicleInvoice> getInvoices() {
return invoices;
}
public void setInvoices(List<VehicleInvoice> invoices) {
this.invoices = invoices;
}
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.orm.test.mapping.joincolumn;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.testing.orm.junit.DomainModel;
@ -23,6 +24,7 @@ import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -43,10 +45,10 @@ public class StringToCharArrayJoinColumnTest {
vehicle.setId( 1L );
vehicle.setCharArrayProp( "2020".toCharArray() );
session.persist( vehicle );
VehicleInvoice invoice = new VehicleInvoice();
invoice.setId( "2020" );
invoice.setVehicle( vehicle );
vehicle.getInvoices().add( invoice );
session.persist( invoice );
} );
}
@ -62,16 +64,28 @@ public class StringToCharArrayJoinColumnTest {
@Test
public void testAssociation(SessionFactoryScope scope) {
scope.inTransaction( session -> {
List<VehicleInvoice> resultList = session.createQuery(
final VehicleInvoice vehicleInvoice = session.createQuery(
"from VehicleInvoice",
VehicleInvoice.class
).getResultList();
assertEquals( 1, resultList.size() );
assertEquals( 1L, resultList.get( 0 ).getVehicle().getId() );
assertEquals( "2020", new String( resultList.get( 0 ).getVehicle().getCharArrayProp() ));
).getSingleResult();
assertEquals( 1L, vehicleInvoice.getVehicle().getId() );
assertEquals( "2020", new String( vehicleInvoice.getVehicle().getCharArrayProp() ) );
} );
}
@Test
public void testInverse(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final Vehicle vehicle = session.createQuery(
"from Vehicle",
Vehicle.class
).getSingleResult();
assertEquals( 1, vehicle.getInvoices().size() );
assertEquals( "2020", vehicle.getInvoices().get( 0 ).getId() );
} );
}
@Entity(name = "VehicleInvoice")
public static class VehicleInvoice {
@Id
@ -107,6 +121,13 @@ public class StringToCharArrayJoinColumnTest {
@Column(name = "char_array_col", nullable = false)
private char[] charArrayProp;
@OneToMany(mappedBy = "vehicle")
private List<VehicleInvoice> invoices;
public Vehicle() {
this.invoices = new ArrayList<>();
}
public Long getId() {
return id;
}
@ -122,6 +143,14 @@ public class StringToCharArrayJoinColumnTest {
public void setCharArrayProp(char[] charArrayProp) {
this.charArrayProp = charArrayProp;
}
public List<VehicleInvoice> getInvoices() {
return invoices;
}
public void setInvoices(List<VehicleInvoice> invoices) {
this.invoices = invoices;
}
}
}

View File

@ -4,7 +4,7 @@
* 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.mapping.joincolumn;
package org.hibernate.orm.test.mapping.joincolumn.embedded;
import java.io.Serializable;
@ -101,7 +101,7 @@ public class CharArrayToStringInEmbeddedJoinColumnOrFormulaTest {
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumnsOrFormulas({
@JoinColumnOrFormula(formula = @JoinFormula(value = "trim(char_array_col_1)", referencedColumnName = "string_col_1")),
@JoinColumnOrFormula(formula = @JoinFormula(value = "char_array_col_1", referencedColumnName = "string_col_1")),
@JoinColumnOrFormula(column = @JoinColumn(name = "char_array_col_2", referencedColumnName = "string_col_2", insertable = false, updatable = false))
})
private Vehicle vehicle;

View File

@ -7,6 +7,7 @@
package org.hibernate.orm.test.mapping.joincolumn.embedded;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.testing.orm.junit.DomainModel;
@ -25,6 +26,7 @@ import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -45,10 +47,10 @@ public class CharArrayToStringInEmbeddedJoinColumnTest {
vehicle.setId( 1L );
vehicle.setStringProp( "2020" );
session.persist( vehicle );
VehicleInvoice invoice = new VehicleInvoice();
invoice.setId( new VehicleInvoiceId( "2020".toCharArray(), 2020 ) );
invoice.setVehicle( vehicle );
vehicle.getInvoices().add( invoice );
session.persist( invoice );
} );
}
@ -64,13 +66,24 @@ public class CharArrayToStringInEmbeddedJoinColumnTest {
@Test
public void testAssociation(SessionFactoryScope scope) {
scope.inTransaction( session -> {
List<VehicleInvoice> resultList = session.createQuery(
final VehicleInvoice vehicleInvoice = session.createQuery(
"from VehicleInvoice",
VehicleInvoice.class
).getResultList();
assertEquals( 1, resultList.size() );
assertEquals( 1L, resultList.get( 0 ).getVehicle().getId() );
assertEquals( "2020", resultList.get( 0 ).getVehicle().getStringProp() );
).getSingleResult();
assertEquals( 1L, vehicleInvoice.getVehicle().getId() );
assertEquals( "2020", vehicleInvoice.getVehicle().getStringProp() );
} );
}
@Test
public void testInverse(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final Vehicle vehicle = session.createQuery(
"from Vehicle",
Vehicle.class
).getSingleResult();
assertEquals( 1, vehicle.getInvoices().size() );
assertEquals( "2020", new String( vehicle.getInvoices().get( 0 ).getId().getCharArrayProp() ) );
} );
}
@ -141,6 +154,13 @@ public class CharArrayToStringInEmbeddedJoinColumnTest {
@Column(name = "string_col", nullable = false)
private String stringProp;
@OneToMany(mappedBy = "vehicle")
private List<VehicleInvoice> invoices;
public Vehicle() {
this.invoices = new ArrayList<>();
}
public Long getId() {
return id;
}
@ -156,6 +176,14 @@ public class CharArrayToStringInEmbeddedJoinColumnTest {
public void setStringProp(String stringProp) {
this.stringProp = stringProp;
}
public List<VehicleInvoice> getInvoices() {
return invoices;
}
public void setInvoices(List<VehicleInvoice> invoices) {
this.invoices = invoices;
}
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.orm.test.mapping.joincolumn.embedded;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.testing.orm.junit.DomainModel;
@ -25,6 +26,7 @@ import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -46,10 +48,10 @@ public class CharArrayToStringInEmbeddedMultipleJoinColumnTest {
vehicle.setStringProp( "2020" );
vehicle.setIntProp( 2020 );
session.persist( vehicle );
VehicleInvoice invoice = new VehicleInvoice();
invoice.setId( new VehicleInvoiceId( "2020".toCharArray(), 2020 ) );
invoice.setVehicle( vehicle );
vehicle.getInvoices().add( invoice );
session.persist( invoice );
} );
}
@ -65,13 +67,24 @@ public class CharArrayToStringInEmbeddedMultipleJoinColumnTest {
@Test
public void testAssociation(SessionFactoryScope scope) {
scope.inTransaction( session -> {
List<VehicleInvoice> resultList = session.createQuery(
final VehicleInvoice vehicleInvoice = session.createQuery(
"from VehicleInvoice",
VehicleInvoice.class
).getResultList();
assertEquals( 1, resultList.size() );
assertEquals( 1L, resultList.get( 0 ).getVehicle().getId() );
assertEquals( "2020", resultList.get( 0 ).getVehicle().getStringProp() );
).getSingleResult();
assertEquals( 1L, vehicleInvoice.getVehicle().getId() );
assertEquals( "2020", vehicleInvoice.getVehicle().getStringProp() );
} );
}
@Test
public void testInverse(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final Vehicle vehicle = session.createQuery(
"from Vehicle",
Vehicle.class
).getSingleResult();
assertEquals( 1, vehicle.getInvoices().size() );
assertEquals( "2020", new String( vehicle.getInvoices().get( 0 ).getId().getCharArrayProp() ) );
} );
}
@ -146,6 +159,13 @@ public class CharArrayToStringInEmbeddedMultipleJoinColumnTest {
@Column(name = "int_col", nullable = false)
private int intProp;
@OneToMany(mappedBy = "vehicle")
private List<VehicleInvoice> invoices;
public Vehicle() {
this.invoices = new ArrayList<>();
}
public Long getId() {
return id;
}
@ -169,6 +189,14 @@ public class CharArrayToStringInEmbeddedMultipleJoinColumnTest {
public void setIntProp(int intProp) {
this.intProp = intProp;
}
public List<VehicleInvoice> getInvoices() {
return invoices;
}
public void setInvoices(List<VehicleInvoice> invoices) {
this.invoices = invoices;
}
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.orm.test.mapping.joincolumn.embedded;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.testing.orm.junit.DomainModel;
@ -25,6 +26,7 @@ import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -45,10 +47,10 @@ public class StringToCharArrayInEmbeddedJoinColumnTest {
vehicle.setId( 1L );
vehicle.setCharArrayProp( "2020".toCharArray() );
session.persist( vehicle );
VehicleInvoice invoice = new VehicleInvoice();
invoice.setId( new VehicleInvoiceId( "2020", 2020 ) );
invoice.setVehicle( vehicle );
vehicle.getInvoices().add( invoice );
session.persist( invoice );
} );
}
@ -64,13 +66,24 @@ public class StringToCharArrayInEmbeddedJoinColumnTest {
@Test
public void testAssociation(SessionFactoryScope scope) {
scope.inTransaction( session -> {
List<VehicleInvoice> resultList = session.createQuery(
final VehicleInvoice vehicleInvoice = session.createQuery(
"from VehicleInvoice",
VehicleInvoice.class
).getResultList();
assertEquals( 1, resultList.size() );
assertEquals( 1L, resultList.get( 0 ).getVehicle().getId() );
assertEquals( "2020", new String( resultList.get( 0 ).getVehicle().getCharArrayProp() ) );
).getSingleResult();
assertEquals( 1L, vehicleInvoice.getVehicle().getId() );
assertEquals( "2020", new String( vehicleInvoice.getVehicle().getCharArrayProp() ) );
} );
}
@Test
public void testInverse(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final Vehicle vehicle = session.createQuery(
"from Vehicle",
Vehicle.class
).getSingleResult();
assertEquals( 1, vehicle.getInvoices().size() );
assertEquals( "2020", vehicle.getInvoices().get( 0 ).getId().getStringProp() );
} );
}
@ -141,6 +154,13 @@ public class StringToCharArrayInEmbeddedJoinColumnTest {
@Column(name = "char_array_col", nullable = false)
private char[] charArrayProp;
@OneToMany(mappedBy = "vehicle")
private List<VehicleInvoice> invoices;
public Vehicle() {
this.invoices = new ArrayList<>();
}
public Long getId() {
return id;
}
@ -156,6 +176,14 @@ public class StringToCharArrayInEmbeddedJoinColumnTest {
public void setCharArrayProp(char[] charArrayProp) {
this.charArrayProp = charArrayProp;
}
public List<VehicleInvoice> getInvoices() {
return invoices;
}
public void setInvoices(List<VehicleInvoice> invoices) {
this.invoices = invoices;
}
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.orm.test.mapping.joincolumn.embedded;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.testing.orm.junit.DomainModel;
@ -25,6 +26,7 @@ import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -46,10 +48,10 @@ public class StringToCharArrayInEmbeddedMultipleJoinColumnTest {
vehicle.setCharArrayProp( "2020".toCharArray() );
vehicle.setIntProp( 2020 );
session.persist( vehicle );
VehicleInvoice invoice = new VehicleInvoice();
invoice.setId( new VehicleInvoiceId( "2020", 2020 ) );
invoice.setVehicle( vehicle );
vehicle.getInvoices().add( invoice );
session.persist( invoice );
} );
}
@ -65,13 +67,24 @@ public class StringToCharArrayInEmbeddedMultipleJoinColumnTest {
@Test
public void testAssociation(SessionFactoryScope scope) {
scope.inTransaction( session -> {
List<VehicleInvoice> resultList = session.createQuery(
final VehicleInvoice vehicleInvoice = session.createQuery(
"from VehicleInvoice",
VehicleInvoice.class
).getResultList();
assertEquals( 1, resultList.size() );
assertEquals( 1L, resultList.get( 0 ).getVehicle().getId() );
assertEquals( "2020", new String( resultList.get( 0 ).getVehicle().getCharArrayProp() ));
).getSingleResult();
assertEquals( 1L, vehicleInvoice.getVehicle().getId() );
assertEquals( "2020", new String( vehicleInvoice.getVehicle().getCharArrayProp() ) );
} );
}
@Test
public void testInverse(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final Vehicle vehicle = session.createQuery(
"from Vehicle",
Vehicle.class
).getSingleResult();
assertEquals( 1, vehicle.getInvoices().size() );
assertEquals( "2020", vehicle.getInvoices().get( 0 ).getId().getStringProp() );
} );
}
@ -146,6 +159,13 @@ public class StringToCharArrayInEmbeddedMultipleJoinColumnTest {
@Column(name = "int_col", nullable = false)
private int intProp;
@OneToMany(mappedBy = "vehicle")
private List<VehicleInvoice> invoices;
public Vehicle() {
this.invoices = new ArrayList<>();
}
public Long getId() {
return id;
}
@ -169,6 +189,14 @@ public class StringToCharArrayInEmbeddedMultipleJoinColumnTest {
public void setIntProp(int intProp) {
this.intProp = intProp;
}
public List<VehicleInvoice> getInvoices() {
return invoices;
}
public void setInvoices(List<VehicleInvoice> invoices) {
this.invoices = invoices;
}
}
}