使用 Spring Data JPA 简化 JPA 开发
清单 7. 本文使用如下的 main 方法进行开发者测试
清单 11. 改造后的基于 Spring 的开发者测试代码
?
至此便大功告成了!执行一下测试代码,然后看一下数据库,新的数据已经如我们预期的添加到表中了。如果要再增加新的持久层业务,比如希望查询出给 ID 的 AccountInfo 对象,该怎么办呢?很简单,在 UserDao 接口中增加一行代码即可:
清单 14. 修改后的持久层接口,增加一个方法声明
但是,使用 CrudRepository 也有副作用,它可能暴露了你不希望暴露给业务层的方法。比如某些接口你只希望提供增加的操作而不希望提供删除的方法。针对这种情况,开发者只能退回到 Repository 接口,然后到 CrudRepository 中把希望保留的方法声明复制到自定义的接口中即可。
分页查询和排序是持久层常用的功能,Spring Data 为此提供了 PagingAndSortingRepository 接口,它继承自 CrudRepository 接口,在 CrudRepository 基础上新增了两个与分页有关的方法。但是,我们很少会将自定义的持久层接口直接继承自 PagingAndSortingRepository,而是在继承 Repository 或 CrudRepository 的基础上,在自己声明的方法参数列表最后增加一个 Pageable 或 Sort 类型的参数,用于指定分页或排序信息即可,这比直接使用 PagingAndSortingRepository 提供了更大的灵活性。
JpaRepository 是继承自 PagingAndSortingRepository 的针对 JPA 技术提供的接口,它在父接口的基础上,提供了其他一些方法,比如 flush(),saveAndFlush(),deleteInBatch() 等。如果有这样的需求,则可以继承该接口。
上述四个接口,开发者到底该如何选择?其实依据很简单,根据具体的业务需求,选择其中之一。笔者建议在通常情况下优先选择 Repository 接口。因为 Repository 接口已经能满足日常需求,其他接口能做到的在 Repository 中也能做到,彼此之间并不存在功能强弱的问题。只是 Repository 需要显示声明需要的方法,而其他则可能已经提供了相关的方法,不需要再显式声明,但如果对 Spring Data JPA 不熟悉,别人在检视代码或者接手相关代码时会有疑惑,他们不明白为什么明明在持久层接口中声明了三个方法,而在业务层使用该接口时,却发现有七八个方法可用,从这个角度而言,应该优先考虑使用 Repository 接口。
前面提到,Spring Data JPA 在后台为持久层接口创建代理对象时,会解析方法名字,并实现相应的功能。除了通过方法名字以外,它还可以通过如下两种方式指定查询语句:
下面我们分别讲述三种创建查询的方式。
可能会存在一种特殊情况,比如 AccountInfo 包含一个 user 的属性,也有一个 userAddress 属性,此时会存在混淆。读者可以明确在属性之间加上 "_" 以显式表达意图,比如 "findByUser_AddressZip()" 或者 "findByUserAddress_Zip()"。
在查询时,通常需要同时根据多个属性进行查询,且查询的条件也格式各样(大于某个值、在某个范围等等),Spring Data JPA 为此提供了一些表达条件查询的关键字,大致如下:
And --- 等价于 SQL 中的 and 关键字,比如 findByUsernameAndPassword(String user, Striang pwd);Or --- 等价于 SQL 中的 or 关键字,比如 findByUsernameOrAddress(String user, String addr);Between --- 等价于 SQL 中的 between 关键字,比如 findBySalaryBetween(int max, int min);LessThan --- 等价于 SQL 中的 "<",比如 findBySalaryLessThan(int max);GreaterThan --- 等价于 SQL 中的">",比如 findBySalaryGreaterThan(int min);IsNull --- 等价于 SQL 中的 "is null",比如 findByUsernameIsNull();IsNotNull --- 等价于 SQL 中的 "is not null",比如 findByUsernameIsNotNull();NotNull --- 与 IsNotNull 等价;Like --- 等价于 SQL 中的 "like",比如 findByUsernameLike(String user);NotLike --- 等价于 SQL 中的 "not like",比如 findByUsernameNotLike(String user);OrderBy --- 等价于 SQL 中的 "order by",比如 findByUsernameOrderBySalaryAsc(String user);Not --- 等价于 SQL 中的 "! =",比如 findByUsernameNot(String user);In --- 等价于 SQL 中的 "in",比如 findByUsernameIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;NotIn --- 等价于 SQL 中的 "not in",比如 findByUsernameNotIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;描述名字大小下载方法样例代码sample-code.rar5KBHTTP
关于下载方法的信息
?
参考资料
学习
访问 Spring Data主页,了解 Spring Data 框架及其针对不同的持久化技术提供的支持,这里也提供了丰富的学习文档,并且可以下载最新的 Spring Data JPA 发布版。讨论
加入 developerWorks 中文社区,developerWorks 社区是一个面向全球 IT 专业人员,可以提供博客、书签、wiki、群组、联系、共享和协作等社区功能的专业社交网络社区。关于作者
张建平,长期从事于基于 Java 的项目开发与管理工作,在 Java SE/Java EE 领域积累了丰富的知识和经验。尤其对 SpringSource 框架集 ( Spring Framework,Spring Security,Spring Roo 等 ) 有深入研究,擅长基于以 Spring 和 Hibernate 为中心的轻量级框架进行项目开发;并对 Java EE 规范集有深入研究。如有兴趣,可以加 MSN:yerlluo@hotmail.com 与他联系。
<!-- MAIN_COLUMN_CONTENT_END --><!-- OVERLAYS_START -->
<!-- Report_Abuse_Start -->
?