Skip to content

Spring Data JPA

Calvin Xiao edited this page Nov 15, 2013 · 1 revision

Spring Data JPA在JPA上又做了一层封装,只要编写接口就够了,不用写一行实现代码,CRUD方法啦,分页啦,自动将findByLoginName()的方法定义翻译成适当的QL啦都由它包了,以前每个项目自己写的BaseDao可以取消了。

	public interface UserDao extends PagingAndSortingRepository<User, Long> {
		User findByLoginName(String loginName);
	}

使用上很简单,快速浏览一下下面的资料就够了。

智能地翻译连LessThan, GreaterThan, Like, In, OrderBy, Not,And,Or都支持的方法名变成相应的JQL是它的一大卖点,比如下面的接口函数

   User findByLoginNameOrEmail(String loginName, String email);
    select user from User user where user.loginName=? or email =?

更厉害的是嵌套的属性也能翻译

   Task findByUserId(Long id)
   select task from Task task where task.user.id=?

它当然也可以直接用@Query在方法上标注复杂的查询语句。

如果要执行批量更新/删除语句,同样基于@Query编写。

 @Modifying 
 @Query("update AccountInfo a set a.salary = ?1 where a.salary < ?2") 
 public int increaseSalary(int after, int before);

预先封装好的分页与排序功能也是一大卖点,只要在接口定义时多丢一个Pageable或Sort参数就可以了,在Quickstart中有分页与排序的详细演示

Page<Task> findByUserId(Long id, Pageable pageRequest);

只有一个坑爹的地方,如果要为UserDao扩展方法(而不是接口),要新增一个UserDaoCustom接口,这时候,实现类的名字必须是UserDaoImpl,而不是UserDaoCustomImpl。

##动态组合查询条件 动态组合查询条件,指的是页面上有若干查询条件输入框,用户可能输入了其中的某一个或几个,这时候,固定的Query语句就不起作用了,必须动态组合。

JPA2.0的Criteria API的设计很傻,比Hibernate原来的设计难用多了,Gavin King周围是怎样一帮学院派啊,特别是什么Type Safe的定义,太傻了。

SpringData JPA额外封装了一个Specification,将JPA中的Predicate包起来了,可以使用如下。但对Predicate的创建就没有更多的支持了。

public interface TaskDao extends PagingAndSortingRepository<Task, Long>, JpaSpecificationExecutor<Task>{
...
}

taskDao.findAll(specification, pageRequest);

在Quickstart中沿用了SpringSide3.0以来的风格,通过在输入框中的约定名称,生成Predicate:

  1. 所有查询输入框的name有一个统一的前缀,如search_,而且将需要逻辑运算的关键字如EQ(equals), LE(less)也编码在name里,比如对title属性的模糊查询是”search_LIKE_title“,目前支持的关键字见SearchFilter.java
  2. 使用Servlets里那个copy自Spring WebUtils的getParametersStartingWith(),将所有查询框中非空的Parameter都拿出来。
  3. 将Parameter变为自定义的SearchFilter列表, 含Name,Value与运算符三元素。
  4. 使用SpringSide-Core中的DynamicSpecifications,自动根据SearchFilter生成Predicate。

DynamicSpecifications这段是精华,按约定的自动反射使得整个动态组合查询条件的代码量很少。如果你不想按照SpringSide的做法,也可以参考 DynamicSpecifications,自己在代码中构建Predicate,关键是不要随便抄网上的代码,特别是那些所谓类型安全的,还要每个Entity另外加一个POJO来定义所谓Meta-Data的.

##资料