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.List;
|
||||
import java.util.UUID;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
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.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.generator.Generator;
|
||||
import org.hibernate.id.OptimizableGenerator;
|
||||
import org.hibernate.id.enhanced.Optimizer;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
|
@ -27,23 +29,25 @@ import org.hibernate.mapping.Collection;
|
|||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.Contributable;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.Selectable;
|
||||
import org.hibernate.mapping.SimpleValue;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.SingleTableEntityPersister;
|
||||
import org.hibernate.generator.Generator;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import static org.hibernate.boot.model.internal.BinderHelper.findPropertyByName;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
* @author Christian Beikov
|
||||
|
@ -198,61 +202,98 @@ public class TemporaryTable implements Exportable, Contributable {
|
|||
);
|
||||
}
|
||||
|
||||
entityDescriptor.visitSubTypeAttributeMappings(
|
||||
attribute -> {
|
||||
if ( attribute instanceof PluralAttributeMapping ) {
|
||||
final PluralAttributeMapping pluralAttribute = (PluralAttributeMapping) attribute;
|
||||
|
||||
if ( pluralAttribute.getSeparateCollectionTable() != null ) {
|
||||
// Ensure that the FK target columns are available
|
||||
ForeignKeyDescriptor keyDescriptor = pluralAttribute.getKeyDescriptor();
|
||||
if ( keyDescriptor == null ) {
|
||||
// This is expected to happen when processing a
|
||||
// PostInitCallbackEntry because the callbacks
|
||||
// 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()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
visitPluralAttributes( entityDescriptor, (pluralAttribute, attributeName) -> {
|
||||
if ( pluralAttribute.getSeparateCollectionTable() != null ) {
|
||||
// Ensure that the FK target columns are available
|
||||
final ForeignKeyDescriptor keyDescriptor = pluralAttribute.getKeyDescriptor();
|
||||
if ( keyDescriptor == null ) {
|
||||
// This is expected to happen when processing a
|
||||
// PostInitCallbackEntry because the callbacks
|
||||
// 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 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;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
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(
|
||||
EntityMappingType entityDescriptor,
|
||||
Function<String, String> temporaryTableNameAdjuster,
|
||||
|
@ -356,8 +397,9 @@ public class TemporaryTable implements Exportable, Contributable {
|
|||
entityDescriptor.visitSubTypeAttributeMappings(
|
||||
attribute -> {
|
||||
if ( !( attribute instanceof PluralAttributeMapping ) ) {
|
||||
final SimpleValue value = (SimpleValue) entityBinding.getSubclassProperty( attribute.getAttributeName() )
|
||||
.getValue();
|
||||
final PersistentClass declaringClass = runtimeModelCreationContext.getBootModel()
|
||||
.getEntityBinding( attribute.findContainingEntityMapping().getEntityName() );
|
||||
final SimpleValue value = (SimpleValue) declaringClass.getProperty( attribute.getAttributeName() ).getValue();
|
||||
final Iterator<Selectable> columnIterator = value.getConstraintColumnIterator();
|
||||
attribute.forEachSelectable(
|
||||
(columnIndex, selection) -> {
|
||||
|
|
|
@ -644,6 +644,7 @@ public abstract class PersistentClass implements IdentifiableTypeClass, Attribut
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated(since = "6.2")
|
||||
public Property getSubclassProperty(String propertyName) throws MappingException {
|
||||
final Property identifierProperty = getIdentifierProperty();
|
||||
if ( identifierProperty != null
|
||||
|
|
|
@ -17,11 +17,15 @@ import org.junit.jupiter.api.AfterAll;
|
|||
import org.junit.jupiter.api.BeforeAll;
|
||||
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.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Inheritance;
|
||||
import jakarta.persistence.InheritanceType;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.Table;
|
||||
|
@ -31,14 +35,15 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
/**
|
||||
* @author Marco Belladelli
|
||||
*/
|
||||
@DomainModel(annotatedClasses = {
|
||||
@DomainModel( annotatedClasses = {
|
||||
JoinedInheritanceSameAttributeNameTest.BaseObj.class,
|
||||
JoinedInheritanceSameAttributeNameTest.Comment.class,
|
||||
JoinedInheritanceSameAttributeNameTest.Author.class,
|
||||
JoinedInheritanceSameAttributeNameTest.Post.class,
|
||||
JoinedInheritanceSameAttributeNameTest.Author.class
|
||||
})
|
||||
JoinedInheritanceSameAttributeNameTest.AuthorEmbedded.class,
|
||||
} )
|
||||
@SessionFactory
|
||||
@JiraKey("HHH-16166")
|
||||
@JiraKey( "HHH-16166" )
|
||||
public class JoinedInheritanceSameAttributeNameTest {
|
||||
@BeforeAll
|
||||
public void setUp(SessionFactoryScope scope) {
|
||||
|
@ -51,6 +56,8 @@ public class JoinedInheritanceSameAttributeNameTest {
|
|||
session.persist( post );
|
||||
session.persist( comment );
|
||||
session.persist( author );
|
||||
final AuthorEmbedded authorEmbedded = new AuthorEmbedded( "Andrea", "comments" );
|
||||
session.persist( authorEmbedded );
|
||||
} );
|
||||
}
|
||||
|
||||
|
@ -76,8 +83,8 @@ public class JoinedInheritanceSameAttributeNameTest {
|
|||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "BaseObj")
|
||||
@Inheritance(strategy = InheritanceType.JOINED)
|
||||
@Entity( name = "BaseObj" )
|
||||
@Inheritance( strategy = InheritanceType.JOINED )
|
||||
public static class BaseObj {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
|
@ -94,8 +101,8 @@ public class JoinedInheritanceSameAttributeNameTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Comment")
|
||||
@Table(name = "Comments")
|
||||
@Entity( name = "Comment" )
|
||||
@Table( name = "Comments" )
|
||||
public static class Comment extends BaseObj {
|
||||
@ManyToOne
|
||||
private Post post;
|
||||
|
@ -124,9 +131,9 @@ public class JoinedInheritanceSameAttributeNameTest {
|
|||
* This sub-entity has the same attribute name
|
||||
* as {@link Author} but with a different (Collection) type
|
||||
*/
|
||||
@Entity(name = "Post")
|
||||
@Entity( name = "Post" )
|
||||
public static class Post extends BaseObj {
|
||||
@OneToMany(mappedBy = "post")
|
||||
@OneToMany( mappedBy = "post" )
|
||||
private Set<Comment> comments;
|
||||
|
||||
public Post() {
|
||||
|
@ -142,7 +149,7 @@ public class JoinedInheritanceSameAttributeNameTest {
|
|||
* This sub-entity has the same attribute name
|
||||
* as {@link Post} but with a different (SimpleValue) type
|
||||
*/
|
||||
@Entity(name = "Author")
|
||||
@Entity( name = "Author" )
|
||||
public static class Author extends BaseObj {
|
||||
private String comments;
|
||||
|
||||
|
@ -161,4 +168,75 @@ public class JoinedInheritanceSameAttributeNameTest {
|
|||
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