javahibernatehql

Updating from hibernate 5.5.x to Hibernate 6.1.7 generated the incorrect discriminator query


My model is as follows:

@Entity
@Table(name = "PARTY")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "CLASS", discriminatorType = DiscriminatorType.STRING)
public class Party implements Serializable {

    @Id
    @GeneratedValue
    @Column(name = "PARTY_ID")
    private long partyID;

    @Column(name = "STATE")
    private String state;

    /*Lots of other columns NOT including CLASS though */
}

@Entity
@DiscriminatorValue("Organisation")
public class Organisation extends Party {
 
 @Column(name = "ORGANISATION_NAME", unique = true)
 private String name; 
}

@Entity
@DiscriminatorValue("Person")
public class Person extends Party {
  
  @OneToMany(cascade=CascadeType.ALL, mappedBy = "clientParty", fetch = FetchType.LAZY, orphanRemoval = true)
    @Fetch(value = FetchMode.SUBSELECT)
    private List<Relationship> relationships = new ArrayList<>();

}

@Entity
@Table(name = "RELATIONSHIP")
public class Relationship implements Serializable { 

    @Id
    @GeneratedValue
    @Column(name = "RELATIONSHIP_ID")
    private long relationshipId;

    @Column(name="CLIENT_PARTY_ID", insertable = false, updatable = false)
    private Long clientPartyId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "CLIENT_PARTY_ID", nullable = false)
    private Person clientParty;

    @Column(name="SUPPLIER_PARTY_ID", insertable = false, updatable = false)
    private Long supplierPartyId;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "SUPPLIER_PARTY_ID", nullable = false)
    private Organisation supplierParty;
}

I have a query that fetches the distinct users that are state = 'active' OR organisation name = 'abc', the HQL is like this:

SELECT DISTINCT u FROM Person u 
LEFT JOIN Relationship r ON u.partyID = r.clientPartyId 
LEFT JOIN Organisation o ON r.supplierPartyId = o.partyID 
WHERE lower(o.name) LIKE :orgName OR
lower(u.state) = :state

I have a test case that expects 3 users to come back:

  1. User A - status 'active', assigned to organisation with name 'abc'
  2. User B - status 'inactive', assigned to organisation with name 'abc'
  3. User C - status 'active', not assigned to any organisation

In hibernate 5, this worked. When I upgraded to hibernate 6 it dropped user C because it didnt have a relationship defined.

This is the generated SQL in hibernate 6.1.7

select distinct
m1_0.PARTY_ID from PARTY m1_0 
left join RELATIONSHIP r1_0 on m1_0.PARTY_ID=r1_0.CLIENT_PARTY_ID 
left join PARTY m2_0 on r1_0.SUPPLIER_PARTY_ID=m2_0.PARTY_ID 
where (lower(m2_0.ORGANISATION_NAME) like ? or lower(m1_0.STATE)=?) and
m1_0.CLASS='Person' and m2_0.CLASS='Organisation'

Shouldn't the CLASS clause be part of the LEFT JOIN and not WHERE clause?

I found similar bug reports https://discourse.hibernate.org/t/hibernate-6-wrong-query-generated-with-discriminatorvalue/6984 and https://hibernate.atlassian.net/browse/HHH-15829 However I upgraded to 6.1.7 (I cant upgrade to 6.2 because there is some other problem) and it hasn't fixed this.

If anyone has any ideas it will be much appreciated. Thanks


Solution

  • This sounds very similar to another Hibernate bug: https://hibernate.atlassian.net/browse/HHH-16438. We have improved how inheritance works a lot in recent updates, I would suggest upgrading to the latest stable version as soon as possible to take advantage of this.

    You mentioned upgrading to 6.2 causes another problem, please report it in Hibernate's issue tracker.