最近一直在用spring-data-jpa这个东西,感觉方法上注解hql语句已经是很常用的方法了,
有一些关于hql的经验分享一下:
一.hql的join
hql的优势就是直接的关联关系嘛,但是通过hql语句进行join查询的时候,需要注意一些地方:
hql的join不能像类似sql的join一样,直接join两张表,需要先维护关联关系,在join:
@Entity @Table(name = "mq_mark") public class MarkModel implements Serializable { /** * */ private static final long serialVersionUID = -5169585172209348371L; @Id @GeneratedValue(strategy = GenerationType.AUTO) public Long id; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "show_id", nullable = false) @Fetch(FetchMode.JOIN) public ShowImage showImage; }
然后在进行hql join查询
@Query("select r from MarkModel t join t.showImage r where t.type= ?1 and t.datamId = ?2 ")
List<ShowImage> findMarkImages(Integer marktype, Long datamId, Pageable pageable);
会生成 left join 语句
二:hql语句的去重
使用sql去重一般是使用distinc ,但是这种方式是会影响效率的。
hql的去重推荐使用group by
@Query("select t.showImage from MarkModel t where t.type= ?1 and t.datamId = ?2 group by t.showImage.id")
List<ShowImage> findMarkImages(Integer marktype, Long datamId, Pageable pageable);
看一下其生成的语句:
select showimage1_.id as id1_25_, showimage1_.create_time as create_t5_25_, showimage1_.image_url as image_ur8_25_, showimage1_.position as positio14_25_
from xxx markmodel0_ inner join mq_showpic showimage1_ on markmodel0_.show_id=showimage1_.id
cross join mq_showpic showimage2_
where markmodel0_.show_id=showimage2_.id and markmodel0_.type=? and markmodel0_.datam_id=?
group by markmodel0_.show_id order by showimage2_.create_time desc limit ?
这里看到有一个cross join ,看见cross join就说明要生成笛卡尔积,这样会非常大的影响效率,
经过排查,发现只有order by的时候有用到了showimage2_,所以猜测是order by的问题,看下怎么生成的order by
Pageable pageable = new PageRequest(page, rows, Direction.DESC, "showImage.createTime");//注意这里的条件 List<ShowImage> result = this.markDao.findMarkImages(marktype, datamId, pageable);
这里使用了join的表进行排序,所以才出现了cross join
将这里改成用主表的createTime进行排序
Pageable pageable = new PageRequest(page, rows, Direction.DESC, "createTime");
生成的sql立马就变了:
select showimage1_.id as id1_25_, showimage1_.create_time as create_t5_25_, showimage1_.image_url as image_ur8_25_, showimage1_.position as positio14_25_
from mq_mark markmodel0_ inner join mq_showpic showimage1_ on markmodel0_.show_id=showimage1_.id
where markmodel0_.type=? and markmodel0_.datam_id=?
group by showimage1_.id order by markmodel0_.create_time desc limit ?
不在有cross join了