HHH-15167 IllegalArgumentException occurred while calling setter for property

This commit is contained in:
Andrea Boriero 2022-04-11 14:43:36 +02:00 committed by Andrea Boriero
parent a2c161f95d
commit 43f310da92
2 changed files with 372 additions and 8 deletions

View File

@ -775,6 +775,7 @@ public class ToOneAttributeMapping
fetchablePath, fetchablePath,
fetchParent, fetchParent,
parentNavigablePath, parentNavigablePath,
fetchTiming,
creationState creationState
); );
} }
@ -935,6 +936,7 @@ public class ToOneAttributeMapping
NavigablePath fetchablePath, NavigablePath fetchablePath,
FetchParent fetchParent, FetchParent fetchParent,
NavigablePath parentNavigablePath, NavigablePath parentNavigablePath,
FetchTiming fetchTiming,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
final NavigablePath referencedNavigablePath; final NavigablePath referencedNavigablePath;
final boolean hasBidirectionalFetchParent; final boolean hasBidirectionalFetchParent;
@ -1019,17 +1021,29 @@ public class ToOneAttributeMapping
realParent = parentNavigablePath; realParent = parentNavigablePath;
} }
final TableGroup tableGroup = fromClauseAccess.getTableGroup( realParent ); final TableGroup tableGroup = fromClauseAccess.getTableGroup( realParent );
final DomainResult<?> domainResult = foreignKeyDescriptor.createDomainResult(
fetchablePath,
tableGroup,
sideNature,
fetchParent,
creationState
);
if ( fetchTiming == FetchTiming.IMMEDIATE ) {
return new EntityFetchSelectImpl(
fetchParent,
this,
fetchablePath,
domainResult,
isSelectByUniqueKey( sideNature ),
creationState
);
}
return new EntityDelayedFetchImpl( return new EntityDelayedFetchImpl(
fetchParent, fetchParent,
this, this,
fetchablePath, fetchablePath,
foreignKeyDescriptor.createDomainResult( domainResult,
fetchablePath,
tableGroup,
sideNature,
fetchParent,
creationState
),
isSelectByUniqueKey( sideNature ) isSelectByUniqueKey( sideNature )
); );
} }
@ -1097,8 +1111,10 @@ public class ToOneAttributeMapping
|| ( partMappingType != entityMappingType || ( partMappingType != entityMappingType
&& !entityMappingType.getEntityPersister().isSubclassEntityName( partMappingType.getMappedJavaType().getJavaType().getTypeName() ) && !entityMappingType.getEntityPersister().isSubclassEntityName( partMappingType.getMappedJavaType().getJavaType().getTypeName() )
&& !( (EntityMappingType) partMappingType ).getEntityPersister().isSubclassEntityName( entityMappingType.getEntityName() ) ) ) { && !( (EntityMappingType) partMappingType ).getEntityPersister().isSubclassEntityName( entityMappingType.getEntityName() ) ) ) {
referencedNavigablePath = referencedNavigablePath.getParent(); referencedNavigablePath = referencedNavigablePath.getParent();
if ( referencedNavigablePath == null ) {
return null;
}
partMappingType = creationState.resolveModelPart( referencedNavigablePath ).getPartMappingType(); partMappingType = creationState.resolveModelPart( referencedNavigablePath ).getPartMappingType();
} }
return referencedNavigablePath; return referencedNavigablePath;

View File

