我在 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/