jpa criteriabuilder连接映射

jpa criteriabuilder连接映射,jpa,Jpa,我有以下条件生成器查询 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,

我有以下条件生成器查询

    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);

我也有同样的问题。经过几个小时的处理,调试Hibernate源代码,反复检查书籍和JPA2.0规范中的示例,我决定在EclipseLink中尝试一下

因此,我创建了一个非常简单的示例:一名员工拥有一张电话号码地图,其中的键是电话类型(家庭、办公室、手机),值是电话号码

@ElementCollection(fetch=FetchType.EAGER)
@CollectionTable(name="emp_phone")
@MapKeyColumn(name="phone_type")
@Column(name="phone_num")
private Map<String, String> phoneNumbers;
在hibernate中,它生成以下SQL查询:

   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'
        )
这显然是畸形的

同样,在EclipseLink和OpenJPA中,这是有效的

因此,很明显,Hibernate肯定出了问题。我在Hibernate Jira问题跟踪器中提交了一个bug

并在Hibernate用户论坛上发布了这个问题


对于那些停留在Hibernate 3.6上的人,我能够通过一个映射加入,并用谓词限制结果。这个解决方案附带了一个重要的警告。只有在每个记录都存在您感兴趣的映射键时,此技术才有效。否则,您将丢失结果集中您可能期望的记录

我的情况与埃德温的例子非常相似。我们有一个具有当前名称映射的Person实体,其中映射键是名称类型,值是名称对象。在我的例子中,我想检索一个人当前的标准名称

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);

非常有趣!检查,我想这是一些类路径问题。谢谢你的努力。我相信很多ppl都会发现它很有用。我遇到了同样的问题,如果有一个合适的hibernate解决方案,我会非常高兴。每个提示都是受欢迎的:)@Tobias如果你查看Hibernate论坛,你会注意到我在那里建议了两种解决方法。@edalorzo你是说Hibernate Bug跟踪页面。我想我会考虑使用选项“2”-> 2。不要使用地图,使用另一种集合。在我的例子中,我创建了一个类(一种带有key和value的条目类),然后使用一个集合来保存这个条目对象的信息。正确地执行equals()和hashCode让我只使用键值查找集合中的项。这个hibernate错误现在已经修复!
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());
   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'
        )
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);
inner join person.currentNames currentStandardName 
with currentStandardName.nameType.id = :standardNameLookupId