Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
507 views
in Technique[技术] by (71.8m points)

jpa criteriabuilder join maps

I have the following criteria builder query

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

    Root<Role> role = critQuery.from(Role.class);

    //create a join between role and permission
    MapJoin<Role,String,Permission> perm = role.joinMap("permissions");
    critQuery.multiselect(role.get("label"), perm.key(), perm.value());

    //this line throws NPE
    Query query = em.createQuery(critQuery);

The last line throws a null pointer exception.

java.lang.NullPointerException
at org.hibernate.ejb.criteria.path.AbstractPathImpl.prepareAlias(AbstractPathImpl.java:246)
at org.hibernate.ejb.criteria.path.AbstractPathImpl.render(AbstractPathImpl.java:253)
at org.hibernate.ejb.criteria.path.AbstractPathImpl.renderProjection(AbstractPathImpl.java:261)
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...