[JIRA] (HHH-16438) Left outer joins do not work with polymorphic entities due to use of discriminator in the main query condition
by Jones (JIRA)
Jones ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... ) *updated* an issue
Hibernate ORM ( https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiYzBlYTU3ZDY1... ) / Bug ( https://hibernate.atlassian.net/browse/HHH-16438?atlOrigin=eyJpIjoiYzBlYT... ) HHH-16438 ( https://hibernate.atlassian.net/browse/HHH-16438?atlOrigin=eyJpIjoiYzBlYT... ) Left outer joins do not work with polymorphic entities due to use of discriminator in the main query condition ( https://hibernate.atlassian.net/browse/HHH-16438?atlOrigin=eyJpIjoiYzBlYT... )
Change By: Jones ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... )
Given
* A simple entity
* A polymorphic entity
When
* querying the simple entity doing a left join with the polymorphic entity
Then
* The results will always be empty when the left joined entity is not present
{code:java}@Entity
@Table(name = "ENTITY_B")
public class EntityB {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
private Integer id;
@Column(name = "SOME_ID")
private Integer someId;
}{code}
{code:java}@Entity
@Table(name = "ENTITY_A")
@DiscriminatorColumn(name = "DISC_COL", discriminatorType = DiscriminatorType.INTEGER)
public abstract class AbstractEntityA {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
Integer id;
}{code}
{code:java}@Entity
@DiscriminatorValue("1")
public class EntityAChildOne extends AbstractEntityA {}{code}
{code:java} @Test
public void hhhXXXXTest() throws Exception {
try (Session s = openSession()) {
Transaction tx = s.beginTransaction();
EntityB entityB = new EntityB();
s.persist(entityB);
tx.commit();
}
try (Session s = openSession()) {
Query<EntityB> query = s.createQuery(
"select b from EntityB b left outer join EntityAChildOne a1 on a1.id = b.someId", EntityB.class);
List<EntityB> actual = query.list();
assertThat(actual).hasSize(1);
}
}{code}
{noformat}java.lang.AssertionError:
Expected size:<1> but was:<0> in:
<[]>
at org.hibernate.bugs.ORMUnitTestCase.hhhXXXXTest(ORMUnitTestCase.java:76)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.hibernate.testing.junit4.ExtendedFrameworkMethod.invokeExplosively(ExtendedFrameworkMethod.java:45)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:299)
at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:293)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.lang.Thread.run(Thread.java:833){noformat}
In hibernate 5.6.15, this example just works, because hibernate 5 completely ignores the discriminator when generating the SQL (might be a limitation or a bug), but the expected outcome for the example is kept and we get the expected result which is the single list with the entity b in it:
{noformat}Hibernate 5.6.15:
select
entityb0_.ID as id1_1_,
entityb0_.SOME_ID as some_id2_1_
from
MY_TABLE entityb0_
left outer join
ENTITY_A entityachi1_
on (
entityachi1_.ID=entityb0_.SOME_ID
){noformat}
In hibernate 6.2.0, the resulting list will always be empty, because hibernate 6 does not ignore the discriminator, but adds it to the main query criteria (this part is the wrong part). Since this is a left join, the joined entity is optional and adding the discriminator criteria to the main part of the query will result to empty when the joined entity is not present.
{noformat}Hibernate 6.2.0:
select
e1_0.ID,
e1_0.SOME_ID
from
MY_TABLE e1_0
left join
ENTITY_A e2_0
on e2_0.ID=e1_0.SOME_ID
where
e2_0.DISC_COL=1{noformat}
A failing test scenario is to be attached and also available here [https://github.com/ratoaq2/HHH-16438|https://github.com/ratoaq2/HHH-16438...]
( https://hibernate.atlassian.net/browse/HHH-16438#add-comment?atlOrigin=ey... ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-16438#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=EmailN... ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100221- sha1:78e8bd6 )
3 years
[JIRA] (HHH-16438) Left outer joins do not work with polymorphic entities due to use of discriminator in the main query condition
by Jones (JIRA)
Jones ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... ) *created* an issue
Hibernate ORM ( https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiMTVhZmI5NzBl... ) / Bug ( https://hibernate.atlassian.net/browse/HHH-16438?atlOrigin=eyJpIjoiMTVhZm... ) HHH-16438 ( https://hibernate.atlassian.net/browse/HHH-16438?atlOrigin=eyJpIjoiMTVhZm... ) Left outer joins do not work with polymorphic entities due to use of discriminator in the main query condition ( https://hibernate.atlassian.net/browse/HHH-16438?atlOrigin=eyJpIjoiMTVhZm... )
Issue Type: Bug Affects Versions: 6.2.0 Assignee: Unassigned Created: 05/Apr/2023 02:13 AM Priority: Critical Reporter: Jones ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... )
Given
* A simple entity
* A polymorphic entity
When
* querying the simple entity doing a left join with the polymorphic entity
Then
* The results will always be empty when the left joined entity is not present
@Entity
@Table(name = "ENTITY_B" )
public class EntityB {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID" )
private Integer id;
@Column(name = "SOME_ID" )
private Integer someId;
}
@Entity
@Table(name = "ENTITY_A" )
@DiscriminatorColumn(name = "DISC_COL" , discriminatorType = DiscriminatorType.INTEGER)
public abstract class AbstractEntityA {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID" )
Integer id;
}
@Entity
@DiscriminatorValue( "1" )
public class EntityAChildOne extends AbstractEntityA {}
@Test
public void hhhXXXXTest() throws Exception {
try (Session s = openSession()) {
Transaction tx = s.beginTransaction();
EntityB entityB = new EntityB();
s.persist(entityB);
tx.commit();
}
try (Session s = openSession()) {
Query<EntityB> query = s.createQuery(
"select b from EntityB b left outer join EntityAChildOne a1 on a1.id = b.someId" , EntityB.class);
List<EntityB> actual = query.list();
assertThat(actual).hasSize(1);
}
}
java.lang.AssertionError:
Expected size:<1> but was:<0> in:
<[]>
at org.hibernate.bugs.ORMUnitTestCase.hhhXXXXTest(ORMUnitTestCase.java:76)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.hibernate.testing.junit4.ExtendedFrameworkMethod.invokeExplosively(ExtendedFrameworkMethod.java:45)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:299)
at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:293)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.lang.Thread.run(Thread.java:833)
In hibernate 5.6.15, this example just works, because hibernate 5 completely ignores the discriminator when generating the SQL (might be a limitation or a bug), but the expected outcome for the example is kept and we get the expected result which is the single list with the entity b in it:
Hibernate 5.6.15:
select
entityb0_.ID as id1_1_,
entityb0_.SOME_ID as some_id2_1_
from
MY_TABLE entityb0_
left outer join
ENTITY_A entityachi1_
on (
entityachi1_.ID=entityb0_.SOME_ID
)
In hibernate 6.2.0, the resulting list will always be empty, because hibernate 6 does not ignore the discriminator, but adds it to the main query criteria (this part is the wrong part). Since this is a left join, the joined entity is optional and adding the discriminator criteria to the main part of the query will result to empty when the joined entity is not present.
Hibernate 6.2.0:
select
e1_0.ID,
e1_0.SOME_ID
from
MY_TABLE e1_0
left join
ENTITY_A e2_0
on e2_0.ID=e1_0.SOME_ID
where
e2_0.DISC_COL=1
A failing test scenario is to be attached
( https://hibernate.atlassian.net/browse/HHH-16438#add-comment?atlOrigin=ey... ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-16438#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=EmailN... ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100221- sha1:78e8bd6 )
3 years
[JIRA] (HHH-16437) class org.hibernate.mapping.BasicValue cannot be cast to class org.hibernate.mapping.ToOne
by Marius K (JIRA)
Marius K ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=70121%3... ) *updated* an issue
Hibernate ORM ( https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiZjg4NjYyOWEw... ) / Bug ( https://hibernate.atlassian.net/browse/HHH-16437?atlOrigin=eyJpIjoiZjg4Nj... ) HHH-16437 ( https://hibernate.atlassian.net/browse/HHH-16437?atlOrigin=eyJpIjoiZjg4Nj... ) class org.hibernate.mapping.BasicValue cannot be cast to class org.hibernate.mapping.ToOne ( https://hibernate.atlassian.net/browse/HHH-16437?atlOrigin=eyJpIjoiZjg4Nj... )
Change By: Marius K ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=70121%3... )
Hi,
I have a One-To-Many relation with the Many-entity having an composite id with AttributeOverrides. This works fine with 6.2.0-CR3 ( and 5), but starts failing with CR4.
{noformat}java.lang.ClassCastException: class org.hibernate.mapping.BasicValue cannot be cast to class org.hibernate.mapping.ToOne (org.hibernate.mapping.BasicValue and org.hibernate.mapping.ToOne are in unnamed module of loader 'app'){noformat}
I attached a test case.
[^hibernate-orm-6.zip]
{noformat}@Entity
public class Contract implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private Integer contractId;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "id.contractId")
@OrderBy(value = "id.positionNumber")
private List<Contractposition> contractpositions = new ArrayList<>();{noformat}
{noformat}@Entity
public class Contractposition implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
@AttributeOverrides(
{
@AttributeOverride(name = "contractId", column = @Column(name = "VERTRAG_ID", nullable = false)),
@AttributeOverride(name = "positionNumber", column = @Column(name = "POSITIONSNUMMER", nullable = false))})
private ContractpositionId id;{noformat}
{noformat}@Embeddable
public class ContractpositionId implements Serializable {
private static final long serialVersionUID = 1L;
@Column(name = "VERTRAG_ID", nullable = false)
private Integer contractId;
@Column(name = "POSITIONSNUMMER", nullable = false)
private int positionNumber;{noformat}
Debugging shows:
!image-20230405-073033.png|width=869,height=476!
( https://hibernate.atlassian.net/browse/HHH-16437#add-comment?atlOrigin=ey... ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-16437#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=EmailN... ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100221- sha1:78e8bd6 )
3 years