HHH-18060 - HbmXmlTransformer
* <join/> -> <secondary-table/> * <list/>
This commit is contained in:
parent
bcf8d7bee8
commit
fd5de56c19
|
@ -9,8 +9,10 @@ package org.hibernate.boot.jaxb.hbm.transform;
|
|||
import java.io.Serializable;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
@ -216,6 +218,12 @@ public class HbmXmlTransformer {
|
|||
private final TransformationState transformationState;
|
||||
private final UnsupportedFeatureHandling unsupportedFeatureHandling;
|
||||
|
||||
private final Map<String,JaxbEmbeddableImpl> jaxbEmbeddableByClassName = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Used to handle secondary table transformations
|
||||
*/
|
||||
private String currentTableName = "";
|
||||
|
||||
private HbmXmlTransformer(
|
||||
Binding<JaxbHbmHibernateMapping> hbmJaxbBinding,
|
||||
|
@ -853,6 +861,8 @@ public class HbmXmlTransformer {
|
|||
origin
|
||||
);
|
||||
|
||||
currentTableName = "";
|
||||
|
||||
transferBaseEntityInformation( hbmClass, entity );
|
||||
|
||||
entity.setMutable( hbmClass.isMutable() );
|
||||
|
@ -1089,6 +1099,9 @@ public class HbmXmlTransformer {
|
|||
origin
|
||||
);
|
||||
|
||||
|
||||
currentTableName = "";
|
||||
|
||||
transferBaseEntityInformation( hbmSubclass, subclassEntity );
|
||||
|
||||
transferEntityElementAttributes( hbmSubclass, subclassEntity );
|
||||
|
@ -1108,6 +1121,9 @@ public class HbmXmlTransformer {
|
|||
origin
|
||||
);
|
||||
|
||||
|
||||
currentTableName = "";
|
||||
|
||||
transferBaseEntityInformation( hbmSubclass, subclassEntity );
|
||||
transferEntityElementAttributes( hbmSubclass, subclassEntity );
|
||||
|
||||
|
@ -1152,7 +1168,7 @@ public class HbmXmlTransformer {
|
|||
column.setTable( tableName );
|
||||
target.addColumn( column );
|
||||
}
|
||||
else {
|
||||
else if ( !source.getColumnOrFormula().isEmpty() ) {
|
||||
for ( Serializable columnOrFormula : source.getColumnOrFormula() ) {
|
||||
if ( columnOrFormula instanceof String ) {
|
||||
target.addFormula( (String) columnOrFormula );
|
||||
|
@ -1166,6 +1182,13 @@ public class HbmXmlTransformer {
|
|||
}
|
||||
}
|
||||
}
|
||||
else if ( StringHelper.isNotEmpty( tableName ) ) {
|
||||
// this is the case of transforming a <join/> where the property did not specify columns or formula.
|
||||
// we need to create a column still to pass along the secondary table name
|
||||
final TargetColumnAdapter column = target.makeColumnAdapter( columnDefaults );
|
||||
column.setTable( tableName );
|
||||
target.addColumn( column );
|
||||
}
|
||||
}
|
||||
|
||||
private void transferColumn(
|
||||
|
@ -1455,14 +1478,19 @@ public class HbmXmlTransformer {
|
|||
return hbmProp.isUpdate();
|
||||
}
|
||||
},
|
||||
// todo : need to push the table name down into this method to pass along
|
||||
// todo : need to push the table name down into this method to pass along
|
||||
null
|
||||
currentTableName
|
||||
);
|
||||
}
|
||||
|
||||
private JaxbEmbeddableImpl applyEmbeddable(JaxbEntityMappingsImpl ormRoot, JaxbHbmCompositeAttributeType hbmComponent) {
|
||||
final String embeddableClassName = hbmComponent.getClazz();
|
||||
if ( StringHelper.isNotEmpty( embeddableClassName ) ) {
|
||||
final JaxbEmbeddableImpl existing = jaxbEmbeddableByClassName.get( embeddableClassName );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
}
|
||||
|
||||
final String embeddableName = determineEmbeddableName( embeddableClassName, hbmComponent.getName() );
|
||||
final JaxbEmbeddableImpl jaxbEmbeddable = convertEmbeddable(
|
||||
embeddableName,
|
||||
|
@ -1470,6 +1498,12 @@ public class HbmXmlTransformer {
|
|||
hbmComponent
|
||||
);
|
||||
ormRoot.getEmbeddables().add( jaxbEmbeddable );
|
||||
|
||||
|
||||
if ( StringHelper.isNotEmpty( embeddableClassName ) ) {
|
||||
jaxbEmbeddableByClassName.put( embeddableClassName, jaxbEmbeddable );
|
||||
}
|
||||
|
||||
return jaxbEmbeddable;
|
||||
}
|
||||
|
||||
|
@ -1485,7 +1519,6 @@ public class HbmXmlTransformer {
|
|||
|
||||
embeddable.setAttributes( new JaxbEmbeddableAttributesContainerImpl() );
|
||||
transferAttributes( hbmComponent.getAttributes(), embeddable.getAttributes() );
|
||||
|
||||
return embeddable;
|
||||
}
|
||||
|
||||
|
@ -1602,7 +1635,7 @@ public class HbmXmlTransformer {
|
|||
}
|
||||
},
|
||||
ColumnDefaultsBasicImpl.INSTANCE,
|
||||
null
|
||||
currentTableName
|
||||
);
|
||||
|
||||
m2o.setName( hbmNode.getName() );
|
||||
|
@ -2371,40 +2404,39 @@ public class HbmXmlTransformer {
|
|||
|
||||
private void transferJoins(JaxbHbmRootEntityType source, JaxbEntityImpl target) {
|
||||
for ( JaxbHbmSecondaryTableType hbmJoin : source.getJoin() ) {
|
||||
if ( !hbmJoin.isInverse() ) {
|
||||
final JaxbSecondaryTableImpl secondaryTable = new JaxbSecondaryTableImpl();
|
||||
secondaryTable.setCatalog( hbmJoin.getCatalog() );
|
||||
secondaryTable.setComment( hbmJoin.getComment() );
|
||||
secondaryTable.setName( hbmJoin.getTable() );
|
||||
secondaryTable.setSchema( hbmJoin.getSchema() );
|
||||
secondaryTable.setOptional( hbmJoin.isOptional() );
|
||||
if ( hbmJoin.getKey() != null ) {
|
||||
final JaxbPrimaryKeyJoinColumnImpl joinColumn = new JaxbPrimaryKeyJoinColumnImpl();
|
||||
joinColumn.setName( hbmJoin.getKey().getColumnAttribute() );
|
||||
secondaryTable.getPrimaryKeyJoinColumn().add( joinColumn );
|
||||
}
|
||||
target.getSecondaryTables().add( secondaryTable );
|
||||
currentTableName = hbmJoin.getTable();
|
||||
assert StringHelper.isNotEmpty( currentTableName );
|
||||
|
||||
final JaxbSecondaryTableImpl secondaryTable = new JaxbSecondaryTableImpl();
|
||||
secondaryTable.setCatalog( hbmJoin.getCatalog() );
|
||||
secondaryTable.setComment( hbmJoin.getComment() );
|
||||
secondaryTable.setName( hbmJoin.getTable() );
|
||||
secondaryTable.setSchema( hbmJoin.getSchema() );
|
||||
secondaryTable.setOptional( hbmJoin.isOptional() );
|
||||
secondaryTable.setOwned( !hbmJoin.isInverse() );
|
||||
if ( hbmJoin.getKey() != null ) {
|
||||
final JaxbPrimaryKeyJoinColumnImpl joinColumn = new JaxbPrimaryKeyJoinColumnImpl();
|
||||
joinColumn.setName( hbmJoin.getKey().getColumnAttribute() );
|
||||
secondaryTable.getPrimaryKeyJoinColumn().add( joinColumn );
|
||||
}
|
||||
target.getSecondaryTables().add( secondaryTable );
|
||||
|
||||
for ( Serializable attributeMapping : hbmJoin.getAttributes() ) {
|
||||
if ( attributeMapping instanceof JaxbHbmBasicAttributeType ) {
|
||||
final JaxbBasicImpl prop = transformBasicAttribute( (JaxbHbmBasicAttributeType) attributeMapping );
|
||||
if ( prop.getColumn() != null ) {
|
||||
prop.getColumn().setTable( hbmJoin.getTable() );
|
||||
if ( prop.getColumn() == null && prop.getFormula() == null ) {
|
||||
prop.setColumn( new JaxbColumnImpl() );
|
||||
prop.getColumn().setTable( currentTableName );
|
||||
}
|
||||
target.getAttributes().getBasicAttributes().add( prop );
|
||||
}
|
||||
else if ( attributeMapping instanceof JaxbHbmCompositeAttributeType ) {
|
||||
throw new MappingException(
|
||||
"transformation of <component/> as part of <join/> (secondary-table) not yet implemented",
|
||||
origin
|
||||
);
|
||||
else if ( attributeMapping instanceof JaxbHbmCompositeAttributeType hbmComponent ) {
|
||||
final JaxbEmbeddableImpl jaxbEmbeddable = applyEmbeddable( ormRoot, hbmComponent );
|
||||
target.getAttributes().getEmbeddedAttributes().add( transformEmbedded( jaxbEmbeddable, hbmComponent ) );
|
||||
}
|
||||
else if ( attributeMapping instanceof JaxbHbmManyToOneType ) {
|
||||
throw new MappingException(
|
||||
"transformation of <many-to-one/> as part of <join/> (secondary-table) not yet implemented",
|
||||
origin
|
||||
);
|
||||
else if ( attributeMapping instanceof JaxbHbmManyToOneType hbmManyToOne ) {
|
||||
final JaxbManyToOneImpl jaxbManyToOne = transformManyToOne( hbmManyToOne );
|
||||
target.getAttributes().getManyToOneAttributes().add( jaxbManyToOne );
|
||||
}
|
||||
else if ( attributeMapping instanceof JaxbHbmAnyAssociationType ) {
|
||||
throw new MappingException(
|
||||
|
@ -2433,6 +2465,7 @@ public class HbmXmlTransformer {
|
|||
for ( JaxbHbmColumnType hbmColumn : hbmM2O.getColumn() ) {
|
||||
final JaxbJoinColumnImpl joinColumn = new JaxbJoinColumnImpl();
|
||||
joinColumn.setName( hbmColumn.getName() );
|
||||
joinColumn.setTable( currentTableName );
|
||||
joinColumn.setNullable( hbmColumn.isNotNull() == null ? null : !hbmColumn.isNotNull() );
|
||||
joinColumn.setUnique( hbmColumn.isUnique() );
|
||||
m2o.getJoinColumns().add( joinColumn );
|
||||
|
@ -2447,6 +2480,7 @@ public class HbmXmlTransformer {
|
|||
else {
|
||||
joinColumn.setName( hbmM2O.getColumnAttribute() );
|
||||
}
|
||||
joinColumn.setTable( currentTableName );
|
||||
m2o.getJoinColumns().add( joinColumn );
|
||||
}
|
||||
|
||||
|
@ -2469,6 +2503,9 @@ public class HbmXmlTransformer {
|
|||
origin
|
||||
);
|
||||
|
||||
|
||||
currentTableName = "";
|
||||
|
||||
subclassEntity.setProxy( hbmSubclass.getProxy() );
|
||||
transferBaseEntityInformation( hbmSubclass, subclassEntity );
|
||||
transferEntityElementAttributes( hbmSubclass, subclassEntity );
|
||||
|
|
|
@ -533,7 +533,8 @@ public interface HibernateAnnotations {
|
|||
);
|
||||
OrmAnnotationDescriptor<SecondaryRow,SecondaryRowAnnotation> SECONDARY_ROW = new OrmAnnotationDescriptor<>(
|
||||
SecondaryRow.class,
|
||||
SecondaryRowAnnotation.class
|
||||
SecondaryRowAnnotation.class,
|
||||
SECONDARY_ROWS
|
||||
);
|
||||
OrmAnnotationDescriptor<SelectBeforeUpdate,SelectBeforeUpdateAnnotation> SELECT_BEFORE_UPDATE = new OrmAnnotationDescriptor<>(
|
||||
SelectBeforeUpdate.class,
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.hibernate.annotations.CascadeType;
|
|||
import org.hibernate.annotations.NotFoundAction;
|
||||
import org.hibernate.annotations.Parameter;
|
||||
import org.hibernate.annotations.ResultCheckStyle;
|
||||
import org.hibernate.annotations.SecondaryRow;
|
||||
import org.hibernate.boot.jaxb.mapping.spi.JaxbAssociationOverrideImpl;
|
||||
import org.hibernate.boot.jaxb.mapping.spi.JaxbAttributeOverrideImpl;
|
||||
import org.hibernate.boot.jaxb.mapping.spi.JaxbBasicMapping;
|
||||
|
@ -126,6 +127,8 @@ import org.hibernate.boot.models.annotations.internal.PrimaryKeyJoinColumnsJpaAn
|
|||
import org.hibernate.boot.models.annotations.internal.RowIdAnnotation;
|
||||
import org.hibernate.boot.models.annotations.internal.SQLJoinTableRestrictionAnnotation;
|
||||
import org.hibernate.boot.models.annotations.internal.SQLRestrictionAnnotation;
|
||||
import org.hibernate.boot.models.annotations.internal.SecondaryRowAnnotation;
|
||||
import org.hibernate.boot.models.annotations.internal.SecondaryRowsAnnotation;
|
||||
import org.hibernate.boot.models.annotations.internal.SecondaryTableJpaAnnotation;
|
||||
import org.hibernate.boot.models.annotations.internal.SecondaryTablesJpaAnnotation;
|
||||
import org.hibernate.boot.models.annotations.internal.SequenceGeneratorJpaAnnotation;
|
||||
|
@ -172,10 +175,13 @@ import jakarta.persistence.UniqueConstraint;
|
|||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import static java.lang.Boolean.FALSE;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static org.hibernate.boot.models.HibernateAnnotations.FILTER;
|
||||
import static org.hibernate.boot.models.HibernateAnnotations.FILTER_JOIN_TABLE;
|
||||
import static org.hibernate.boot.models.HibernateAnnotations.PARAMETER;
|
||||
import static org.hibernate.boot.models.HibernateAnnotations.SECONDARY_ROW;
|
||||
import static org.hibernate.boot.models.HibernateAnnotations.SECONDARY_ROWS;
|
||||
import static org.hibernate.boot.models.HibernateAnnotations.SQL_RESTRICTION;
|
||||
import static org.hibernate.boot.models.JpaAnnotations.ASSOCIATION_OVERRIDE;
|
||||
import static org.hibernate.boot.models.JpaAnnotations.ASSOCIATION_OVERRIDES;
|
||||
|
@ -1672,16 +1678,29 @@ public class XmlAnnotationHelper {
|
|||
JpaAnnotations.SECONDARY_TABLES,
|
||||
xmlDocumentContext.getModelBuildingContext()
|
||||
);
|
||||
|
||||
final SecondaryTable[] tableUsages = new SecondaryTable[jaxbSecondaryTables.size()];
|
||||
tablesUsage.value( tableUsages );
|
||||
|
||||
final SecondaryRowsAnnotation rowsUsage = (SecondaryRowsAnnotation) target.replaceAnnotationUsage(
|
||||
SECONDARY_ROW,
|
||||
SECONDARY_ROWS,
|
||||
xmlDocumentContext.getModelBuildingContext()
|
||||
);
|
||||
final SecondaryRow[] rowUsages = new SecondaryRow[jaxbSecondaryTables.size()];
|
||||
rowsUsage.value( rowUsages );
|
||||
|
||||
for ( int i = 0; i < jaxbSecondaryTables.size(); i++ ) {
|
||||
final SecondaryTableJpaAnnotation tableUsage = SECONDARY_TABLE.createUsage( xmlDocumentContext.getModelBuildingContext() );
|
||||
tableUsages[i] = tableUsage;
|
||||
|
||||
final JaxbSecondaryTableImpl jaxbSecondaryTable = jaxbSecondaryTables.get( i );
|
||||
tableUsage.apply( jaxbSecondaryTable, xmlDocumentContext );
|
||||
|
||||
final SecondaryRowAnnotation rowUsage = SECONDARY_ROW.createUsage( xmlDocumentContext.getModelBuildingContext() );
|
||||
rowUsages[i] = rowUsage;
|
||||
rowUsage.table( tableUsage.name() );
|
||||
rowUsage.optional( jaxbSecondaryTable.isOptional() == TRUE );
|
||||
rowUsage.owned( jaxbSecondaryTable.isOwned() == TRUE );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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.boot.models.hbm.collections.list;
|
||||
|
||||
import jakarta.persistence.Embeddable;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Embeddable
|
||||
public class Category {
|
||||
private String name;
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "owner_fk")
|
||||
private User owner;
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* 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.boot.models.hbm.collections.list;
|
||||
|
||||
import org.hibernate.cfg.MappingSettings;
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.List;
|
||||
import org.hibernate.mapping.ManyToOne;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.Value;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.DomainModelScope;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.Setting;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@SuppressWarnings("JUnitMalformedDeclaration")
|
||||
public class ListTests {
|
||||
@Test
|
||||
@DomainModel( xmlMappings = "mappings/models/hbm/list/hbm.xml" )
|
||||
void testHbmXml(DomainModelScope domainModelScope) {
|
||||
final PersistentClass rootBinding = domainModelScope.getDomainModel().getEntityBinding( Root.class.getName() );
|
||||
validateTags( rootBinding.getProperty( "tags" ) );
|
||||
validateCategories( rootBinding.getProperty( "categories" ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
@ServiceRegistry( settings = @Setting( name = MappingSettings.TRANSFORM_HBM_XML, value = "true" ) )
|
||||
@DomainModel( xmlMappings = "mappings/models/hbm/list/hbm.xml" )
|
||||
void testTransformation(DomainModelScope domainModelScope) {
|
||||
final PersistentClass rootBinding = domainModelScope.getDomainModel().getEntityBinding( Root.class.getName() );
|
||||
validateTags( rootBinding.getProperty( "tags" ) );
|
||||
validateCategories( rootBinding.getProperty( "categories" ) );
|
||||
}
|
||||
|
||||
private void validateTags(Property tags) {
|
||||
final List listValue = (List) tags.getValue();
|
||||
|
||||
final Value indexValue = listValue.getIndex();
|
||||
assertThat( indexValue.getColumns() ).hasSize( 1 );
|
||||
|
||||
final Value elementValue = listValue.getElement();
|
||||
assertThat( elementValue.getColumns() ).hasSize( 1 );
|
||||
}
|
||||
|
||||
private void validateCategories(Property categories) {
|
||||
final List listValue = (List) categories.getValue();
|
||||
assertThat( listValue.getCollectionTable().getName() ).isEqualTo( "root_categories" );
|
||||
|
||||
final BasicValue indexValue = (BasicValue) listValue.getIndex();
|
||||
assertThat( indexValue.getColumns() ).hasSize( 1 );
|
||||
|
||||
final Component elementValue = (Component) listValue.getElement();
|
||||
assertThat( elementValue.getColumns() ).hasSize( 2 );
|
||||
assertThat( elementValue.getComponentClass() ).isEqualTo( Category.class );
|
||||
for ( Property subProperty : elementValue.getProperties() ) {
|
||||
if ( "name".equals( subProperty.getName() ) ) {
|
||||
validateCategoryName( subProperty );
|
||||
}
|
||||
else if ( "owner".equals( subProperty.getName() ) ) {
|
||||
validateCategoryOwner( subProperty );
|
||||
}
|
||||
else if ( "admins".equals( subProperty.getName() ) ) {
|
||||
validateAdmins( subProperty );
|
||||
}
|
||||
else {
|
||||
fail( "Unexpected Category property :" + subProperty.getName() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateCategoryName(Property nameProperty) {
|
||||
assertThat( nameProperty.getColumns() ).hasSize( 1 );
|
||||
assertThat( nameProperty.getColumns().get( 0 ).getName() ).isEqualTo( "name" );
|
||||
assertThat( nameProperty.getValue().getTable().getName() ).isEqualTo( "root_categories" );
|
||||
}
|
||||
|
||||
private void validateCategoryOwner(Property owenerProperty) {
|
||||
assertThat( owenerProperty.getColumns() ).hasSize( 1 );
|
||||
assertThat( owenerProperty.getColumns().get( 0 ).getName() ).isEqualTo( "owner_fk" );
|
||||
assertThat( owenerProperty.getValue().getTable().getName() ).isEqualTo( "root_categories" );
|
||||
|
||||
}
|
||||
|
||||
private void validateAdmins(Property adminsProperty) {
|
||||
assertThat( adminsProperty.getColumns() ).hasSize( 1 );
|
||||
assertThat( adminsProperty.getColumns().get( 0 ).getName() ).isEqualTo( "root_fk" );
|
||||
|
||||
final List listValue = (List) adminsProperty.getValue();
|
||||
assertThat( listValue.getCollectionTable().getName() ).isEqualTo( "root_admins" );
|
||||
|
||||
final BasicValue indexValue = (BasicValue) listValue.getIndex();
|
||||
assertThat( indexValue.getColumns() ).hasSize( 1 );
|
||||
|
||||
final ManyToOne element = (ManyToOne) listValue.getElement();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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.boot.models.hbm.collections.list;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.persistence.CollectionTable;
|
||||
import jakarta.persistence.ElementCollection;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Basic;
|
||||
import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.OrderColumn;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Entity
|
||||
public class Root {
|
||||
@Id
|
||||
private Integer id;
|
||||
@Basic
|
||||
private String name;
|
||||
@ElementCollection
|
||||
private List<String> tags;
|
||||
@ElementCollection
|
||||
@CollectionTable(name="root_categories")
|
||||
@OrderColumn(name = "position")
|
||||
private List<String> categories;
|
||||
@ManyToMany
|
||||
@CollectionTable(name="root_admins")
|
||||
private List<User> admins;
|
||||
|
||||
|
||||
protected Root() {
|
||||
// for Hibernate use
|
||||
}
|
||||
|
||||
public Root(Integer id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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.boot.models.hbm.collections.list;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Basic;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "`users`")
|
||||
public class User {
|
||||
@Id
|
||||
private Integer id;
|
||||
@Basic
|
||||
private String name;
|
||||
|
||||
protected User() {
|
||||
// for Hibernate use
|
||||
}
|
||||
|
||||
public User(Integer id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* 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.boot.models.hbm.join;
|
||||
|
||||
import jakarta.persistence.Embeddable;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Embeddable
|
||||
public class Data {
|
||||
private String first;
|
||||
private String second;
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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.boot.models.hbm.join;
|
||||
|
||||
import jakarta.persistence.Embedded;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Basic;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Entity
|
||||
public class Person {
|
||||
@Id
|
||||
private Integer id;
|
||||
@Basic
|
||||
private String name;
|
||||
private String stuff;
|
||||
@ManyToOne
|
||||
private SupplementalDetails details;
|
||||
@Embedded
|
||||
private Data data;
|
||||
private String datum;
|
||||
|
||||
protected Person() {
|
||||
// for Hibernate use
|
||||
}
|
||||
|
||||
public Person(Integer id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* 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.boot.models.hbm.join;
|
||||
|
||||
import org.hibernate.cfg.MappingSettings;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.Join;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.DomainModelScope;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.Setting;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@SuppressWarnings("JUnitMalformedDeclaration")
|
||||
public class SecondaryTableTests {
|
||||
@Test
|
||||
@DomainModel(xmlMappings = "mappings/models/hbm/join/hbm.xml")
|
||||
void baseline(DomainModelScope domainModelScope) {
|
||||
verifyModel( domainModelScope.getDomainModel().getEntityBinding( Person.class.getName() ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
@DomainModel(xmlMappings = "mappings/models/hbm/join/mapping.xml")
|
||||
void testMappingXml(DomainModelScope domainModelScope) {
|
||||
verifyModel( domainModelScope.getDomainModel().getEntityBinding( Person.class.getName() ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
@ServiceRegistry(settings = @Setting(name = MappingSettings.TRANSFORM_HBM_XML, value = "true"))
|
||||
@DomainModel(xmlMappings = "mappings/models/hbm/join/hbm.xml")
|
||||
void testJoinTransformations(DomainModelScope domainModelScope) {
|
||||
verifyModel( domainModelScope.getDomainModel().getEntityBinding( Person.class.getName() ) );
|
||||
}
|
||||
|
||||
private void verifyModel(PersistentClass entityBinding) {
|
||||
assertThat( entityBinding.getJoins() ).hasSize( 2 );
|
||||
|
||||
for ( Join join : entityBinding.getJoins() ) {
|
||||
if ( "supplemental1".equals( join.getTable().getName() ) ) {
|
||||
verifySupplemental1( join );
|
||||
}
|
||||
else if ( "supplemental2".equals( join.getTable().getName() ) ) {
|
||||
verifySupplemental2( join );
|
||||
}
|
||||
else {
|
||||
fail( "Unexpected secondary table : " + join.getTable().getName() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void verifySupplemental1(Join join) {
|
||||
assertThat( join.isOptional() ).isFalse();
|
||||
assertThat( join.isInverse() ).isFalse();
|
||||
|
||||
assertThat( join.getKey().getColumns() ).hasSize( 1 );
|
||||
assertThat( join.getKey().getColumns().get(0).getName() ).isEqualTo( "supp1_fk" );
|
||||
|
||||
assertThat( join.getProperties() ).hasSize( 3 );
|
||||
for ( Property property : join.getProperties() ) {
|
||||
if ( "stuff".equals( property.getName() ) ) {
|
||||
validateStuffProperty( property );
|
||||
}
|
||||
else if ( "data".equals( property.getName() ) ) {
|
||||
validateDataProperty( property );
|
||||
}
|
||||
else if ( "details".equals( property.getName() ) ) {
|
||||
validateDetailsProperty( property );
|
||||
}
|
||||
else {
|
||||
fail( "Unexpected property : " + property.getName() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateStuffProperty(Property property) {
|
||||
assertThat( property.getValue().getTable().getName() ).isEqualTo( "supplemental1" );
|
||||
}
|
||||
|
||||
private void validateDataProperty(Property property) {
|
||||
assertThat( property.getValue().getTable().getName() ).isEqualTo( "supplemental1" );
|
||||
assertThat( property.getValue() ).isInstanceOf( Component.class );
|
||||
final Component component = (Component) property.getValue();
|
||||
for ( Property subProperty : component.getProperties() ) {
|
||||
assertThat( subProperty.getValue().getTable().getName() ).isEqualTo( "supplemental1" );
|
||||
}
|
||||
}
|
||||
|
||||
private void validateDetailsProperty(Property property) {
|
||||
assertThat( property.getValue().getTable().getName() ).isEqualTo( "supplemental1" );
|
||||
}
|
||||
|
||||
private void verifySupplemental2(Join join) {
|
||||
assertThat( join.isOptional() ).isTrue();
|
||||
assertThat( join.isInverse() ).isTrue();
|
||||
|
||||
assertThat( join.getKey().getColumns() ).hasSize( 1 );
|
||||
assertThat( join.getKey().getColumns().get(0).getName() ).isEqualTo( "supp2_fk" );
|
||||
|
||||
assertThat( join.getProperties() ).hasSize( 1 );
|
||||
assertThat( join.getProperties().get(0).getName() ).isEqualTo( "datum" );
|
||||
assertThat( join.getProperties().get(0).getValue().getTable().getName() ).isEqualTo( "supplemental2" );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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.boot.models.hbm.join;
|
||||
|
||||
import jakarta.persistence.Basic;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Entity
|
||||
public class SupplementalDetails {
|
||||
@Id
|
||||
private Integer id;
|
||||
@Basic
|
||||
private String name;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests for transforming {@code <join/>} -> {@code <secondary-table/>}.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
package org.hibernate.orm.test.boot.models.hbm.join;
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.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.
|
||||
-->
|
||||
|
||||
<!DOCTYPE hibernate-mapping PUBLIC
|
||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping
|
||||
package="org.hibernate.orm.test.boot.models.hbm.join"
|
||||
default-access="field">
|
||||
|
||||
<class name="Person">
|
||||
<id name="id"/>
|
||||
<property name="name" type="string"/>
|
||||
<join table="supplemental1">
|
||||
<key column="supp1_fk"/>
|
||||
<property name="stuff" type="string"/>
|
||||
<many-to-one name="details" entity-name="org.hibernate.orm.test.boot.models.hbm.join.SupplementalDetails" column="details_fk"/>
|
||||
<component name="data" class="Data">
|
||||
<property name="first" type="string"/>
|
||||
<property name="second" type="string"/>
|
||||
</component>
|
||||
</join>
|
||||
<join table="supplemental2" inverse="true" optional="true">
|
||||
<key column="supp2_fk"/>
|
||||
<property name="datum" type="string"/>
|
||||
</join>
|
||||
</class>
|
||||
<class name="SupplementalDetails">
|
||||
<id type="integer"/>
|
||||
<property name="name" type="string"/>
|
||||
</class>
|
||||
</hibernate-mapping>
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.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.
|
||||
-->
|
||||
|
||||
<entity-mappings xmlns="http://www.hibernate.org/xsd/orm/mapping"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
version="7.0">
|
||||
<entity class="org.hibernate.orm.test.boot.models.hbm.join.Person" access="FIELD">
|
||||
<secondary-table name="supplemental1" optional="false" owned="true">
|
||||
<primary-key-join-column name="supp1_fk"/>
|
||||
</secondary-table>
|
||||
<secondary-table name="supplemental2" optional="true" owned="false">
|
||||
<primary-key-join-column name="supp2_fk"/>
|
||||
</secondary-table>
|
||||
|
||||
<attributes>
|
||||
<id name="id"/>
|
||||
<basic name="name"/>
|
||||
<basic name="stuff">
|
||||
<column table="supplemental1"/>
|
||||
</basic>
|
||||
<basic name="datum">
|
||||
<column table="supplemental2"/>
|
||||
</basic>
|
||||
<many-to-one name="details" target-entity="org.hibernate.orm.test.boot.models.hbm.join.SupplementalDetails">
|
||||
<join-column table="supplemental1"/>
|
||||
</many-to-one>
|
||||
<embedded name="data">
|
||||
<target>org.hibernate.orm.test.boot.models.hbm.join.Data</target>
|
||||
<attribute-override name="first">
|
||||
<column table="supplemental1"/>
|
||||
</attribute-override>
|
||||
<attribute-override name="second">
|
||||
<column table="supplemental1"/>
|
||||
</attribute-override>
|
||||
</embedded>
|
||||
</attributes>
|
||||
</entity>
|
||||
<entity class="org.hibernate.orm.test.boot.models.hbm.join.SupplementalDetails">
|
||||
<attributes>
|
||||
<id name="id"/>
|
||||
<basic name="name"/>
|
||||
</attributes>
|
||||
</entity>
|
||||
<embeddable class="org.hibernate.orm.test.boot.models.hbm.join.Data">
|
||||
<attributes>
|
||||
<basic name="first"/>
|
||||
<basic name="second"/>
|
||||
</attributes>
|
||||
</embeddable>
|
||||
</entity-mappings>
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.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.
|
||||
-->
|
||||
|
||||
<!DOCTYPE hibernate-mapping PUBLIC
|
||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping default-access="FIELD">
|
||||
|
||||
<class name="org.hibernate.orm.test.boot.models.hbm.collections.list.Root">
|
||||
<id type="integer"/>
|
||||
<property name="name" type="string"/>
|
||||
<list name="tags">
|
||||
<key column="root_fk"/>
|
||||
<list-index/>
|
||||
<element column="txt" type="string"/>
|
||||
</list>
|
||||
<list name="categories" table="root_categories">
|
||||
<key column="root_fk"/>
|
||||
<list-index column="position"/>
|
||||
<composite-element class="org.hibernate.orm.test.boot.models.hbm.collections.list.Category">
|
||||
<property name="name"/>
|
||||
<many-to-one name="owner" class="org.hibernate.orm.test.boot.models.hbm.collections.list.User" column="owner_fk"/>
|
||||
</composite-element>
|
||||
</list>
|
||||
<list name="admins" table="root_admins">
|
||||
<key column="root_fk"/>
|
||||
<list-index/>
|
||||
<many-to-many class="org.hibernate.orm.test.boot.models.hbm.collections.list.User" column="user_fk"/>
|
||||
</list>
|
||||
</class>
|
||||
|
||||
<class name="org.hibernate.orm.test.boot.models.hbm.collections.list.User">
|
||||
<id/>
|
||||
<property name="name"/>
|
||||
</class>
|
||||
|
||||
</hibernate-mapping>
|
Loading…
Reference in New Issue