Oracle变更:使用 Spring Data JPA 简化 JPA 开发

于一个简单易行的 JPA 示例初步

本文主要讲述 Spring Data JPA,但是为了不至于给 JPA 和 Spring
的新家造成比较生之学曲线,我们首先从 JPA 开始,简单介绍一个 JPA
示例;接着重构该示例,并引入 Spring
框架,这简单组成部分未见面提到了多的字数,如果期望能一针见血学 Spring 和
JPA,可以因本文最后提供的参考资料进一步读书。

从 JPA 伴随 Java EE 5
发布以来,受到了各个大厂商和开源社区的追捧,各种商用的同开源之 JPA
框架而恒河沙数一般出现,为开发者提供了增长的精选。它同改前 EJB 2.x
中实体 Bean 笨重且难以使用的像,充分接受了以开源社区都相对成熟的 ORM
思想。另外,它并无依赖让 EJB
容器,可以看作一个单身的持久层技术使留存。目前于成熟的 JPA
框架主要概括 Jboss 的 Hibernate EntityManager、Oracle 捐献给 Eclipse
社区的 EclipseLink、Apache 的 OpenJPA 等。

本文的示范代码基于 Hibernate EntityManager
开发,但是读者几乎不用修改外代码,便可非常容易地切换到其他 JPA
框架,因为代码中应用及之且是 JPA 规范提供的接口 /
类,并不曾采取到框架本身的私特性。示例主要涉嫌七只文件,但是老清晰:业务层包含一个接口及一个实现;持久层包含一个接口、一个兑现、一个实体类;另外加上一个
JPA 配置文件以及一个测试类。相关类 / 接口代码如下:

清单 1. 实体类 AccountInfo.java
 @Entity 
 @Table(name = "t_accountinfo") 
 public class AccountInfo implements Serializable { 
 private Long accountId; 
 private Integer balance; 

 // 此处省略 getter 和 setter 方法。
 }
清单 2. 业务层接口 UserService.java
 public interface UserService { 
 public AccountInfo createNewAccount(String user, String pwd, Integer init); 
 }
清单 3. 业务层的贯彻类 UserServiceImpl.java
 public class UserServiceImpl implements UserService { 

 private UserDao userDao = new UserDaoImpl(); 

 public AccountInfo createNewAccount(String user, String pwd, Integer init){ 
 // 封装域对象
 AccountInfo accountInfo = new AccountInfo(); 
 UserInfo userInfo = new UserInfo(); 
 userInfo.setUsername(username); 
 userInfo.setPassword(password); 
 accountInfo.setBalance(initBalance); 
 accountInfo.setUserInfo(userInfo); 
 // 调用持久层,完成数据的保存
 return userDao.save(accountInfo); 
    } 
 }
清单 4. 持久层接口
 public interface UserDao { 
 public AccountInfo save(AccountInfo accountInfo); 
 }
清单 5. 持久层的实现类似
 public class UserDaoImpl implements UserDao { 
 public AccountInfo save(AccountInfo accountInfo) { 
 EntityManagerFactory emf = 
 Persistence.createEntityManagerFactory("SimplePU"); 
 EntityManager em = emf.createEntityManager(); 
 em.getTransaction().begin(); 
 em.persist(accountInfo); 
 em.getTransaction().commit(); 
 emf.close(); 
 return accountInfo; 
    } 
 }
清单 6. JPA 标准配置文件 persistence.xml
 <?xml version="1.0" encoding="UTF-8"?> 
 <persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0"> 
 <persistence-unit name="SimplePU" transaction-type="RESOURCE_LOCAL"> 
 <provider>org.hibernate.ejb.HibernatePersistence</provider> 
 <class>footmark.springdata.jpa.domain.UserInfo</class> 
 <class>footmark.springdata.jpa.domain.AccountInfo</class> 
 <properties> 
 <property name="hibernate.connection.driver_class"
 value="com.mysql.jdbc.Driver"/> 
 <property name="hibernate.connection.url" 
 value="jdbc:mysql://10.40.74.197:3306/zhangjp"/> 
 <property name="hibernate.connection.username" value="root"/> 
 <property name="hibernate.connection.password" value="root"/> 
 <property name="hibernate.dialect"
 value="org.hibernate.dialect.MySQL5Dialect"/> 
 <property name="hibernate.show_sql" value="true"/> 
 <property name="hibernate.format_sql" value="true"/> 
 <property name="hibernate.use_sql_comments" value="false"/> 
 <property name="hibernate.hbm2ddl.auto" value="update"/> 
 </properties> 
 </persistence-unit> 
 </persistence>
