Yoann Rodière (
https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%...
) *created* an issue
Hibernate ORM (
https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiOTE3ZTFmZjc0...
) / Bug (
https://hibernate.atlassian.net/browse/HHH-16209?atlOrigin=eyJpIjoiOTE3ZT...
) HHH-16209 (
https://hibernate.atlassian.net/browse/HHH-16209?atlOrigin=eyJpIjoiOTE3ZT...
) Identically-named association in entity root and embeddable leads to mixup during
association loading (
https://hibernate.atlassian.net/browse/HHH-16209?atlOrigin=eyJpIjoiOTE3ZT...
)
Issue Type: Bug Affects Versions: 6.2.0.CR2 Assignee: Unassigned Components:
hibernate-core Created: 21/Feb/2023 02:31 AM Fix Versions: 6.2.0 Priority: Major Reporter:
Yoann Rodière (
https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%...
)
I personally encountered this problem while trying to remove a workaround for
https://hibernate.atlassian.net/browse/HHH-15604 (
https://hibernate.atlassian.net/browse/HHH-15604 ) , which was fixed. It seems we have a
similar bug on embeddeds ( HHH-15604 (
https://hibernate.atlassian.net/browse/HHH-15604 )
Resolved was about element collections of embeddeds, which I guess are treated
differently).
Affects 6.2.0.CR2 and the latest main (commit 100d9351cdcc6afa6120ee321c8f2bb07e13fdcb)
for sure. Don’t know about 6.1. There seem to be different problems on 5.6, but personally
I never encountered them, so let’s focus on 6.2?
The following model will cause Hibernate ORM to mix up associations from the root entity
and the embedddables, eventually leading to incorrect loading of associations. Judging
from SQL logs, persisting associations seems to work fine.
@Entity(name = "entityA")
public static class EntityA {
@Id
private Integer id;
@OneToOne(mappedBy = "identicallyNamedAssociationFromB")
private EntityB identicallyNamedAssociationFromA;
@Embedded
private EmbeddableA embeddableA;
@Override
public String toString() {
return "EntityB{" +
"id=" + id +
", identicallyNamedAssociationFromA=" +
identicallyNamedAssociationFromA.getId() +
", embeddableA=" + embeddableA +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public EntityB getIdenticallyNamedAssociationFromA() {
return identicallyNamedAssociationFromA;
}
public void setIdenticallyNamedAssociationFromA(EntityB
identicallyNamedAssociationFromA) {
this.identicallyNamedAssociationFromA = identicallyNamedAssociationFromA;
}
public EmbeddableA getEmbeddableA() {
return embeddableA;
}
public void setEmbeddableA(EmbeddableA embeddableA) {
this.embeddableA = embeddableA;
}
}
@Embeddable
public static class EmbeddableA {
@OneToOne(mappedBy = "embeddableB.identicallyNamedAssociationFromB")
private EntityB identicallyNamedAssociationFromA;
@Override
public String toString() {
return "EmbeddableA{" +
", identicallyNamedAssociationFromA=" +
identicallyNamedAssociationFromA.getId() +
'}';
}
public EntityB getIdenticallyNamedAssociationFromA() {
return identicallyNamedAssociationFromA;
}
public void setIdenticallyNamedAssociationFromA(EntityB a) {
this.identicallyNamedAssociationFromA = a;
}
}
@Entity(name = "entityB")
public static class EntityB {
@Id
private Integer id;
@OneToOne
@JoinColumn(name = "entityA_id")
private EntityA identicallyNamedAssociationFromB;
@Embedded
private EmbeddableB embeddableB;
@Override
public String toString() {
return "EntityB{" +
"id=" + id +
", identicallyNamedAssociationFromB=" +
identicallyNamedAssociationFromB.getId() +
", embeddableB=" + embeddableB +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public EntityA getIdenticallyNamedAssociationFromB() {
return identicallyNamedAssociationFromB;
}
public void setIdenticallyNamedAssociationFromB(EntityA a) {
this.identicallyNamedAssociationFromB = a;
}
public EmbeddableB getEmbeddableB() {
return embeddableB;
}
public void setEmbeddableB(EmbeddableB embeddableB) {
this.embeddableB = embeddableB;
}
}
@Embeddable
public static class EmbeddableB {
@OneToOne
@JoinColumn(name = "emb_entityA_id")
private EntityA identicallyNamedAssociationFromB;
@Override
public String toString() {
return "EmbeddableB{" +
", identicallyNamedAssociationFromB=" +
identicallyNamedAssociationFromB.getId() +
'}';
}
public EntityA getIdenticallyNamedAssociationFromB() {
return identicallyNamedAssociationFromB;
}
public void setIdenticallyNamedAssociationFromB(EntityA a) {
this.identicallyNamedAssociationFromB = a;
}
}
Note the situation exposed in this issue seems a bit exotic, but it hints at mixups in
Hibernate ORM internals which could have more widespread consequences, so I think it’s
still worth fixing.
I will provide a reproducer soon.
(
https://hibernate.atlassian.net/browse/HHH-16209#add-comment?atlOrigin=ey...
) Add Comment (
https://hibernate.atlassian.net/browse/HHH-16209#add-comment?atlOrigin=ey...
)
Get Jira notifications on your phone! Download the Jira Cloud app for Android (
https://play.google.com/store/apps/details?id=com.atlassian.android.jira....
) or iOS (
https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=Em...
) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100216- sha1:3fa9804 )