jpa criteriabuilder join maps

前端 未结 2 1907
终归单人心
终归单人心 2020-12-10 17:19

I have the following criteria builder query

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery critQuery = cb.createQuery();

         


        
                      
相关标签:
2条回答
  • 2020-12-10 17:48

    I have exactly the same problem. After hours of dealing with the issue, and after debugging the Hibernate source code, and after checking over and over again the examples in books and in the JPA 2.0 Specification, I decided to give it a try in EclipseLink.

    So, I created a very simple example: an employee with a map of phone numbers, where the key is the type of phone (home, office, mobile) and the value was the phone number.

    @ElementCollection(fetch=FetchType.EAGER)
    @CollectionTable(name="emp_phone")
    @MapKeyColumn(name="phone_type")
    @Column(name="phone_num")
    private Map<String, String> phoneNumbers;
    

    I could verify that this works perfectly with EclipseLink 2.1 and OpenJPA 2.1.0, but it fails in Hibernate 3.5.3, 3.6.1., 3.6.3

    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaQuery<Employee> criteria = builder.createQuery(Employee.class);
    Root<Employee> employeeRoot = criteria.from(Employee.class);
    criteria.select(employeeRoot);
    MapJoin<Employee, String, String> phoneRoot = employeeRoot.joinMap("phoneNumbers");
    
    criteria.where(builder.equal(phoneRoot.key(), "HOME"));
    
    System.out.println(entityManager.createQuery(criteria).getResultList());
    

    I thought, well if Criteria API fails, perhaps I can do it with a named query. Interestingly, Hibernate does not support the KEY, VALUE or ENTRY keywords, and therefore queries proved to be malformed.

    http://opensource.atlassian.com/projects/hibernate/browse/HHH-5396

    This is what run:

    String query = "SELECT e FROM Employee e JOIN e.phoneNumbers p WHERE KEY(p) IN ('HOME')";
    System.out.println(entityManager.createQuery(query, Employee.class).getResultList());
    

    In hibernate it generates the following SQL query:

       select
            employee0_.id as id0_,
            employee0_.name as name0_ 
        from
            Employee employee0_ 
        inner join
            emp_phone phonenumbe1_ 
                on employee0_.id=phonenumbe1_.Employee_id 
        where
            KEY(phonenumbe1_.phone_num) in (
                'HOME'
            )
    

    Which is evidently malformed.

    Again, in EclipseLink and OpenJPA this works.

    So, evidently, something must be wrong with Hibernate. I have submitted an bug in the Hibernate Jira Issue Tracker

    http://opensource.atlassian.com/projects/hibernate/browse/HHH-6103

    And have posted the question in the Hibernate Users Forum

    https://forum.hibernate.org/viewtopic.php?f=1&t=1010411

    0 讨论(0)
  • 2020-12-10 17:54

    For those stuck on Hibernate 3.6, I was able to join through a map and limit the results with a predicate. This solution comes with a significant caveat. This technique only works if the map key you're interested in exists for every record. If it does not, you will lose records that you might otherwise expect in the result set.

    My case is very similar to Edwin's example. We have a Person entity with a map of current names where the map key is a name type and the value is a Name object. In my case, I wanted to retrieve a person's current standard name.

    Root<Person> person = query.from(Person.class);
    Join currentName = person.join("currentNames");
    
    NameLookup standardName = NameLookup.lookup("ST");
    
    Predicate useridMatches = criteria.equal(person.get("userid"), "user1");
    Predicate isStandardName = criteria.equal(currentName.get("nameType"), standardName);
    Predicate useridAndStandardName = criteria.and(useridMatches, isStandardName);
    query.where(useridAndStandardName);
    

    In JPQL, we typically use the WITH clause to limit the join.

    inner join person.currentNames currentStandardName 
    with currentStandardName.nameType.id = :standardNameLookupId
    
    0 讨论(0)
提交回复
热议问题