清单 7. 本文使用如下的 main 方法开展开发者测试
 public class SimpleSpringJpaDemo { 
    public static void main(String[] args) { 
        new UserServiceImpl().createNewAccount("ZhangJianPing", "123456", 1); 
    } 
 }

 

回页首

简述 Spring 框架对 JPA 的支持

属下我们引入 Spring,以显示 Spring 框架对 JPA 的支撑。业务层接口
UserService 保持无变换,UserServiceImpl 中追加了三个注解,以给 Spring
完成因注入,因此不再要利用 new 操作符创建 UserDaoImpl
对象了。同时我们还使用了 Spring 的声明式事务:

清单 8. 布置为 Spring Bean 的业务层实现
 @Service("userService") 
 public class UserServiceImpl implements UserService { 
 @Autowired 
 private UserDao userDao; 

 @Transactional 
 public AccountInfo createNewAccount( 
 String name, String pwd, Integer init) { …… } 
 }

于持久层,UserDao 接口也未待改,只需要修改 UserDaoImpl
实现,修改后底代码如下:

清单 9. 布置为 Spring Bean 的持久层实现
 @Repository("userDao") 
 public class UserDaoImpl implements UserDao { 

 @PersistenceContext 
 private EntityManager em; 

 @Transactional 
   public Long save(AccountInfo accountInfo) { 
 em.persist(accountInfo); 
 return accountInfo.getAccountId(); 
 } 
 }
清单 10. Spring 配置文件
 <?xml version="1.0" encoding="UTF-8"?> 
 <beans...> 
 <context:component-scan base-package="footmark.springdata.jpa"/> 
 <tx:annotation-driven transaction-manager="transactionManager"/> 
 <bean id="transactionManager" 
 class="org.springframework.orm.jpa.JpaTransactionManager"> 
 <property name="entityManagerFactory" ref="entityManagerFactory"/> 
 </bean> 
 <bean id="entityManagerFactory" class= 
"org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    </bean> 
 </beans>
清单 11. 改造后底依据 Spring 的开发者测试代码
 public class SimpleSpringJpaDemo{ 
 public static void main(String[] args){ 
 ClassPathXmlApplicationContext ctx = 
 new ClassPathXmlApplicationContext("spring-demo-cfg.xml"); 
 UserDao userDao = ctx.getBean("userDao", UserDao.class); 
 userDao.createNewAccount("ZhangJianPing", "123456", 1); 
 } 
 }

由此比重构前后的代码,可以窥见 Spring 对 JPA
的简化已经特别精美了,我们得约总结一下 Spring 框架对 JPA
提供的支撑至关重要反映于如下几独面:

  • 率先,它让 JPA 配置变得进一步灵敏。JPA 规范要求,配置文件要命名也
    persistence.xml,并是为类路径下的 META-INF
    目录中。该文件一般含了初始化 JPA 引擎所需要的全部音讯。Spring 提供的
    LocalContainerEntityManagerFactoryBean
    提供了非常灵活的安排,persistence.xml
    中的信息都得以斯以性注入的主意提供。

  • 附带,Spring 实现了片于 EJB 容器环境下才具有的职能,比如针对
    @PersistenceContext、@PersistenceUnit 的容器注入支持。
  • 其三,也是极致富有意义的,Spring 将 EntityManager
    的创造及销毁、事务管理等代码抽取出来,并出于该联合管理,开发者不欲关怀这些,如前的代码所示,业务方法被单独剩余操作领域对象的代码,事务管理和
    EntityManager 创建、销毁的代码都不再要开发者关心了。

 

回页首

再进一步:Spring Data JPA 让整类似完美

