【问题标题】:JPA and JPQL MEMBER OF queries always returning empty resultsJPA 和 JPQL MEMBER OF 查询总是返回空结果
【发布时间】:2013-08-23 23:26:17
【问题描述】:

我在使用 JPA2/Hibernate 4.2/MySQL 5.1/Java 6 时遇到问题

我有以下类 User,它有一个属性 Set<Role>,其中 Role 是一个枚举。这是课程:

@Entity
public class User
{
  private static final long serialVersionUID = 1L;

  @ElementCollection(fetch=FetchType.EAGER)
  @Enumerated(value=EnumType.STRING)
  protected Set<Role> roles;

  // .. other stuff
}

public enum Role { ADMIN, OPERATOR, ... }

我已尝试为此创建 CriteriaQuery 和 JPQL 查询,但由于某种原因,即使角色存在,每次都返回一个空列表。

这是我的条件查询代码:

CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
CriteriaQuery<User> query = builder.createQuery(User.class);
Root<User> root = query.from(User.class);

query.where(builder.isMember( Role.ADMIN, root.<Set<Role>>get( "roles" ) ) );

List<User> result = getEntityManager().createQuery(query).getResultList();

这是我正在创建的 JPQL:

String jpql = "SELECT * FROM com.mypackage.user.User WHERE (:roles1 MEMBER OF roles))";
Query query = em.createQuery(jpql);
query.setParameter( "roles1", Role.ADMIN );
List result = em.getResultList();

users 表包含一个具有所有角色的用户,但这些都没有返回任何结果。对于我正在做的工作,我需要同时拥有 JPA 和 JPQL 版本。请帮忙!

【问题讨论】:

  • 生成的SQL是什么?直接执行这个生成的 SQL 会发生什么?
  • 我已经改变了 jpql,所以它暂时计算了 - 休眠本机 SQL 给出:select count(*) as col_0_0_ from User user0_ where ? in (select roles1_.roles from User_roles roles1_ where user0_.id=roles1_.User_id) - 如果我改变?到“管理”它的工作原理。
  • SQL 看起来正确。尝试查看实际绑定到语句的值,在数据库上自行执行查询,检查数据,并检查是否连接到正确的数据库。
  • 不确定这是否是正确的方式 - 我本来希望像select count(*) as col_0_0_ from User user0_ where user0_.id in (select roles1_.User_id from User_roles roles1_ where roles1_.roles = 'ADMIN')
  • 嗨 JB Nizet - 如果我更改生成的 SQL,那么?被 'ADMIN' 取代,我得到了预期的结果。 Role 枚举只是一个裸枚举(即我没有更改 toString 或 name 方法)所以我猜 hibernate 也在 ADMIN 中交换,除非它失败。

标签: hibernate jpa persistence jpql criteriaquery


【解决方案1】:

好的,对于那些有类似问题的人,我有一个解决方案,但不是很好。感谢 JB Nizet 在帮助诊断问题时提供的指导。

问题是由于 JPA 和/或 Hibernate 在处理非字符串数据时的限制。在这里,我使用了一个枚举,它在 Role 对象和它在数据库中的字符串表示之间进行相等性测试,而不是将我传入的 Role 转换为它的 db 表示(正如你所期望的那样),然后进行比较。

为了让 JPQL 版本继续运行,我做了:

String jpql = "SELECT * FROM com.mypackage.user.User WHERE (:roles1 MEMBER OF roles))";
Query query = em.createQuery(jpql);
query.setParameter( "roles1", Role.ADMIN.toString() );
List result = em.getResultList();

为了修复 JPA 版本,我做了:

CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
CriteriaQuery<User> query = builder.createQuery(User.class);
Root<User> root = query.from(User.class);

query.where(builder.isMember( Role.ADMIN.toString(), root.<Set<String>>get( "roles" ) ) );

List<User> result = getEntityManager().createQuery(query).getResultList();

如果有人可以更正此代码并使其成为不必要的 toString (我没有排除我只是没有正确设置它的想法),如果你能把我说对,我将不胜感激。 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-05
    • 2011-08-27
    • 1970-01-01
    • 2021-08-16
    • 1970-01-01
    • 2018-08-02
    • 2014-06-23
    • 2011-02-10
    相关资源
    最近更新 更多