7
votes

I've got a JPA entity hierarchy with JPA joined inheritance:

@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING)
Product

and

@Entity
@Table(name = "product_quiz")
@DiscriminatorValue("quiz")
public class QuizProduct extends Product

I want to run a spring-data query with QueryByExample and PageRequest like this:

Example<Product> example = ...
PageRequest pageRequest = ...
Page<Product> productPage = productRepository.findAll(example, pageRequest);

It works fine, except if I set sortField of the pageRequest to be "type" (the @DiscriminatorColumn).

I've tried to:

  • directly add the type field to the entity. This way the query runs fine, but the persisting operation fails with org.postgresql.util.PSQLException: The column index is out of range: 11, number of columns: 10.
  • if I mark this field as @Transient, the persisting works, but the query gives me this exception: Unable to locate Attribute with the the given name [type] on this ManagedType [...AbstractEntityWithDate] (AbstractEntityWithDate is a @MappedSuperclass of Product, which contains creationDate and modificationDate)

I'm using spring-boot version 1.4.5.RELEASE with the dependency-managed versions of spring-data-jpa(1.10.8.RELEASE) and hibernate(5.0.12.Final).

How can I configure the sorting by discriminator field with Pageable? (I don't want to write custom @Query for this).

1
You cannot use a discriminator field in JPQL, so you cannot with Spring either. The only way to use columns with no class representation is to use native queries - Neil Stockton
Thanks! Although i not fully agree with this (there is type(t) in JPA and t.class as workaround in hibernate), your comment helped me to find this workaround: theodoreyoung.wordpress.com/2011/08/08/… Looks like it works for me, and if no better answer arrives for some time, i will post this as an answer. - C-Shark

1 Answers

8
votes

Discriminator columns can be mapped as read-only entity attributes

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING)
class Product {
  @Column(name = "TYPE", insertable = false, updatable = false)
  private String type;
}

Then, the following query will work:

productRepository.findAll(new Sort("type"))

Working sample available on Github.


Having said this, attempting to use the discriminator value in code with inheritance strategy JOINED will not work with Hibernate (type will always be null). This is because traditionally Hibernate has not supported @DiscriminatorColumn with JOINED (see HHH-6911) and has only started to save the column value for joined inheritance with v4.2.9 onwards. It seems like there is still a bug that does not read the discriminator column value, even though the value is saved correctly.