经过前的分析可以望,Spring 对 JPA
的支撑曾充分强,开发者只需要关注核心业务逻辑的落实代码,无需过多关心
EntityManager 的创、事务处理等 JPA
相关的拍卖,这差不多也是用作一个支付框架而言所能够好的顶点了。然而,Spring
开发小组并无止步,他们再接再厉,于最近出了 Spring Data JPA
框架,主要针对的哪怕是 Spring
唯一没有简化到之作业逻辑代码,至此,开发者连才剩的落实持久层业务逻辑的工作还看了,唯一要召开的,就一味是声称持久层的接口,其他都交由
Spring Data JPA 来帮衬你得!

从那之后,读者或许会见是一个问题,框架怎么可能替开发者实现工作逻辑吗?毕竟,每一个应用之持久层业务还世界对象还不尽相同,框架是怎么形成的也?其实就背后的考虑并无复杂,比如,当你看
UserDao.findUserById()
这样一个道声明,大致应该能够判断出就是冲加条件的 ID 查询出满足条件的
User 对象。Spring Data JPA
做的就算是标准措施的名字,根据符合规范的名字来确定方法要贯彻怎样的逻辑。

通下去我们对前的例证进行改造,让 Spring Data JPA
来援助我们完成作业逻辑。在着手写代码之前,开发者需要先 下载Spring
Data JPA 的发布包(需要以下载 Spring Data Commons 和 Spring Data JPA
个别单公布包,Commons 是 Spring Data 的公物基础包),并拿相关的负 JAR
文件在到 CLASSPATH 中。

第一,让持久层接口 UserDao 继承 Repository
接口。该接口使用了泛型,需要吗其提供个别只项目:第一只为该接口处理的所在对象类型,第二个吗该域对象的主键类型。修改后底
UserDao 如下:

清单 12. Spring Data JPA 风格的持久层接口
 public interface UserDao extends Repository<AccountInfo, Long> { 
    public AccountInfo save(AccountInfo accountInfo); 
 }

然后去 UserDaoImpl
类,因为我们眼前说过,框架会呢咱成功作业逻辑。最后,我们需要以 Spring
配置文件中益如下配置,以要 Spring 识别出得也其促成之持久层接口:

清单 13. 每当 Spring 配置文件中启用扫描并活动创建代理的效能
 <-- 需要在 <beans> 标签中增加对 jpa 命名空间的引用 --> 
 <jpa:repositories base-package="footmark.springdata.jpa.dao"
 entity-manager-factory-ref="entityManagerFactory" 
 transaction-manager-ref="transactionManager"/>

从那之后便杀功告成了!执行一下测试代码,然后看一下数据库,新的多少就使我辈预料的丰富顶表中了。如果只要双重追加新的恒久层业务,比如希望查询有为
ID 的 AccountInfo 对象,该怎么收拾为?很简单,在 UserDao
接口中长一行代码即可:

清单 14. 改动后的持久层接口,增加一个智声明
 public interface UserDao extends Repository<AccountInfo, Long> { 

 public AccountInfo save(AccountInfo accountInfo); 

 // 你需要做的,仅仅是新增如下一行方法声明
 public AccountInfo findByAccountId(Long accountId); 
 }

脚总结一下用 Spring Data JPA 进行持久层开发大致需要之老三独步骤:

  1. 扬言持久层的接口,该接口继承 Repository,Repository
    是一个标记型接口,它不包含其他方法,当然如果发生需要,Spring Data
    也供了好多 Repository
    子接口,其中定义了有的常用之增删改查,以及分页相关的法门。
  2. 于接口中宣示需要的政工方法。Spring Data
    将因加的政策(具体政策稍后讲解)来呢那个变实现代码。
  3. 每当 Spring 配置文件被增加一行声明,让 Spring
    为声明的接口创建代理对象。配置了 <jpa:repositories> 后,Spring
    初始化容器时拿会扫描 base-package 指定的包目录及其子目录,为后续
    Repository 或其子接口的接口创建代理对象,并拿代理对象注册为 Spring
    Bean,业务层即可由此 Spring 自动包的特色来直接行使该目标。

除此以外,<jpa:repository>
还提供了有些性质和子标签,便于做还细粒度的主宰。可以以
<jpa:repository> 内部使用
<context:include-filter>、<context:exclude-filter>
来过滤掉一部分无指望为围观到之接口。具体的运办法见 Spring参照文档。

该继承哪个接口?

