mysql - JPA 的 Map<KEY, VALUE> JPQL 查询失败

标签 mysql hibernate jpa jpql

我在 JPA 中存储了一个 Map,它存储了每种语言的关键字翻译。例如一个对象存储 Locale.ENGLISH -> "Father", Locale.CHINESE -> "PaPa"。另一个对象存储 Locale.ENGLISH -> "Mother", Locale.CHINESE -> "MaMa";

这是我的工作设计:

public class Relation {
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private long id;

  @ElementCollection
  @MapKeyColumn(name="locale")
  @Column(name="value")
  @CollectionTable(name = "RelationName", joinColumns = @JoinColumn(name = "relation_id"))
  private Map<Locale, String> langMap = new HashMap<>();

  // other fields skipped
}

效果很好,我可以将许多关键字翻译存储到数据库中。但是使用 JPQL 查询时,出现了一些问题:

例如,我想查找哪个关系具有值为“Father”的英文键:

这是我的代码:

Relation r = em.createQuery("select r from Relation r join r.langMap m where ( KEY(m) = :locale and VALUE(m) = :value ) " , Relation.class)
  .setParameter("locale" , locale)
  .setParameter("value" , value)
  .getSingleResult();

它生成这个奇怪的/不工作的 SQL :

Hibernate: 
    select
        relation0_.id as id1_18_
    from
        Relation relation0_ 
    inner join
        RelationName langmap1_ 
            on relation0_.id=langmap1_.relation_id 
    where
        langmap1_.locale=? 
        and (
            select
                langmap1_.value 
            from
                RelationName langmap1_ 
            where
                relation0_.id=langmap1_.relation_id
        )=?
00:16:12.038 WARN  o.h.e.jdbc.spi.SqlExceptionHelper - SQL Error: 1242, SQLState: 21000
00:16:12.038 ERROR o.h.e.jdbc.spi.SqlExceptionHelper - Subquery returns more than 1 row

我不知道它为什么会生成那个奇怪的子查询。

我可以通过标准解决这个问题:

CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Relation> criteria = builder.createQuery(Relation.class);
Root<Relation> root = criteria.from(Relation.class);
criteria.select(root);
MapJoin<Relation , Locale , String> mapJoin = root.joinMap("langMap");
criteria.where(builder.and(
  builder.equal(mapJoin.key(), locale) ,
  builder.equal(mapJoin.value() , value))
);

return em.createQuery(criteria).getSingleResult();

它生成正确的 SQL(where langmap1_.locale=? and langmap1_.value=?)并且运行良好。

但是我觉得Criteria太复杂了。我想知道为什么 JPQL 失败了?如何更正 JPQL ?

谢谢。

环境:

JPA2、Hibernate 4.2.3、MySQL 方言

最佳答案

我遇到了同样的问题。看起来通过 ref 访问 map (没有 VALUE())已经为您提供了 map 条目值,即下一个 JPQL 应该转换为有效的 SQL:

select r from Relation r join r.langMap m where ( KEY(m) = :locale and m = :value )

关于mysql - JPA 的 Map<KEY, VALUE> JPQL 查询失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21263725/

相关文章:

java - 将 Hibernate 与 Spring 一起使用时,我可以摆脱 persistence.xml 吗?

java - 获取 EntityManager 的不同方法

java - 使用 FK 作为过滤器在 Java 上创建查询

mysql - sql创建函数将字符串转换为ascii整数

mysql - 在 Mac 上安装 MySQL2 gem 失败

java - 尝试在 tomcat 服务器上配置 hibernate 时出现命名异常

java - 什么方法加入实体更快?

mysql - 在包含 json 的文本字段中搜索

asp.net - 从 ASP.net Web 服务返回大量数据时有哪些好的做法?

java - Grails、作业、静态辅助方法和 Hibernate session