HHH-16166 Change subtype property access and deprecate unused method in PersistentClass
This commit is contained in:
parent
06490876d6
commit
d6b5357c7b
|
@ -10,6 +10,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import org.hibernate.boot.model.naming.Identifier;
|
import org.hibernate.boot.model.naming.Identifier;
|
||||||
|
@ -18,6 +19,7 @@ import org.hibernate.boot.model.relational.QualifiedNameParser;
|
||||||
import org.hibernate.boot.model.relational.QualifiedTableName;
|
import org.hibernate.boot.model.relational.QualifiedTableName;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.jdbc.Size;
|
import org.hibernate.engine.jdbc.Size;
|
||||||
|
import org.hibernate.generator.Generator;
|
||||||
import org.hibernate.id.OptimizableGenerator;
|
import org.hibernate.id.OptimizableGenerator;
|
||||||
import org.hibernate.id.enhanced.Optimizer;
|
import org.hibernate.id.enhanced.Optimizer;
|
||||||
import org.hibernate.internal.CoreLogging;
|
import org.hibernate.internal.CoreLogging;
|
||||||
|
@ -27,23 +29,25 @@ import org.hibernate.mapping.Collection;
|
||||||
import org.hibernate.mapping.Column;
|
import org.hibernate.mapping.Column;
|
||||||
import org.hibernate.mapping.Contributable;
|
import org.hibernate.mapping.Contributable;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
|
import org.hibernate.mapping.Property;
|
||||||
import org.hibernate.mapping.Selectable;
|
import org.hibernate.mapping.Selectable;
|
||||||
import org.hibernate.mapping.SimpleValue;
|
import org.hibernate.mapping.SimpleValue;
|
||||||
import org.hibernate.mapping.Value;
|
|
||||||
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
import org.hibernate.metamodel.mapping.ModelPart;
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
|
||||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.entity.SingleTableEntityPersister;
|
import org.hibernate.persister.entity.SingleTableEntityPersister;
|
||||||
import org.hibernate.generator.Generator;
|
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.StandardBasicTypes;
|
import org.hibernate.type.StandardBasicTypes;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
import static org.hibernate.boot.model.internal.BinderHelper.findPropertyByName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
* @author Christian Beikov
|
* @author Christian Beikov
|
||||||
|
@ -198,61 +202,98 @@ public class TemporaryTable implements Exportable, Contributable {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
entityDescriptor.visitSubTypeAttributeMappings(
|
visitPluralAttributes( entityDescriptor, (pluralAttribute, attributeName) -> {
|
||||||
attribute -> {
|
if ( pluralAttribute.getSeparateCollectionTable() != null ) {
|
||||||
if ( attribute instanceof PluralAttributeMapping ) {
|
// Ensure that the FK target columns are available
|
||||||
final PluralAttributeMapping pluralAttribute = (PluralAttributeMapping) attribute;
|
final ForeignKeyDescriptor keyDescriptor = pluralAttribute.getKeyDescriptor();
|
||||||
|
if ( keyDescriptor == null ) {
|
||||||
if ( pluralAttribute.getSeparateCollectionTable() != null ) {
|
// This is expected to happen when processing a
|
||||||
// Ensure that the FK target columns are available
|
// PostInitCallbackEntry because the callbacks
|
||||||
ForeignKeyDescriptor keyDescriptor = pluralAttribute.getKeyDescriptor();
|
// are not ordered. The exception is caught in
|
||||||
if ( keyDescriptor == null ) {
|
// MappingModelCreationProcess.executePostInitCallbacks()
|
||||||
// This is expected to happen when processing a
|
// and the callback is re-queued.
|
||||||
// PostInitCallbackEntry because the callbacks
|
throw new IllegalStateException( "Not yet ready: " + pluralAttribute );
|
||||||
// are not ordered. The exception is caught in
|
|
||||||
// MappingModelCreationProcess.executePostInitCallbacks()
|
|
||||||
// and the callback is re-queued.
|
|
||||||
throw new IllegalStateException( "Not yet ready: " + pluralAttribute );
|
|
||||||
}
|
|
||||||
final ModelPart fkTarget = keyDescriptor.getTargetPart();
|
|
||||||
if ( !fkTarget.isEntityIdentifierMapping() ) {
|
|
||||||
final Value value = entityBinding.getSubclassProperty( pluralAttribute.getAttributeName() )
|
|
||||||
.getValue();
|
|
||||||
final Iterator<Selectable> columnIterator =
|
|
||||||
( (Collection) value ).getKey().getColumnIterator();
|
|
||||||
fkTarget.forEachSelectable(
|
|
||||||
(columnIndex, selection) -> {
|
|
||||||
final Selectable selectable = columnIterator.next();
|
|
||||||
if ( selectable instanceof Column ) {
|
|
||||||
final Column column = (Column) selectable;
|
|
||||||
columns.add(
|
|
||||||
new TemporaryTableColumn(
|
|
||||||
temporaryTable,
|
|
||||||
column.getText( dialect ),
|
|
||||||
selection.getJdbcMapping(),
|
|
||||||
column.getSqlType(
|
|
||||||
runtimeModelCreationContext.getMetadata()
|
|
||||||
),
|
|
||||||
column.getColumnSize(
|
|
||||||
dialect,
|
|
||||||
runtimeModelCreationContext.getMetadata()
|
|
||||||
),
|
|
||||||
column.isNullable()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
final ModelPart fkTarget = keyDescriptor.getTargetPart();
|
||||||
|
if ( !fkTarget.isEntityIdentifierMapping() ) {
|
||||||
|
final PersistentClass declaringClass = runtimeModelCreationContext.getBootModel()
|
||||||
|
.getEntityBinding( pluralAttribute.findContainingEntityMapping().getEntityName() );
|
||||||
|
final Property property = findPropertyByName( declaringClass, attributeName );
|
||||||
|
assert property != null;
|
||||||
|
final Iterator<Selectable> columnIterator = ( (Collection) property.getValue() ).getKey().getColumnIterator();
|
||||||
|
fkTarget.forEachSelectable(
|
||||||
|
(columnIndex, selection) -> {
|
||||||
|
final Selectable selectable = columnIterator.next();
|
||||||
|
if ( selectable instanceof Column ) {
|
||||||
|
final Column column = (Column) selectable;
|
||||||
|
columns.add(
|
||||||
|
new TemporaryTableColumn(
|
||||||
|
temporaryTable,
|
||||||
|
column.getText( dialect ),
|
||||||
|
selection.getJdbcMapping(),
|
||||||
|
column.getSqlType(
|
||||||
|
runtimeModelCreationContext.getMetadata()
|
||||||
|
),
|
||||||
|
column.getColumnSize(
|
||||||
|
dialect,
|
||||||
|
runtimeModelCreationContext.getMetadata()
|
||||||
|
),
|
||||||
|
column.isNullable()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} );
|
||||||
return columns;
|
return columns;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void visitPluralAttributes(
|
||||||
|
EntityMappingType entityDescriptor,
|
||||||
|
BiConsumer<PluralAttributeMapping, String> consumer) {
|
||||||
|
entityDescriptor.visitSubTypeAttributeMappings(
|
||||||
|
attribute -> {
|
||||||
|
if ( attribute instanceof PluralAttributeMapping ) {
|
||||||
|
consumer.accept( (PluralAttributeMapping) attribute, attribute.getAttributeName() );
|
||||||
|
}
|
||||||
|
else if ( attribute instanceof EmbeddedAttributeMapping ) {
|
||||||
|
visitPluralAttributes(
|
||||||
|
(EmbeddedAttributeMapping) attribute,
|
||||||
|
attribute.getAttributeName(),
|
||||||
|
consumer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void visitPluralAttributes(
|
||||||
|
EmbeddedAttributeMapping attributeMapping,
|
||||||
|
String attributeName,
|
||||||
|
BiConsumer<PluralAttributeMapping, String> consumer) {
|
||||||
|
attributeMapping.visitSubParts(
|
||||||
|
modelPart -> {
|
||||||
|
if ( modelPart instanceof PluralAttributeMapping ) {
|
||||||
|
final PluralAttributeMapping pluralAttribute = (PluralAttributeMapping) modelPart;
|
||||||
|
consumer.accept( pluralAttribute, attributeName + "." + pluralAttribute.getAttributeName() );
|
||||||
|
}
|
||||||
|
else if ( modelPart instanceof EmbeddedAttributeMapping ) {
|
||||||
|
final EmbeddedAttributeMapping embeddedAttribute = (EmbeddedAttributeMapping) modelPart;
|
||||||
|
visitPluralAttributes(
|
||||||
|
embeddedAttribute,
|
||||||
|
attributeName + "." + embeddedAttribute.getAttributeName(),
|
||||||
|
consumer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public static TemporaryTable createEntityTable(
|
public static TemporaryTable createEntityTable(
|
||||||
EntityMappingType entityDescriptor,
|
EntityMappingType entityDescriptor,
|
||||||
Function<String, String> temporaryTableNameAdjuster,
|
Function<String, String> temporaryTableNameAdjuster,
|
||||||
|
@ -356,8 +397,9 @@ public class TemporaryTable implements Exportable, Contributable {
|
||||||
entityDescriptor.visitSubTypeAttributeMappings(
|
entityDescriptor.visitSubTypeAttributeMappings(
|
||||||
attribute -> {
|
attribute -> {
|
||||||
if ( !( attribute instanceof PluralAttributeMapping ) ) {
|
if ( !( attribute instanceof PluralAttributeMapping ) ) {
|
||||||
final SimpleValue value = (SimpleValue) entityBinding.getSubclassProperty( attribute.getAttributeName() )
|
final PersistentClass declaringClass = runtimeModelCreationContext.getBootModel()
|
||||||
.getValue();
|
.getEntityBinding( attribute.findContainingEntityMapping().getEntityName() );
|
||||||
|
final SimpleValue value = (SimpleValue) declaringClass.getProperty( attribute.getAttributeName() ).getValue();
|
||||||
final Iterator<Selectable> columnIterator = value.getConstraintColumnIterator();
|
final Iterator<Selectable> columnIterator = value.getConstraintColumnIterator();
|
||||||
attribute.forEachSelectable(
|
attribute.forEachSelectable(
|
||||||
(columnIndex, selection) -> {
|
(columnIndex, selection) -> {
|
||||||
|
|
|
@ -644,6 +644,7 @@ public abstract class PersistentClass implements IdentifiableTypeClass, Attribut
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated(since = "6.2")
|
||||||
public Property getSubclassProperty(String propertyName) throws MappingException {
|
public Property getSubclassProperty(String propertyName) throws MappingException {
|
||||||
final Property identifierProperty = getIdentifierProperty();
|
final Property identifierProperty = getIdentifierProperty();
|
||||||
if ( identifierProperty != null
|
if ( identifierProperty != null
|
||||||
|
|
|
@ -17,11 +17,15 @@ import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import jakarta.persistence.CollectionTable;
|
||||||
|
import jakarta.persistence.ElementCollection;
|
||||||
|
import jakarta.persistence.Embeddable;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.GeneratedValue;
|
import jakarta.persistence.GeneratedValue;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.Inheritance;
|
import jakarta.persistence.Inheritance;
|
||||||
import jakarta.persistence.InheritanceType;
|
import jakarta.persistence.InheritanceType;
|
||||||
|
import jakarta.persistence.JoinColumn;
|
||||||
import jakarta.persistence.ManyToOne;
|
import jakarta.persistence.ManyToOne;
|
||||||
import jakarta.persistence.OneToMany;
|
import jakarta.persistence.OneToMany;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
|
@ -31,14 +35,15 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
/**
|
/**
|
||||||
* @author Marco Belladelli
|
* @author Marco Belladelli
|
||||||
*/
|
*/
|
||||||
@DomainModel(annotatedClasses = {
|
@DomainModel( annotatedClasses = {
|
||||||
JoinedInheritanceSameAttributeNameTest.BaseObj.class,
|
JoinedInheritanceSameAttributeNameTest.BaseObj.class,
|
||||||
JoinedInheritanceSameAttributeNameTest.Comment.class,
|
JoinedInheritanceSameAttributeNameTest.Comment.class,
|
||||||
|
JoinedInheritanceSameAttributeNameTest.Author.class,
|
||||||
JoinedInheritanceSameAttributeNameTest.Post.class,
|
JoinedInheritanceSameAttributeNameTest.Post.class,
|
||||||
JoinedInheritanceSameAttributeNameTest.Author.class
|
JoinedInheritanceSameAttributeNameTest.AuthorEmbedded.class,
|
||||||
})
|
} )
|
||||||
@SessionFactory
|
@SessionFactory
|
||||||
@JiraKey("HHH-16166")
|
@JiraKey( "HHH-16166" )
|
||||||
public class JoinedInheritanceSameAttributeNameTest {
|
public class JoinedInheritanceSameAttributeNameTest {
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
public void setUp(SessionFactoryScope scope) {
|
public void setUp(SessionFactoryScope scope) {
|
||||||
|
@ -51,6 +56,8 @@ public class JoinedInheritanceSameAttributeNameTest {
|
||||||
session.persist( post );
|
session.persist( post );
|
||||||
session.persist( comment );
|
session.persist( comment );
|
||||||
session.persist( author );
|
session.persist( author );
|
||||||
|
final AuthorEmbedded authorEmbedded = new AuthorEmbedded( "Andrea", "comments" );
|
||||||
|
session.persist( authorEmbedded );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,8 +83,8 @@ public class JoinedInheritanceSameAttributeNameTest {
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity(name = "BaseObj")
|
@Entity( name = "BaseObj" )
|
||||||
@Inheritance(strategy = InheritanceType.JOINED)
|
@Inheritance( strategy = InheritanceType.JOINED )
|
||||||
public static class BaseObj {
|
public static class BaseObj {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue
|
@GeneratedValue
|
||||||
|
@ -94,8 +101,8 @@ public class JoinedInheritanceSameAttributeNameTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity(name = "Comment")
|
@Entity( name = "Comment" )
|
||||||
@Table(name = "Comments")
|
@Table( name = "Comments" )
|
||||||
public static class Comment extends BaseObj {
|
public static class Comment extends BaseObj {
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
private Post post;
|
private Post post;
|
||||||
|
@ -124,9 +131,9 @@ public class JoinedInheritanceSameAttributeNameTest {
|
||||||
* This sub-entity has the same attribute name
|
* This sub-entity has the same attribute name
|
||||||
* as {@link Author} but with a different (Collection) type
|
* as {@link Author} but with a different (Collection) type
|
||||||
*/
|
*/
|
||||||
@Entity(name = "Post")
|
@Entity( name = "Post" )
|
||||||
public static class Post extends BaseObj {
|
public static class Post extends BaseObj {
|
||||||
@OneToMany(mappedBy = "post")
|
@OneToMany( mappedBy = "post" )
|
||||||
private Set<Comment> comments;
|
private Set<Comment> comments;
|
||||||
|
|
||||||
public Post() {
|
public Post() {
|
||||||
|
@ -142,7 +149,7 @@ public class JoinedInheritanceSameAttributeNameTest {
|
||||||
* This sub-entity has the same attribute name
|
* This sub-entity has the same attribute name
|
||||||
* as {@link Post} but with a different (SimpleValue) type
|
* as {@link Post} but with a different (SimpleValue) type
|
||||||
*/
|
*/
|
||||||
@Entity(name = "Author")
|
@Entity( name = "Author" )
|
||||||
public static class Author extends BaseObj {
|
public static class Author extends BaseObj {
|
||||||
private String comments;
|
private String comments;
|
||||||
|
|
||||||
|
@ -161,4 +168,75 @@ public class JoinedInheritanceSameAttributeNameTest {
|
||||||
this.comments = comments;
|
this.comments = comments;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
public static class NestedEmbeddable {
|
||||||
|
@ElementCollection
|
||||||
|
@CollectionTable(
|
||||||
|
name = "author_comments",
|
||||||
|
joinColumns = @JoinColumn( name = "name", referencedColumnName = "name" )
|
||||||
|
)
|
||||||
|
private Set<String> comments;
|
||||||
|
|
||||||
|
private Integer testProperty;
|
||||||
|
|
||||||
|
public NestedEmbeddable() {
|
||||||
|
comments = new HashSet<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getComments() {
|
||||||
|
return comments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setComments(Set<String> comments) {
|
||||||
|
this.comments = comments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getTestProperty() {
|
||||||
|
return testProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTestProperty(Integer testProperty) {
|
||||||
|
this.testProperty = testProperty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
public static class AuthorEmbeddable {
|
||||||
|
private NestedEmbeddable nestedEmbeddable;
|
||||||
|
|
||||||
|
public AuthorEmbeddable() {
|
||||||
|
this.nestedEmbeddable = new NestedEmbeddable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public NestedEmbeddable getNestedEmbeddable() {
|
||||||
|
return nestedEmbeddable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNestedEmbeddable(NestedEmbeddable nestedEmbeddable) {
|
||||||
|
this.nestedEmbeddable = nestedEmbeddable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "AuthorEmbedded" )
|
||||||
|
public static class AuthorEmbedded extends BaseObj {
|
||||||
|
private AuthorEmbeddable authorEmbeddable;
|
||||||
|
|
||||||
|
public AuthorEmbedded() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthorEmbedded(String name, String comment) {
|
||||||
|
setName( name );
|
||||||
|
this.authorEmbeddable = new AuthorEmbeddable();
|
||||||
|
this.authorEmbeddable.getNestedEmbeddable().getComments().add( comment );
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthorEmbeddable getAuthorEmbeddable() {
|
||||||
|
return authorEmbeddable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthorEmbeddable(AuthorEmbeddable authorEmbeddable) {
|
||||||
|
this.authorEmbeddable = authorEmbeddable;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue