简体   繁体   中英

JPA 2 Criteria Query on Single Table Inheritance (Hibernate)

My project is using JPA 2 with Hibernate and there is a single table inheritance setup for dealing with two types of customer. When I try to query data on customers by using Spring Data JPA Specification, I always get incorrect result. I think it's because I create the query wrong and still got no idea how to make it right.

Here is my test code (I am trying search customer by company name):

@Test
public void test() {
    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
    CriteriaQuery<Customer> customerQuery = criteriaBuilder.createQuery(Customer.class);
    Root<Customer> customerRoot = customerQuery.from(Customer.class);
    Root<CompanyCustomer> companyCustomerRoot = customerQuery.from(CompanyCustomer.class);

    CriteriaQuery<Customer> select = customerQuery.select(customerRoot);
    select.where(criteriaBuilder.equal(companyCustomerRoot.get(CompanyCustomer_.companyName), "My Company Name"));

    TypedQuery<Customer> query = entityManager.createQuery(select);
    List<Customer> results = query.getResultList();

    assertEquals(1, results.size()); // always got size 2
}

SQL script in the log:

Hibernate: 
    select
        customer0_.id as id2_16_,
        customer0_.type as type1_16_,
        customer0_.first_name as first_na8_16_,
        customer0_.last_name as last_nam9_16_,
        customer0_.company_name as company13_16_ 
    from
        customers customer0_ cross 
    join
        customers companycus1_ 
    where
        companycus1_.type='COMPANY' 
        and companycus1_.company_name=?

There are two records in my database:

insert into customers (id, type, company_name) values (1, 'COMPANY', 'My Company Name');

insert into customers (id, type, first_name, last_name) values (2, 'PERSONAL', 'My First Name', 'My Last Name');

My single table inheritance setup:

@Entity
@Table(name = "customers")
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)
public abstract class Customer {    

    @Enumerated(EnumType.STRING)
    @Column(name = "type", insertable = false, updatable = false)
    private CustomerType type;
    private String contactNumber;
}

@Entity
@DiscriminatorValue("PERSONAL")
public class PersonalCustomer extends Customer {          

    private String firstName;
    private String lastName;    
}

@Entity
@DiscriminatorValue("COMPANY")
public class CompanyCustomer extends Customer {

    private String companyName;
}

public enum CustomerType {

    COMPANY, PERSONAL;
}

I found the answer from JPA Criteria Query over an entity hierarchy using single table inheritance

Solution: Use CriteriaBuilder.treat() to downcast Customer entity instead of using CriteriaQuery.from()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM