mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-27 14:30:16 +00:00
Removed unnecessary visitedNavigablePath from LoaderSelectBuilder and added bidirectionalPropertyName for circularity detection
This commit is contained in:
parent
6aefe00c1e
commit
3c7a208b96
@ -834,6 +834,17 @@ public static String nullIfEmpty(String value) {
|
||||
return isEmpty( value ) ? null : value;
|
||||
}
|
||||
|
||||
public static String subStringNullIfEmpty(String value, Character startChar) {
|
||||
if ( isEmpty( value ) ) {
|
||||
return null;
|
||||
}
|
||||
int index = value.indexOf( startChar );
|
||||
if ( index != -1 ) {
|
||||
return value.substring( index + 1 );
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static List<String> parseCommaSeparatedString(String incomingString) {
|
||||
return CommaSeparatedStringHelper.parseCommaSeparatedString( incomingString );
|
||||
}
|
||||
|
@ -82,8 +82,6 @@
|
||||
public class LoaderSelectBuilder {
|
||||
private static final Logger log = Logger.getLogger( LoaderSelectBuilder.class );
|
||||
|
||||
private HashMap<String, List<Fetch>> visitedNavigablePath = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Create an SQL AST select-statement based on matching one-or-more keys
|
||||
*
|
||||
@ -435,10 +433,6 @@ private List<Fetch> visitFetches(FetchParent fetchParent, QuerySpec querySpec, L
|
||||
|
||||
final List<Fetch> fetches = new ArrayList<>();
|
||||
String fullPath = fetchParent.getNavigablePath().getFullPath();
|
||||
final List<Fetch> fullPathFetches = visitedNavigablePath.get( fullPath );
|
||||
if ( fullPathFetches != null ) {
|
||||
return fullPathFetches;
|
||||
}
|
||||
|
||||
final BiConsumer<Fetchable, Boolean> processor = createFetchableBiConsumer( fetchParent, querySpec, creationState, fetches );
|
||||
|
||||
@ -449,7 +443,6 @@ private List<Fetch> visitFetches(FetchParent fetchParent, QuerySpec querySpec, L
|
||||
}
|
||||
referencedMappingContainer.visitFetchables(
|
||||
fetchable -> processor.accept( fetchable, false ), null );
|
||||
visitedNavigablePath.put( fullPath, fetches );
|
||||
return fetches;
|
||||
}
|
||||
|
||||
@ -459,11 +452,11 @@ private BiConsumer<Fetchable, Boolean> createFetchableBiConsumer(
|
||||
LoaderSqlAstCreationState creationState,
|
||||
List<Fetch> fetches) {
|
||||
return (fetchable, isKeyFetchable) -> {
|
||||
NavigablePath navigablePath = fetchParent.getNavigablePath();
|
||||
NavigablePath panrentNavigablePath = fetchParent.getNavigablePath();
|
||||
if ( isKeyFetchable ) {
|
||||
navigablePath = navigablePath.append( EntityIdentifierMapping.ROLE_LOCAL_NAME );
|
||||
panrentNavigablePath = panrentNavigablePath.append( EntityIdentifierMapping.ROLE_LOCAL_NAME );
|
||||
}
|
||||
final NavigablePath fetchablePath = navigablePath.append( fetchable.getFetchableName() );
|
||||
final NavigablePath fetchablePath = panrentNavigablePath.append( fetchable.getFetchableName() );
|
||||
|
||||
final Fetch biDirectionalFetch = fetchable.resolveCircularFetch(
|
||||
fetchablePath,
|
||||
|
@ -56,5 +56,5 @@ default void visitFetchables(Consumer<Fetchable> fetchableConsumer, EntityMappin
|
||||
|
||||
String getSeparateCollectionTable();
|
||||
|
||||
String getMappedBy();
|
||||
String getBidirectionalPropertyName();
|
||||
}
|
||||
|
@ -18,11 +18,11 @@
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.jpa.spi.JpaCompliance;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.IndexedCollection;
|
||||
import org.hibernate.mapping.List;
|
||||
import org.hibernate.mapping.OneToOne;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||
@ -98,7 +98,7 @@ public interface Aware {
|
||||
private final FetchStyle fetchStyle;
|
||||
|
||||
private final CascadeStyle cascadeStyle;
|
||||
private final String mappedBy;
|
||||
private final String bidirectionalPropertyName;
|
||||
|
||||
private final CollectionPersister collectionDescriptor;
|
||||
private final String separateCollectionTable;
|
||||
@ -174,7 +174,8 @@ public PluralAttributeMappingImpl(
|
||||
this.fetchStyle = fetchStyle;
|
||||
this.cascadeStyle = cascadeStyle;
|
||||
this.collectionDescriptor = collectionDescriptor;
|
||||
this.mappedBy = bootDescriptor.getMappedByProperty();
|
||||
|
||||
this.bidirectionalPropertyName = StringHelper.subStringNullIfEmpty( bootDescriptor.getMappedByProperty(), '.');
|
||||
|
||||
this.sqlAliasStem = SqlAliasStemHelper.INSTANCE.generateStemFromAttributeName( attributeName );
|
||||
|
||||
@ -393,8 +394,8 @@ public String getSeparateCollectionTable() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMappedBy() {
|
||||
return mappedBy;
|
||||
public String getBidirectionalPropertyName() {
|
||||
return bidirectionalPropertyName;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -76,7 +76,7 @@ public enum Cardinality {
|
||||
private final boolean referringPrimaryKey;
|
||||
|
||||
private final Cardinality cardinality;
|
||||
private String mappedBy;
|
||||
private String bidirectionalPropertyName;
|
||||
|
||||
private ForeignKeyDescriptor foreignKeyDescriptor;
|
||||
private ForeignKeyDirection foreignKeyDirection;
|
||||
@ -126,12 +126,61 @@ public ToOneAttributeMapping(
|
||||
else {
|
||||
assert bootValue instanceof OneToOne;
|
||||
cardinality = Cardinality.ONE_TO_ONE;
|
||||
String mappedByProperty = ( (OneToOne) bootValue ).getMappedByProperty();
|
||||
|
||||
/*
|
||||
The otherSidePropertyName value is used to determine bidirectionality based on the navigablePath string
|
||||
|
||||
e.g.
|
||||
|
||||
class Card{
|
||||
@OneToMany( mappedBy = "card")
|
||||
Set<CardField> fields;
|
||||
}
|
||||
|
||||
class CardField{
|
||||
@ManyToOne(optional = false)
|
||||
Card card;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
Card card1;
|
||||
}
|
||||
|
||||
NavigablePath(CardField.card.fields) fields is consideredBidirectional
|
||||
NavigablePath(CardField.card1.fields) fields is NOT bidirectional
|
||||
|
||||
e.g. Embeddable case
|
||||
|
||||
class Card{
|
||||
@OneToMany( mappedBy = "primaryKey.card")
|
||||
Set<CardField> fields;
|
||||
}
|
||||
|
||||
class CardField{
|
||||
@EmbeddedId
|
||||
PrimaryKey primaryKey;
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
class PrimaryKey implements Serializable {
|
||||
@ManyToOne(optional = false)
|
||||
Card card;
|
||||
}
|
||||
|
||||
in such case the mappedBy is "primaryKey.card"
|
||||
the the navigable path is NavigablePath(Card.fields.{element}.{id}.card) and it does not contain the "primaryKey" part
|
||||
so in ored to recognize the bidirectionality the "primaryKey." is removed from the otherSidePropertyName value.
|
||||
*/
|
||||
|
||||
String mappedByProperty = StringHelper.subStringNullIfEmpty(
|
||||
( (OneToOne) bootValue ).getMappedByProperty(),
|
||||
'.'
|
||||
);
|
||||
|
||||
if ( mappedByProperty == null ) {
|
||||
mappedBy = StringHelper.nullIfEmpty( referencedPropertyName );
|
||||
bidirectionalPropertyName = StringHelper.subStringNullIfEmpty( referencedPropertyName, '.' );
|
||||
}
|
||||
else {
|
||||
mappedBy = mappedByProperty;
|
||||
bidirectionalPropertyName = mappedByProperty;
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,7 +242,7 @@ public Fetch resolveCircularFetch(
|
||||
modelPart = creationState.resolveModelPart( parent );
|
||||
}
|
||||
|
||||
if ( this.mappedBy != null && parent.getFullPath().endsWith( this.mappedBy ) ) {
|
||||
if ( this.bidirectionalPropertyName != null && parent.getFullPath().endsWith( this.bidirectionalPropertyName ) ) {
|
||||
/*
|
||||
class Child {
|
||||
@OneToOne(mappedBy = "biologicalChild")
|
||||
@ -220,7 +269,7 @@ class Mother {
|
||||
/*
|
||||
check if mappedBy is on the other side of the association
|
||||
*/
|
||||
final String otherSideMappedBy = getOtherSideMappedBy( modelPart, parent.getParent(), creationState );
|
||||
final String otherSideMappedBy = getOthrerSideMappedBy( modelPart, parent.getParent(), creationState );
|
||||
if ( otherSideMappedBy != null ) {
|
||||
/*
|
||||
class Child {
|
||||
@ -280,26 +329,30 @@ class Mother {
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getOtherSideMappedBy(
|
||||
private String getOthrerSideMappedBy(
|
||||
ModelPart modelPart,
|
||||
NavigablePath parentOfParent,
|
||||
DomainResultCreationState creationState) {
|
||||
if ( modelPart instanceof ToOneAttributeMapping ) {
|
||||
return ( (ToOneAttributeMapping) modelPart ).getMappedBy();
|
||||
return ( (ToOneAttributeMapping) modelPart ).getBidirectionalPropertyName();
|
||||
}
|
||||
|
||||
if ( modelPart instanceof PluralAttributeMapping ) {
|
||||
return ( (PluralAttributeMapping) modelPart ).getBidirectionalPropertyName();
|
||||
}
|
||||
|
||||
if ( modelPart instanceof EntityCollectionPart ) {
|
||||
if ( parentOfParent.getFullPath().endsWith( EntityIdentifierMapping.ROLE_LOCAL_NAME ) ) {
|
||||
parentOfParent = parentOfParent.getParent();
|
||||
}
|
||||
return ( (PluralAttributeMapping) creationState.resolveModelPart( parentOfParent ) ).getMappedBy();
|
||||
return ( (PluralAttributeMapping) creationState.resolveModelPart( parentOfParent ) ).getBidirectionalPropertyName();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getMappedBy(){
|
||||
return mappedBy;
|
||||
public String getBidirectionalPropertyName(){
|
||||
return bidirectionalPropertyName;
|
||||
}
|
||||
|
||||
private Fetch createCircularBiDirectionalFetch(
|
||||
|
@ -82,7 +82,7 @@ public AbstractEntityResultGraphNode(
|
||||
}
|
||||
}
|
||||
else {
|
||||
identifierResult = entityDescriptor.getIdentifierMapping().createDomainResult(
|
||||
identifierResult = identifierMapping.createDomainResult(
|
||||
navigablePath.append( EntityIdentifierMapping.ROLE_LOCAL_NAME ),
|
||||
entityTableGroup,
|
||||
null,
|
||||
|
@ -43,7 +43,7 @@ public void initializeInstance(RowProcessingState rowProcessingState) {
|
||||
return;
|
||||
}
|
||||
final String entityName = concreteDescriptor.getEntityName();
|
||||
String uniqueKeyPropertyName = fetchedAttribute.getMappedBy();
|
||||
String uniqueKeyPropertyName = fetchedAttribute.getBidirectionalPropertyName();
|
||||
|
||||
final SharedSessionContractImplementor session = rowProcessingState.getSession();
|
||||
|
||||
|
@ -200,7 +200,6 @@ public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourcePr
|
||||
if ( initializer.getInitializedInstance() == null ) {
|
||||
initializer.resolveKey( rowProcessingState );
|
||||
initializer.resolveInstance( rowProcessingState );
|
||||
initializer.initializeInstance( rowProcessingState );
|
||||
}
|
||||
return initializer.getInitializedInstance();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user