spring jpa教程

##关于实体层编写及配置
###概述
项目所有实体层位于 `${package}.entity`目录下,实体对象编写需要遵从JPA规范进行标注。

###命名规范
对于实体名及包名的编写规范,建议遵循以下方式:

* 子包名应短小并且包含实际业务划分的含义,可以为缩写,尽量不超过6个字母。例如:`auths`、`info`。
* 实体名应为有业务含义的英文,必要时可以使用合成词汇,但必须符合骆驼命名法。例如:`User`、`UserRole`。
* 实体映射的表名应为:"子包名+实体名",全部小写,此表名在实体中使用`@Table`标注,大写字母应使用`_`替代。例如:`@Table(name = "auths_user")`。

###推荐使用
在entity目录下包含了一个UUID的主键,推荐使用此种方式作为主键的生成方式,使用方法为实体类集成此ID类即可。

###注意事项
不允许将实体置于entity包下,否则系统将无法对其进行ORM映射。

###参考文档
关于实体类的映射方法,推荐阅读如下列表:
[Oracle JPA标注参考](http://www.oracle.com/technetwork/middleware/ias/toplink-jpa-annotations-096251.html)

##关于数据访问层编写及配置
###概述
项目所有数据访问层位于`${package}.repository`目录下,数据访问对象编写不出现特殊需要只需实现访问接口即可,编写方式需遵从Spring JPA data要求。

##命名规范
对于数据访问对象名及方法的编写规范,建议遵循如下方式:

* 所有数据访问对象应与实体一一对应,放置于与实体子报名相同的包目录下,并在实体名后增加Dao后缀。例如:`{pakcage}.repository.auths.UserDao`。
* 需要包含分页及排序方法应实现`PagingAndSortingRepository`接口,需要实现条件查询应实现`JpaSpecificationExecutor`接口。泛型类应于需要实现的实体类相同。默认推荐编写时实现上述2个接口。
* JPA Data支持通过解析方法名创建查询,因此在方法名的编写上需严格遵从规范要求编写。

框架在进行方法名解析时,会先把方法名多余的前缀截取掉,比如 find、findBy、read、readBy、get、getBy,然后对剩下部分进行解析。并且如果方法的最后一个参数是 Sort 或者 Pageable 类型,也会提取相关的信息,以便按规则进行排序或者分页查询。

在创建查询时,我们通过在方法名中使用属性名称来表达,比如 findByUserAddressZip ()。框架在解析该方法时,首先剔除 findBy,然后对剩下的属性进行解析,详细规则如下(此处假设该方法针对的域对象为 AccountInfo 类型):

先判断 userAddressZip (根据 POJO 规范,首字母变为小写,下同)是否为 AccountInfo 的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,继续第二步;

从右往左截取第一个大写字母开头的字符串(此处为 Zip),然后检查剩下的字符串是否为 AccountInfo 的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,则重复第二步,继续从右往左截取;最后假设 user 为 AccountInfo 的一个属性;

接着处理剩下部分( AddressZip ),先判断 user 所对应的类型是否有 addressZip 属性,如果有,则表示该方法最终是根据 "AccountInfo.user.addressZip" 的取值进行查询;否则继续按照步骤 2 的规则从右往左截取,最终表示根据 "AccountInfo.user.address.zip" 的值进行查询。

可能会存在一种特殊情况,比如 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 类型,也可以是数组或者不定长参数;

* 使用自定义语句进行查询可以使用`@Query`标注,当出现使用Query实现的方法,方法名应遵从如下方式:

* 查询集合方法以`findBy`起头,依照条件使用`And`、`Or`等条件语句将参数连接起来(此命名方法与JPA Data解析方法名相同)。例如:`List<User> findByRoleName(String roleName)`。
* 查询单条记录应以 `getBy`起头,依照条件使用条件语句将参数进行连接。例如:`User getByIdCard(String idCard)`。
* 插入(insert)、更新(update)方法应以`save`起头,依照条件使用条件语句将参数进行连接。例如:`User savePassword(String password)`。
* 删除(delete)方法应以`deleteBy`起头,依照条件使用条件语句将参数进行连接。例如:`void deleteByRoleName(String roleName)`。

###注意事项

###参考文档
[使用 Spring Data JPA 简化 JPA 开发](http://www.ibm.com/developerworks/cn/opensource/os-cn-spring-jpa/)

##关于业务层编写及配置
###概述
项目所有业务层位于 `${package}.service`目录下,基于`@Component`标注进行配置,业务层为门板模式(Facade),一个业务按照需求封装成为一个或多个业务类。

###命名规范
* 业务类名以`业务名称+Service`组合形成,业务名称应为有含义的英文,可为组合词。例如:`AccountService`、`AuthorityService`。
* 业务类方法名命名,应使用`操作`+`资源`方式进行表现,例如:常见的CRUD,可以写为`createUser()`、`deleteUser()`、`readUser()`、`updateUser()`,也可使用`saveUser`作为create及update操作的总述。方法名命名没有强制约定必须,但应尽量简洁可读,不同资源的相同类型操作应使用相同的前缀进行描述。推荐使用如下词作为前缀:
* save 新增或修改
* delete 删除
* list 返回列表不论分页还是不分页
* enable 使能
* disable 使不能
* download 下载
* upload 上传

###注意事项
* 所有方法应做事务标注。
* 注入数据接入接口应使用@Autoware方法。
* 禁止在Service中注入其他Service类。
* 注意非RuntimeException转化为RuntimeException抛出。

###参考文档
[Spring Framework 开发参考手册5.9](http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/beans.html#beans-annotation-config)

##关于控制层编写及配置
项目所有控制层位于 `${package}.controller`目录下,基于`@Controller`标注进行配置。

###命名规范
* 该包目录下包含多个子包,rest为restful风格的webservice数据接口,web为servlet/jsp模式页面跳转的处理接口,若使用soap协议则应放入soap子包下。
* 控制层对象应以资源为最小单位,对象命名应以`资源名+接口类型名+Controller`,例如:`UserRestController`、`RoleWebController`。
* url的命名以Restful风格进行封装,主要有一下两种方式:
数据接口,可以使用HTTP协议GET、POST、DELETE、PUT等方法请求:
* \${资源名复数} GET方法:查看资源列表
* \${资源名复数} POST方法:增加资源方法
* \${资源名}\${id} GET方法:查看某个资源方法
* \${资源名}\${id} POST方法:保存某个资源方法
* \${资源名}\${id} DELETE方法:删除某个资源方法
* \${资源名}\${id} OPTIONS方法:特定业务操作某个资源方法
页面跳转,可以使用资源名\操作方式进行请求:
* \${资源名} GET\POST方法:查看资源列表
* \${资源名}\add GET\POST方法:增加资源方法
* \${资源名}\${id} GET\POST方法:获取某个资源方法
* \${资源名}\${id}\save GET\POST方法:保存某个资源方法
* \${资源名}\${id}\delete GET\POST方法:删除某个资源方法
* \${资源名}\${id}\enable GET\POST方法:特殊操作某个资源方法、操作方法应为动词

###参考文档
[Spring Framework 开发参考手册.17](http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/mvc.html)

猜你喜欢

转载自bjmike.iteye.com/blog/1987615