Skip to content

Commit

Permalink
HHH-16514 - Property sorting can lead to incorrect column mappings wi…
Browse files Browse the repository at this point in the history
…th derived embeddable keys

(cherry picked from commit 60b6fe3)
  • Loading branch information
sebersole committed Jun 28, 2023
1 parent 26ba403 commit 1ead5d2
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@
* @author Emmanuel Bernard
*/
public class TableBinder {
//TODO move it to a getter/setter strategy
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, TableBinder.class.getName() );

private MetadataBuildingContext buildingContext;
Expand Down Expand Up @@ -550,6 +549,12 @@ else if ( firstColumn.isImplicit() ) {
// if columns are implicit, then create the columns based
// on the referenced entity id columns
bindImplicitColumns( referencedEntity, joinColumns, value );
if ( value instanceof ToOne ) {
// in the case of implicit foreign-keys, make sure the columns making up
// the foreign-key do not get resorted since the order is already properly
// ascertained from the referenced identifier
( (ToOne) value ).setSorted( true );
}
}
else {
bindExplicitColumns( referencedEntity, joinColumns, value, buildingContext, associatedClass );
Expand Down Expand Up @@ -586,7 +591,6 @@ private static void bindImplicitPrimaryKeyReference(
PersistentClass associatedClass) {
//implicit case, we hope PK and FK columns are in the same order
if ( joinColumns.getColumns().size() != referencedEntity.getIdentifier().getColumnSpan() ) {
// TODO: what about secondary tables?? associatedClass is null?
throw new AnnotationException(
"An association that targets entity '" + referencedEntity.getEntityName()
+ "' from entity '" + associatedClass.getEntityName()
Expand Down Expand Up @@ -669,7 +673,7 @@ private static boolean matchUpJoinColumnsWithKeyColumns(
columns = referencedTable.getPrimaryKey().getColumns();
break;
}
catch ( MappingException i ) {
catch (MappingException ignore) {
}
}
if ( referencedColumn == null ) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* 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.foreignkeys.sorting;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;

/**
* @author Steve Ebersole
*/
@Entity
public class A {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;

@ManyToOne(cascade = CascadeType.PERSIST)
B b;

public A() {
}

public A(B b) {
this.b = b;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* 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.foreignkeys.sorting;

import java.math.BigDecimal;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.Id;

/**
* @author Steve Ebersole
*/
@Entity
public class B {
enum Type {ONE,ANOTHER}

@Id
@Column(length = 12)
String code;

@Id
@Column(precision = 10, scale = 0)
BigDecimal cost;

@Id
@Enumerated(EnumType.STRING)
Type type;

@Id
long id;

String name;

public B() {
}

public B(String code, BigDecimal cost, Type type, long id, String name) {
this.code = code;
this.cost = cost;
this.type = type;
this.id = id;
this.name = name;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* 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.foreignkeys.sorting;

import java.math.BigDecimal;

import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.Jira;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

/**
* @author Steve Ebersole
*/
@DomainModel(annotatedClasses = { A.class, B.class })
@SessionFactory
public class ForeignKeyColumnSortingTests {
@Test
@Jira( "https://hibernate.atlassian.net/browse/HHH-16514" )
public void testDerivedCompositeFk(SessionFactoryScope sfScope) {

sfScope.inTransaction( (session) -> {
final B b = new B( "abc", new BigDecimal( 1 ), B.Type.ONE, 1L, "tester" );
session.persist( b );
session.persist( new A( b ) );
} );

sfScope.inTransaction( (session) -> {
final A loaded = session.get( A.class, 1 );
assertThat( loaded ).isNotNull();
assertThat( loaded.b ).isNotNull();
assertThat( loaded.b.name ).isEqualTo( "tester" );
} );
}
}

0 comments on commit 1ead5d2

Please sign in to comment.