Spring data jpa @MapKeyColumn的查询处理

最近在使用Spring Data JPA, 查询起来还是比较方便的。简单看了下@Query支持的,其实叫JPQL,是JPA规范中提出的一种面向对象的查询方式,其实JPQL只是HQL的子集(毕竟JPA源于Hibernate),不过HQL原本我也不熟,所以还是需要一段时间来看看JPA2的规范,貌似现在对聚合查询,子查询等功能都支持的不错了。不过网上的资料还是不多,感觉现在国内互联网还是以Mybatis为主要ORM框架,毕竟SQL是可以完全自定义的。其实Spring data JPA也可以通过native=true来完成。

言归正传,最近用到了"纵表"的设计,主表跟从表是一对多关系,从表是个简单的key:value对,另外还有个外键用来关联主表主键。

主表:主表ID,名称,XXX
从表:从表ID,主表ID,Key,Value

持久化对象的类上只需要在主表的类中加入一个Map的属性,就能把从表的键值对加载过来,假设主表是一个Group表,从表是一个Group_params表:

@ElementCollection(fetch = FetchType.EAGER)
	@CollectionTable(name = "GROUP_PARAMS", joinColumns = @JoinColumn(name = "GROUP_ID"))
	@MapKeyColumn(name = "PARAM_KEY")
	@Column(name = "PARAM_VALUE")
	private Map<String, String> groupParams = new HashMap<String, String>();



在做完了这些之后,在增删改的时候都能以groupParams这个属性来拿到从表中的相关数据。

但是查询的时候遇到了一些问题,例如:根据param的Key和value查询group。

第一是要解决怎么写的问题,JPQL中使用了"Path Expressions"的方式来获取属性,也对Map这种数据结构提供了方法: KEY, VALUE, ENTRY, 也对应了Map当中的属性。
用法(以下写法有问题):

@Query(value = "select g from MyGroup g join g.groupParams p where KEY(p) = :paramKey and VALUE(p) = :paramValue ")

用了上述的注解后生成的native SQL(重点在查询条件):
where groupparam1_.param_key=? and (select groupparam1_.param_value from group_params groupparam1_ where mygroup0_.group_id=groupparam1_.group_id)=?;

可以看到查询是有问题的,Value方法直接导致生成了子查询。解决方法是把第二个查询条件的 VALUE(p) = :paramValue 直接修改为p=:paramValue.

具体的原因我只能通过查询获取一点信息,没有从源码级别看,hibernate东西还是挺多的,相关链接见:
https://stackoverflow.com/questions/29852701/is-it-possible-to-query-jpa-entities-by-elementcollections-where-the-elementcoll

https://stackoverflow.com/questions/21263725/jpas-mapkey-value-query-by-jpql-failed

猜你喜欢

转载自wwwcomy.iteye.com/blog/2425993