1.概述
本文将重点介绍Spring 3.1,JPA和Spring Data的持久层的配置和实现。 有关使用基于Java的配置和项目的基本Maven pom设置Spring上下文的分步介绍,请参阅本文 。
持久性与春天 系列 :
- 第1部分 – 具有Spring 3.1和Hibernate的持久层
- 第2部分 – 使用Spring和Java泛型简化数据访问层
- 第3部分 – 具有Spring 3.1和JPA的持久层
- 第4部分 – 使用Spring Data JPA的持久层
- 第5部分 – 使用JPA和Spring 3.1进行事务配置
2.没有更多的DAO实现
如前一篇文章中所讨论的, DAO层通常包含许多可以并且应该简化的样板代码。 这种简化的优点有很多方面:减少需要定义和维护的工件数量,简化和简化数据访问模式并保持配置一致性。
Spring Data将这一简化向前迈了一步,并且有可能完全删除DAO实现-DAO的接口现在是唯一需要明确定义的工件。
3. Spring Data管理的DAO
为了开始通过JPA使用Spring Data编程模型,DAO接口需要在Spring的接口层次结构中扩展JPA特定的Repository接口– JpaRepository 。 这将使Spring Data能够找到该接口并为其自动创建一个实现。
此外,通过扩展接口,我们可以获得DAO中可用的大多数(即使不是全部)相关的CRUD通用方法来进行标准数据访问。
4.定义自定义访问方法和查询
如上所述,通过实现存储库接口之一,DAO将已经定义和实现了一些基本的CRUD方法(和查询)。 为了定义更具体的访问方法,Spring JPA支持许多选项–您可以在界面中简单地定义一个新方法 ,或者可以使用@Query注释提供实际的JPQ查询 。
定义自定义查询的第三个选项是使用JPA命名查询,但这具有以下缺点:要么涉及XML,要么使查询负担域类。
除了这些之外,Spring Data 引入了更灵活和方便的API,类似于JPA Criteria API,只是更具可读性和可重用性。 当处理大量固定查询时,此API的优势将变得更加明显,这些固定查询可以通过较少数量的可重复使用的块(以不同的组合形式不断出现)来更简洁地表达。
4.1。 自动自定义查询
当Spring Data创建一个新的Repository实现时,它会分析接口定义的所有方法,并尝试根据方法名自动生成查询。 尽管这有局限性,但它是一种非常有用且优雅的方法,可以轻松定义新的自定义访问方法。
例如,如果管理实体具有名称字段(以及该字段的Java Bean标准getter和setter),则在DAO接口中定义findByName方法将自动生成正确的查询:
public interface IFooDAO extends JpaRepository< Foo, Long >{Foo findByName( final String name );}
这是一个相对简单的例子。 查询创建机制支持更多的关键字集 。
如果解析器无法将该属性与域对象字段匹配,则会引发以下异常:
java.lang.IllegalArgumentException:未为类型类org.rest.model.Foo找到属性nam
4.2。 手动自定义查询
除了从方法名称派生查询外,还可以使用方法级别@Query注释手动指定自定义查询。
为了对查询的创建进行更精细的控制,例如使用命名参数或修改现有查询, 该参考是一个不错的起点。
5. Spring Data事务配置
Spring Data托管DAO的实际实现-SimpleJpaRepository-使用注释来定义和配置事务 。 在类级别使用只读@Transactional批注,然后将其替换为非只读方法。 其余的事务语义是默认的,但是可以很容易地按方法手动覆盖它们。
5.1。 没有模板的异常翻译
Spring ORM模板( JpaTemplate , HibernateTemplate )的职责之一是异常转换 -将JPA异常(将API与JPA关联) 转换为Spring的DataAccessException层次结构。
没有模板可以执行此操作,仍然可以通过使用@Repository批注对DAO进行批注来启用异常转换。 结合使用Spring bean后处理器,将为所有@Repository bean提供在Container中找到的PersistenceExceptionTranslator的所有实现–无需使用模板即可提供异常转换。
异常转换确实有效的事实可以通过集成测试轻松验证:
@Test( expected = DataAccessException.class )
public void whenAUniqueConstraintIsBroken_thenSpringSpecificExceptionIsThrown(){String name = "randomName";service.save( new Foo( name ) );service.save( new Foo( name ) );
}
异常翻译是通过代理完成的; 为了使Spring能够围绕DAO类创建代理,不得将它们声明为final 。
6. Spring数据配置
为了激活Spring JPA存储库支持,定义了jpa命名空间并将其用于指定DAO接口所位于的包:
<?xml version="1.0" encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:jpa="http://www.springframework.org/schema/data/jpa"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.2.xsdhttp://www.springframework.org/schema/data/jpahttp://www.springframework.org/schema/data/jpa/spring-jpa.xsd"><jpa:repositories base-package="org.rest.dao.spring" /></beans>
在这一点上,没有等效的基于Java的配置–然而,对它的支持正在进行中 。
7. Spring Java或XML配置
该系列的上一篇文章已经详细讨论了如何在Spring 3中配置JPA 。 Spring Data还利用了对JPA @PersistenceContext批注的Spring支持,该批注用于将EntityManager连接到负责创建实际DAO实现的Spring工厂bean – JpaRepositoryFactoryBean 。
除了已经讨论过的配置之外,还有最后一个缺失的部分–包括整体持久性配置中的Spring Data XML配置:
@Configuration
@EnableTransactionManagement
@ImportResource( "classpath*:*springDataConfig.xml" )
public class PersistenceJPAConfig{...
}
8. Maven配置
除了上一篇文章中定义的JPA的Maven配置之外,还添加了spring-data-jpa依赖项:
<dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-jpa</artifactId><version>1.3.2.RELEASE</version>
</dependency>
9.结论
本文介绍了使用基于XML和Java的配置以及Spring 3.1,JPA 2和Spring JPA(属于Spring Data伞项目的一部分)的持久层的配置和实现。 讨论了定义更高级的自定义查询的各种方法,以及使用新的jpa名称空间和事务语义的配置。 最终结果是对Spring进行数据访问的一种新颖而优雅的方式,几乎没有实际的实现工作。 您可以在github项目中查看完整的实现。
翻译自: https://www.javacodegeeks.com/2011/12/persistence-layer-with-spring-data-jpa.html