@ -0,0 +1,348 @@
package org.hibernate.orm.test.jpa.association.toone;
import java.util.List;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.testing.jdbc.SQLStatementInspector;
import org.hibernate.testing.orm.jdbc.DefaultSQLStatementInspectorSettingProvider;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.Jpa;
import org.hibernate.testing.orm.junit.SettingProvider;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Fetch;
import jakarta.persistence.criteria.From;
import jakarta.persistence.criteria.JoinType;
import jakarta.persistence.metamodel.EntityType;
import jakarta.persistence.metamodel.SingularAttribute;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
@Jpa(
annotatedClasses = {
CriteriaJoinFetchTest.Customer.class,
CriteriaJoinFetchTest.Address.class,
CriteriaJoinFetchTest.Note.class
},
settingProviders = {
@SettingProvider(
settingName = AvailableSettings.STATEMENT_INSPECTOR,
provider = DefaultSQLStatementInspectorSettingProvider.class
)
}
)
public class CriteriaJoinFetchTest {
private static SQLStatementInspector statementInspector;
@BeforeEach
public void setUp(EntityManagerFactoryScope scope) {
statementInspector = scope.getStatementInspector( SQLStatementInspector.class );
scope.inTransaction(
entityManager -> {
Customer customer0 = new Customer( 1, "William P. Keaton" );
Customer customer1 = new Customer( 2, "Kate P. Hudson" );
entityManager.persist( customer0 );
entityManager.persist( customer1 );
Note note0 = new Note( 3, "Note for address 0" );
Note note1 = new Note( 4, "Note for address 1" );
Address address0 = new Address( 5, "Flit street", "London", note0, customer0 );
Address address1 = new Address( 6, "via Marconi", "Pavia", note1, customer1 );
entityManager.persist( address0 );
entityManager.persist( address1 );
customer0.setAddress( address0 );
customer1.setAddress( address1 );
}
);
}
@AfterEach
public void tearDown(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
entityManager.createQuery( "delete from Address" ).executeUpdate();
entityManager.createQuery( "delete from Note" ).executeUpdate();
entityManager.createQuery( "delete from Customer" ).executeUpdate();
}
);
}
@Test
public void testCriteriaFetchSingularAttribute(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
statementInspector.clear();
final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
final CriteriaQuery<Customer> criteriaQuery = criteriaBuilder.createQuery( Customer.class );
final From<Customer, Customer> customer = criteriaQuery.from( Customer.class );
final EntityType<Customer> customerEntityType = entityManager.getMetamodel()
.entity( Customer.class );
final SingularAttribute<? super Customer, Address> address = (SingularAttribute<? super Customer, Address>) customerEntityType.getSingularAttribute(
"address" );
customer.fetch( address, JoinType.INNER );
criteriaQuery.select( customer );
final TypedQuery<Customer> query = entityManager.createQuery( criteriaQuery );
List<Customer> result = query.getResultList();
assertThat( result.size(), is( 2 ) );
assertThat( statementInspector.getSqlQueries().size(), is( 3 ) );
Customer customer1 = result.get( 0 );
Note note = customer1.getAddress().getNote();
assertThat( note, notNullValue() );
if ( customer1.getId() == 1 ) {
assertThat( note.getId(), is( 3 ) );
}
else {
assertThat( note.getId(), is( 4 ) );
}
}
);
}
@Test
public void testCriteriaFetchSingularAttribute2(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
statementInspector.clear();
final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
final CriteriaQuery<Customer> criteriaQuery = criteriaBuilder.createQuery( Customer.class );
final From<Customer, Customer> customer = criteriaQuery.from( Customer.class );
final EntityType<Customer> customerEntityType = entityManager.getMetamodel()
.entity( Customer.class );
final SingularAttribute<? super Customer, Address> address = (SingularAttribute<? super Customer, Address>) customerEntityType.getSingularAttribute(
"address" );
final Fetch<Customer, Address> fetch = customer.fetch( address, JoinType.INNER );
fetch.fetch( entityManager.getMetamodel()
.entity( Address.class ).getSingularAttribute( "note" ), JoinType.INNER );
criteriaQuery.select( customer );
final TypedQuery<Customer> query = entityManager.createQuery( criteriaQuery );
final List<Customer> result = query.getResultList();
assertThat( result.size(), is( 2 ) );
assertThat( statementInspector.getSqlQueries().size(), is( 1 ) );
final Customer customer1 = result.get( 0 );
final Note note = customer1.getAddress().getNote();
assertThat( note, notNullValue() );
if ( customer1.getId() == 1 ) {
assertThat( note.getId(), is( 3 ) );
}
else {
assertThat( note.getId(), is( 4 ) );
}
assertThat( statementInspector.getSqlQueries().size(), is( 1 ) );
}
);
}
@Test
public void testFind(EntityManagerFactoryScope scope) {
statementInspector.clear();
scope.inTransaction(
entityManager -> {
Customer customer = entityManager.find( Customer.class, 2 );
final Note note = customer.getAddress().getNote();
assertThat( note.getId(), is( 4 ) );
assertThat( statementInspector.getSqlQueries().size(), is( 1 ) );
}
);
}
@Entity(name = "Customer")
@Table(name = "CUSTOMER_TABLE")
public static class Customer {
@Id
private Integer id;
private String name;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "customer")
private Address address;
public Customer() {
}
public Customer(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
@Entity(name = "Address")
@Table(name = "ADDRESS_TABLE")
public static class Address {
@Id
private Integer id;
private String street;
private String city;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "NOTE_FK")
private Note note;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "CUSTOMER_FK")
private Customer customer;
public Address() {
}
public Address(
Integer id,
String street,
String city,
Note note,
Customer customer) {
this.id = id;
this.street = street;
this.city = city;
this.note = note;
this.note.setAddress( this );
this.customer = customer;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public Note getNote() {
return note;
}
public void setNote(Note note) {
this.note = note;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
@Entity(name = "Note")
@Table(name = "NOTE_TABLE")
public static class Note {
@Id
private Integer id;
private String line;
@OneToOne(mappedBy = "note")
private Address address;
public Note() {
}
public Note(Integer id, String line) {
this.id = id;
this.line = line;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
}