Spring数据访问

Spring数据访问,个人认为还是比较易懂的~

数据访问

1. Transaction Management

1.1. Spring Framework 的事务支持模型的优点

1.2. 理解 Spring 框架事务抽象

1.3. 将资源与事务同步

1.4. 声明式事务管理

1.5. 程序化事务管理

2. DAO 支持

2.1. 一致的异常层次结构

2.2. 用于配置 DAO 或存储库类的注释


数据访问

1. Transaction Management

全面的事务支持是使用 Spring Framework 的最令人信服的理由之一。Spring Framework 为事务管理提供了一致的抽象,具有以下优点:

  • 跨不同事务 API 的一致编程模型,例如 Java 事务 API (JTA)、JDBC、Hibernate 和 Java Persistence API (JPA)。

  • 支持声明式事务管理。

  • 比复杂的事务 API(例如 JTA)更简单的用于程序化事务管理的 API。

  • 与 Spring 的数据访问抽象的完美集成。

以下部分描述了 Spring Framework 的事务特性和技术:

  • Spring Framework 事务支持模型的优点描述了为什么要使用 Spring Framework 的事务抽象而不是 EJB 容器管理事务 (CMT) 或选择通过专有 API(例如 Hibernate)驱动本地事务。

  • 理解 Spring Framework 事务抽象 概述了核心类并描述了如何DataSource 从各种来源配置和获取实例。

  • 将资源与事务同步描述了应用程序代码如何确保正确创建、重用和清理资源。

  • 声明式事务管理描述了对声明式事务管理的支持。

  • 程序化事务管理涵盖了对程序化(即显式编码)事务管理的支持。

  • 事务绑定事件描述了如何在事务中使用应用程序事件。

1.1. Spring Framework 的事务支持模型的优点

传统上,Java EE 开发人员对事务管理有两种选择:全局事务或本地事务,两者都有很大的局限性。在接下来的两节中回顾全局和本地事务管理,然后讨论 Spring Framework 的事务管理支持如何解决全局和本地事务模型的局限性。

1.1.1. Global Transactions

全局事务可以使用多个事务资源,通常是关系数据库和消息队列。

1.1.2. Local Transactions

本地事务是特定于资源的,例如与 JDBC 连接关联的事务。本地事务可能更易于使用,但有一个明显的缺点:它们不能跨多个事务资源工作。

1.1.3. Spring Framework 的一致编程模型

Spring 解决了全局事务和本地事务的缺点。它允许应用程序开发人员在任何环境中使用一致的编程模型。

通过编程事务管理,开发人员可以使用 Spring Framework 事务抽象,它可以在任何底层事务基础架构上运行。使用首选声明式模型,开发人员通常很少编写或不编写与事务管理相关的代码,因此不依赖于 Spring Framework 事务 API 或任何其他事务 API。

1.2. 理解 Spring 框架事务抽象

Spring 事务抽象的关键是事务策略的概念。事务策略由 定义TransactionManager,特别是 org.springframework.transaction.PlatformTransactionManager命令式事务管理的org.springframework.transaction.ReactiveTransactionManager接口和反应式事务管理的 接口。以下清单显示了PlatformTransactionManagerAPI的定义 :

 public interface PlatformTransactionManager extends TransactionManager {
 ​
     TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
 ​
     void commit(TransactionStatus status) throws TransactionException;
 ​
     void rollback(TransactionStatus status) throws TransactionException;
 }

以下清单显示了由 定义的事务策略 org.springframework.transaction.ReactiveTransactionManager

 public interface ReactiveTransactionManager extends TransactionManager {
 ​
     Mono<ReactiveTransaction> getReactiveTransaction(TransactionDefinition definition) throws TransactionException;
 ​
     Mono<Void> commit(ReactiveTransaction status) throws TransactionException;
 ​
     Mono<Void> rollback(ReactiveTransaction status) throws TransactionException;
 }

反应式事务管理器主要是一个服务提供者接口 (SPI),尽管您可以从应用程序代码中以编程方式使用它。因为ReactiveTransactionManager是一个接口,所以可以根据需要轻松模拟或存根。

TransactionDefinition接口指定:

  • 传播:通常,事务范围内的所有代码都在该事务中运行。但是,如果在事务上下文已经存在时运行事务方法,您可以指定行为。例如,代码可以在现有事务中继续运行(常见情况),或者可以暂停现有事务并创建新事务。Spring 提供了 EJB CMT 中熟悉的所有事务传播选项。

  • 隔离度:此事务与其他事务的工作隔离的程度。例如,这个事务可以看到来自其他事务的未提交的写入吗?

  • 超时:此事务在超时和被底层事务基础设施自动回滚之前运行的时间。

  • 只读状态:当您的代码读取但不修改数据时,您可以使用只读事务。在某些情况下,只读事务可能是一种有用的优化,例如当您使用 Hibernate 时。

TransactionStatus接口为事务代码提供了一种简单的方式来控制事务执行和查询事务状态。这些概念应该很熟悉,因为它们对所有事务 API 都是通用的。以下清单显示了 TransactionStatus界面:

 
public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {
 ​
     @Override
     boolean isNewTransaction();
 ​
     boolean hasSavepoint();
 ​
     @Override
     void setRollbackOnly();
 ​
     @Override
     boolean isRollbackOnly();
 ​
     void flush();
 ​
     @Override
     boolean isCompleted();
 }

以下示例展示了如何定义本地PlatformTransactionManager实现(在本例中,使用普通 JDBC。)

datasource

 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
     <property name="driverClassName" value="${jdbc.driverClassName}" />
     <property name="url" value="${jdbc.url}" />
     <property name="username" value="${jdbc.username}" />
     <property name="password" value="${jdbc.password}" />
 </bean>

然后相关的PlatformTransactionManagerbean 定义有一个对DataSource定义的引用 。它应该类似于以下示例:

 <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
     <property name="dataSource" ref="dataSource"/>
 </bean>

如果在 Java EE 容器中使用 JTA,那么将DataSource通过 JNDI 获得的容器与 Spring 的JtaTransactionManager. 以下示例显示了 JTA 和 JNDI 查找版本的样子:

 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:jee="http://www.springframework.org/schema/jee"
     xsi:schemaLocation="
         http://www.springframework.org/schema/beans
         https://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/jee
         https://www.springframework.org/schema/jee/spring-jee.xsd">
 ​
     <jee:jndi-lookup id="dataSource" jndi-name="jdbc/jpetstore"/>
 ​
     <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
 ​
     <!-- other <bean/> definitions here -->
 ​
 </beans>

1.2.1. 休眠事务设置

还可以轻松地使用 Hibernate 本地事务,

以下示例声明sessionFactorytxManagerbean:

 <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
     <property name="dataSource" ref="dataSource"/>
     <property name="mappingResources">
         <list>
             <value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
         </list>
     </property>
     <property name="hibernateProperties">
         <value>
             hibernate.dialect=${hibernate.dialect}
         </value>
     </property>
 </bean>
 ​
 <bean id="txManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
     <property name="sessionFactory" ref="sessionFactory"/>
 </bean>

如果使用 Hibernate 和 Java EE 容器管理的 JTA 事务,应该使用与JtaTransactionManager前面的 JTA 示例相同的 JDBC,如以下示例所示。此外,建议通过其事务协调器以及可能的连接释放模式配置使 Hibernate 了解 JTA:

 <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
     <property name="dataSource" ref="dataSource"/>
     <property name="mappingResources">
         <list>
             <value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
         </list>
     </property>
     <property name="hibernateProperties">
         <value>
             hibernate.dialect=${hibernate.dialect}
             hibernate.transaction.coordinator_class=jta
             hibernate.connection.handling_mode=DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT
         </value>
     </property>
 </bean>
 ​
 <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>

或者,可以传递给JtaTransactionManager LocalSessionFactoryBean 以强制执行相同的默认值:

 <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
     <property name="dataSource" ref="dataSource"/>
     <property name="mappingResources">
         <list>
             <value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
         </list>
     </property>
     <property name="hibernateProperties">
         <value>
             hibernate.dialect=${hibernate.dialect}
             hibernate.transaction.coordinator_class=jta
             hibernate.connection.handling_mode=DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT
         </value>
     </property>
 </bean>
 ​
 <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>

1.3. 将资源与事务同步

如何创建不同的事务管理器以及它们如何链接到需要同步到事务的相关资源(例如DataSourceTransactionManager 到 JDBC DataSourceHibernateTransactionManager到 HibernateSessionFactory等)现在应该很清楚了。

1.3.1. 高级同步方法

首选方法是使用 Spring 的最高级别基于模板的持久性集成 API,或者使用带有事务感知工厂 bean 或代理的本机 ORM API 来管理本机资源工厂。

1.3.2. 低级同步方法

诸如DataSourceUtils(对于JDBC)、EntityManagerFactoryUtils(对于JPA)、 SessionFactoryUtils(对于Hibernate)等类存在于较低级别。当您希望应用程序代码直接处理原生持久化 API 的资源类型时,您可以使用这些类来确保获得适当的 Spring Framework 管理的实例,事务(可选)同步,并且过程中发生的异常是正确映射到一致的 API。例如,在JDBC的情况下,您可以使用Spring的类代替 传统的JDBC方式在 上调用getConnection()方法,如下所示:

DataSource``org.springframework.jdbc.datasource.DataSourceUtils

Connection conn = DataSourceUtils.getConnection(dataSource);
 

如果现有事务已经有一个与之同步(链接)的连接,则返回该实例。否则,该方法调用会触发新连接的创建,该连接(可选)同步到任何现有事务,并可供后续在同一事务中重用。如前所述, any SQLException包装在 Spring Framework 中CannotGetJdbcConnectionException,Spring Framework 的未检查DataAccessException类型层次结构之一。这种方法提供了比从 中轻松获取的更多信息,SQLException并确保了跨数据库甚至跨不同持久性技术的可移植性。

这种方法也可以在没有 Spring 事务管理的情况下工作(事务同步是可选的),因此无论是否使用 Spring 进行事务管理,都可以使用它。

当然,一旦使用了 Spring 的 JDBC 支持、JPA 支持或 Hibernate 支持通常不喜使用DataSourceUtils或其他辅助类,因为通过 Spring 抽象工作比直接使用相关 API 更快乐。例如,如果使用 SpringJdbcTemplatejdbc.object包来简化您对 JDBC 的使用,则正确的连接检索发生在幕后,无需编写任何特殊代码。

1.3.3. TransactionAwareDataSourceProxy

在最底层存在TransactionAwareDataSourceProxy类。这是一个 target 的代理DataSource,它包装了 targetDataSource以增加对 Spring 管理的事务的感知。在这方面,它类似于DataSourceJava EE 服务器提供的事务性 JNDI 。

几乎不需要或不想使用此类,除非必须调用现有代码并传递标准 JDBCDataSource接口实现。在这种情况下,此代码可能可用但正在参与 Spring 管理的事务。可以使用前面提到的更高级别的抽象来编写新代码。

1.4. 声明式事务管理

Spring Framework 的声明式事务管理通过 Spring 面向方面的编程 (AOP) 成为可能。但是,由于事务方面代码随 Spring Framework 发行版一起提供并且可以样板方式使用,因此通常不必理解 AOP 概念即可有效使用此代码。

Spring Framework 的声明式事务管理类似于 EJB CMT,因为可以将事务行为(或缺少它&

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Eieiiii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值