HHH-11255 - NaturalId mapping fails when using a composite natural identifier
Add support for adding unique constraints to composite entity properties, like when using a @NaturalId with an @Embedded property
This commit is contained in:
parent
95b1e27902
commit
74a789e617
|
@ -6,13 +6,20 @@
|
|||
*/
|
||||
package org.hibernate.cfg;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.Index;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.mapping.UniqueKey;
|
||||
|
||||
/**
|
||||
* @author Emmanuel Bernard
|
||||
|
@ -64,10 +71,27 @@ public class IndexOrUniqueKeySecondPass implements SecondPass {
|
|||
}
|
||||
if ( column != null ) {
|
||||
this.table = column.getTable();
|
||||
addConstraintToColumn(
|
||||
buildingContext.getMetadataCollector()
|
||||
|
||||
PersistentClass persistentClass = (PersistentClass) persistentClasses.get( column.getPropertyHolder().getEntityName() );
|
||||
Property property = persistentClass.getProperty( column.getPropertyName() );
|
||||
|
||||
if ( property.getValue() instanceof Component ) {
|
||||
Component component = (Component) property.getValue();
|
||||
|
||||
List<Column> columns = new ArrayList<>();
|
||||
component.getColumnIterator().forEachRemaining( selectable -> {
|
||||
if ( selectable instanceof Column ) {
|
||||
columns.add( (Column) selectable );
|
||||
}
|
||||
} );
|
||||
addConstraintToColumns( columns );
|
||||
}
|
||||
else {
|
||||
addConstraintToColumn(
|
||||
buildingContext.getMetadataCollector()
|
||||
.getLogicalColumnName( table, column.getMappingColumn().getQuotedName() )
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,4 +113,19 @@ public class IndexOrUniqueKeySecondPass implements SecondPass {
|
|||
table.getOrCreateIndex( indexName ).addColumn( column );
|
||||
}
|
||||
}
|
||||
|
||||
private void addConstraintToColumns(List<Column> columns) {
|
||||
if ( unique ) {
|
||||
UniqueKey uniqueKey = table.getOrCreateUniqueKey( indexName );
|
||||
for ( Column column : columns ) {
|
||||
uniqueKey.addColumn( column );
|
||||
}
|
||||
}
|
||||
else {
|
||||
Index index = table.getOrCreateIndex( indexName );
|
||||
for ( Column column : columns ) {
|
||||
index.addColumn( column );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,25 +12,27 @@ import org.hibernate.boot.registry.StandardServiceRegistry;
|
|||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
|
||||
import org.hibernate.testing.FailureExpected;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@TestForIssue(jiraKey = "HHH-11255")
|
||||
public class CompositeNaturalIdMappingTest extends BaseUnitTestCase {
|
||||
|
||||
@Test
|
||||
@FailureExpected( jiraKey = "tbd" )
|
||||
public void test() {
|
||||
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().build();
|
||||
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder()
|
||||
.build();
|
||||
|
||||
try {
|
||||
Metadata meta = new MetadataSources( ssr )
|
||||
.addAnnotatedClass( PostalCarrier.class )
|
||||
.addAnnotatedClass( PostalCode.class )
|
||||
.buildMetadata();
|
||||
( ( MetadataImplementor) meta ).validate();
|
||||
( (MetadataImplementor) meta ).validate();
|
||||
}
|
||||
finally {
|
||||
StandardServiceRegistryBuilder.destroy( ssr );
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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.naturalid.composite;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
*/
|
||||
@TestForIssue(jiraKey = "HHH-11255")
|
||||
public class EmbeddedNaturalIdTest extends BaseEntityManagerFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {
|
||||
PostalCarrier.class
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
PostalCarrier postalCarrier = new PostalCarrier();
|
||||
postalCarrier.setId( 1L );
|
||||
postalCarrier.setPostalCode( new PostalCode() );
|
||||
postalCarrier.getPostalCode().setCode( "ABC123" );
|
||||
postalCarrier.getPostalCode().setCountry( "US" );
|
||||
|
||||
entityManager.persist( postalCarrier );
|
||||
} );
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
PostalCarrier postalCarrier = entityManager.unwrap( Session.class )
|
||||
.byNaturalId( PostalCarrier.class )
|
||||
.using( "postalCode", new PostalCode( "ABC123", "US" ) )
|
||||
.load();
|
||||
assertEquals( Long.valueOf( 1L ), postalCarrier.getId() );
|
||||
} );
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
PostalCarrier postalCarrier = entityManager.unwrap( Session.class )
|
||||
.bySimpleNaturalId( PostalCarrier.class )
|
||||
.load( new PostalCode( "ABC123", "US" ) );
|
||||
assertEquals( Long.valueOf( 1L ), postalCarrier.getId() );
|
||||
} );
|
||||
}
|
||||
}
|
|
@ -24,6 +24,9 @@ public class PostalCarrier {
|
|||
@Embedded
|
||||
private PostalCode postalCode;
|
||||
|
||||
public PostalCarrier() {
|
||||
}
|
||||
|
||||
public PostalCarrier(long id, PostalCode postalCode) {
|
||||
this.id = id;
|
||||
this.postalCode = postalCode;
|
||||
|
|
Loading…
Reference in New Issue