前方提到,持久层接口继承 Repository 并无是唯一选择。Repository 接口是
Spring Data
的一个基本接口,它不提供任何措施,开发者需要以祥和定义的接口中宣示需要之点子。与继承
Repository 等价格的一致种办法,就是于持久层接口及运 @RepositoryDefinition
注解,并为其指定 domainClass 和 idClass 属性。如下两栽方法是了等价格的:

清单 15. 少种等价的连续接口方式示例
 public interface UserDao extends Repository<AccountInfo, Long> { …… } 

 @RepositoryDefinition(domainClass = AccountInfo.class, idClass = Long.class) 
 public interface UserDao { …… }

要持久层接口较多,且每一个接口都得声明相似之增删改查方法,直接接轨
Repository 就显略微啰嗦,这时可以持续
CrudRepository,它会活动为域对象创建增删改查方法,供业务层直接使用。开发者只是多写了
“Crud” 四独字母,即刻便为域对象提供了开箱即用的十单增删改查方法。

不过,使用 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
在后台为持久层接口创建代理对象时,会分析方法名字,并促成相应的效力。除了通过措施名字之外,它还可以通过如下两种艺术指定查询语句:

  1. Spring Data JPA 可以拜 JPA
    命名查询语句。开发者只待以概念命名查询语句时,为其指定一个可被定格式的讳,Spring
    Data JPA 便会当开立代理对象时,使用该命名查询语句来实现该效力。
  2. 开发者还好直接当宣称的方式方面下 @Query
    注解,并提供一个查询语句作为参数,Spring Data JPA
    在开创代理对象时,便以提供的查询语句来落实该职能。

下面我们独家讲述三栽创建查询的章程。

经过分析方法名创建查询

经过前的事例,读者多对分析方法名创建查询的不二法门来了一个大致的摸底,这吗是
Spring Data JPA 吸引开发者的一个深要紧的要素。该意义实在无须 Spring Data
JPA 首创,而是源自一个开源之 JPA 框架 Hades,该框架的作者 Oliver Gierke
本身又是 Spring Data JPA 项目之 Leader,所以把 Hades 的优势引入到 Spring
Data JPA 也就是言之有理的了。

框架在开展方式名解析时,会先把措施名多余的前方缀截取掉,比如
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 注解的使非常简单,只待以声明的道方面标注该注解,同时提供一个
JP QL 查询语句即可,如下所示:

清单 16. 下 @Query 提供由定义查询语句示例
 public interface UserDao extends Repository<AccountInfo, Long> { 

 @Query("select a from AccountInfo a where a.accountId = ?1") 
 public AccountInfo findByAccountId(Long accountId); 

    @Query("select a from AccountInfo a where a.balance > ?1") 
 public Page<AccountInfo> findByBalanceGreaterThan( 
 Integer balance,Pageable pageable); 
 }

许多开发者在开创 JP QL 时好以命名参数来顶替位置编号,@Query
也对之提供了支持。JP QL 语句被经”:
变量”的格式来指定参数,同时于章程的参数前面使用 @Param 将艺术参数和 JP
QL 中之命名参数对应,示例如下:

清单 17. @Query 支持命名参数示例
 public interface UserDao extends Repository<AccountInfo, Long> { 

 public AccountInfo save(AccountInfo accountInfo); 

 @Query("from AccountInfo a where a.accountId = :id") 
 public AccountInfo findByAccountId(@Param("id")Long accountId); 

   @Query("from AccountInfo a where a.balance > :balance") 
   public Page<AccountInfo> findByBalanceGreaterThan( 
 @Param("balance")Integer balance,Pageable pageable); 
 }

除此以外,开发者也足以通过采取 @Query
来实行一个翻新操作,为者,我们要以采取 @Query 的又,用 @Modifying
来拿欠操作标识也修改查询,这样框架最终见面变一个创新的操作,而非查询。如下所示:

清单 18. 用 @Modifying 将查询标识也修改查询
 @Modifying 
 @Query("update AccountInfo a set a.salary = ?1 where a.salary < ?2") 
 public int increaseSalary(int after, int before);

由此调用 JPA 命名查询语句子创建查询

命名查询是 JPA
提供的平等种植将查询语句从方法体中独出来,以供多单道并用的效果。Spring
Data JPA 对命名查询也提供了挺好的支撑。用户只有待按 JPA 规范在 orm.xml
文件或者当代码中应用 @NamedQuery(或
@NamedNativeQuery)定义好查询语句,唯一要做的尽管是为该语句命名时,需要满足”DomainClass.methodName()”的命名规则。假设定义了如下接口:

清单 19. 采取 JPA 命名查询时,声明接口及办法时未欲什么新鲜处理
 public interface UserDao extends Repository<AccountInfo, Long> { 

 ...... 

 public List<AccountInfo> findTop5(); 
 }

若是指望为 findTop5()
创建命名查询,并和的干,我们只是待以当的职定义命名查询语句,并拿其取名也
“AccountInfo.findTop5″,框架在创立代理类的过程被,解析及拖欠办法时,优先找名吧
“AccountInfo.findTop5”
的命名查询定义,如果没找到,则尝试解析方法名,根据办法名字创办查询。

创查询的各个

Spring Data JPA
在也接口创建代理对象时,如果发现并且在多上述情况可用,它该先使用哪种政策也?为这,<jpa:repositories>
提供了 query-lookup-strategy
属性,用以指定查找的逐条。它发出如下三单取值:

  • create —
    通过分析方法名字来创造查询。即使有适合的命名查询,或者措施通过
    @Query 指定的询问语句,都拿会给忽视。
  • create-if-not-found — 如果艺术通过 @Query
    指定了查询语句,则以该语句实现查询;如果没有,则寻是否定义了符合条件的命名查询,如果找到,则使用该命名查询;如果两岸都不曾找到,则透过分析方法名字来创造查询。这是
    query-lookup-strategy 属性的默认值。
  • use-declared-query — 如果措施通过 @Query
    指定了询问语句,则使该语句实现查询;如果没,则寻是否定义了符合条件的命名查询,如果找到,则应用该命名查询;如果双方都没有找到,则弃来十分。

Spring Data JPA 对工作的支撑

默认情况下,Spring Data JPA
实现的主意都是使用工作之。针对查询类型的方,其相当于于
@Transactional(readOnly=true);增删改类型的道,等价于
@Transactional。可以见到,除了用查询的计要为才读事务外,其他作业属性都用默认值。

只要用户认为有必要,可以当接口方法上采用 @Transactional
显式指定业务属性,该值覆盖 Spring Data JPA
提供的默认值。同时,开发者也可于业务层方法上运 @Transactional
指定工作属性,这要对一个业务层方法多次调用持久层方法的情况。持久层的事务会根据设置的工作传播行为来决定是悬挂于业务层事务还是进入业务层的事务。具体
@Transactional
的使,请参考 Spring的参照文档。

也接口中之一些方法供于定义实现

些微上,开发者可能得以某些方法中举行一些与众不同的处理,此时自动生成的代理对象不克全满足要求。为了享受
Spring Data JPA
带吃咱们的方便,同时又能够为一些方法供自定义实现,我们得以利用如下的措施:

  • 以索要开发者手动实现之方式从持久层接口(假设为 AccountDao
    )中抽取出来,独立成为一个初的接口(假设为 AccountDaoPlus ),并吃
    AccountDao 继承 AccountDaoPlus;
  • 为 AccountDaoPlus 提供自定义实现(假设为 AccountDaoPlusImpl );
  • 将 AccountDaoPlusImpl 配置为 Spring Bean;
  • 于 <jpa:repositories> 中遵循清单 19 之方展开布置。
清单 20. 指定由定义实现类似
 <jpa:repositories base-package="footmark.springdata.jpa.dao"> 
 <jpa:repository id="accountDao" repository-impl-ref=" accountDaoPlus " /> 
 </jpa:repositories> 

 <bean id="accountDaoPlus" class="......."/>

除此以外,<jpa:repositories > 提供了一个 repository-impl-postfix
属性,用以指定实现类似的后缀。假设做了之类配置:

清单 21. 安装自动搜索时默认的自定义实现类似命名规则
 <jpa:repositories base-package="footmark.springdata.jpa.dao"
 repository-impl-postfix="Impl"/>

虽然在框架扫描到 AccountDao 接口时,它用尝试以平的包目录下寻找
AccountDaoImpl.java,如果找到,便将内部的实现方式作为最后生成的代理类中相应措施的兑现。

转:http://www.ibm.com/developerworks/cn/opensource/os-cn-spring-jpa/\#icomments

相关文章