Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make Hibernate discriminator value use bind variable instead of literal

When using the @DiscriminatorColumn on a class and @DiscriminatorValue on subclasses, the SQL that Hibernate generates uses the discriminator value as a literal for the clause involving the discriminator column.

Example:

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "PART_TYPE")
@Table(name = "NAME")
public class NamePartEntity implements Comparable<NamePartEntity> {
  // Stuff
}

@Entity
@DiscriminatorValue(value = "GIV")
public class GivenNameEntity extends NamePartEntity {
  // stuff
}

If I create a simple criteria query with no criteria except the class, I would get SQL generated like such:

select this_.person_id as y0_ from name this_ where this_.part_type='GIV'

This isn't so bad until you have a handful of discriminator values and the table might be selected from multiple times, such that a query like the below:

SELECT this_.person_id AS y0_
FROM name this_
WHERE this_.part_type='FAM'
AND this_.value_u    =:8
AND this_.tenant_id  =:9
AND this_.person_id IN
  (SELECT this_.person_id AS y0_
  FROM name this_
  WHERE this_.part_type='GIV'
  AND this_.value_u    =:10
  AND this_.tenant_id  =:11
  AND this_.person_id IN
    (SELECT this_.person_id AS y0_
    FROM name this_
    WHERE this_.part_type='GIV'
    AND this_.value_u    =:12
    AND this_.tenant_id  =:13
    AND this_.person_id IN
      (SELECT this_.person_id AS y0_
      FROM name this_
      WHERE this_.part_type='PFX'
      AND this_.value_u    =:14
      AND this_.tenant_id  =:15
      )
    )
  )

could have a ton of different SQL ids and execution plans based on the literals ('FAM', 'GIV', 'PFX' in this case but they could be different and in different orders). However, if bind variables were used in place of those discriminator value literals, it would be the same sql id and have the same execution plan.

So, is it possible to have Hibernate use the discriminator column/value annotations in such a way that bind variables are used instead of literals? I know it would be possible to rewrite my entities in such a way to avoid this but I wanted to see if I could get the bind variable functionality with the existing annotations in some way.

Alternatively, is there a way I can still use my extended classes without using discriminator values? If I try that and have the @Entity annotation on each extended class, it complains about missing the discriminator type even when there are no discriminator annotations.

like image 205
AHungerArtist Avatar asked Nov 08 '22 14:11

AHungerArtist


1 Answers

No, it is not possible to get it out of the box.

The closest workaround that comes to my mind is to select from the base class and explicitly filter by subclass:

entityManager.createQuery("select gne from NamePartEntity gne where type(gne) = :subclass")
    .setParameter("subclass", GivenNameEntity.class)
    .getResultList();
like image 177
Dragan Bozanovic Avatar answered Nov 12 '22 17:11

Dragan Bozanovic