Spring Data学习记录
事务管理
Spring 解决了全局和局部事务的弊端。它让应用开发者在任何环境下都能使用一个一致的编程模型。你只需写一次代码,它就可以在不同的环境中受益于不同的事务管理策略。Spring 框架同时提供声明式和编程式事务管理。
全局事务
全局事务让你与多个事务性资源一起工作,通常是关系型数据库和消息队列。应用服务器通过 JTA 管理全局事务,这意味着你也需要使用 JNDI 才能使用 JTA。全局事务的使用限制了任何潜在的应用程序代码的重用,因为 JTA 通常只在应用程序服务器环境中可用。
本地事务
本地事务是特定资源的,例如与 JDBC 连接相关的事务。本地事务可能更容易使用,但有一个明显的缺点: 它们不能跨多个事务资源工作。
Spring 事务抽象
Spring 事务抽象的关键是事务策略的概念。事务策略是由 TransactionManager 定义的
TransactionDefinition 接口规定了:
- Propagation: 通常情况下,一个事务范围内的所有代码都在该事务中运行。
- Isolation: 这个事务与其他事务的隔离级别
- Timeout: 这个事务会保持多久直到由基础事务基础设施自动超时并回滚。
- Read-only status(只读状态): 当你的代码读取但不修改数据时,你可以使用一个只读事务。
引入:
1 | public interface PlatformTransactionManager extends TransactionManager { |
Hibernate 本地事务
需要定义一个 Hibernate LocalSessionFactoryBean,你的应用代码可以用它来获取 Hibernate Session 实例。
关于具体如何使用可以查阅我关于 Spring Boot 的文档,因为 Spring Boot 为我们提供了许多便捷,所以我们不需要掌握如何使用 Spring 了,如果感兴趣,可以自行了解 Spring 的使用方法。
声明式事务管理
Spring 框架的声明式事务管理是通过 Spring 面向切面编程(AOP)实现的。然而,由于事务方面的代码是随 Spring 框架的发布而来,并且可以以模板的方式使用,所以一般不需要理解 AOP 的概念来有效地使用这些代码。
- 你可以将 Spring 框架的声明式事务管理应用于任何类
- Spring 框架提供了声明式的回滚规则
- Spring 框架允许你通过使用 AOP 来定制事务行为
- Spring 框架不支持跨远程调用的事务上下文的传播,如果你需要这个功能,我们建议你使用 EJB。然而,在使用这种功能之前,请仔细考虑,因为,通常情况下,人们不希望事务跨越远程调用。
*回滚规则的概念很重要。它们让你指定哪些异常(和 throwable)应该导致自动回滚。你可以在配置中声明性地指定,而不是在 Java 代码中。因此,尽管你仍然可以在 TransactionStatus 对象上调用 setRollbackOnly() 来回滚当前事务,但最常见的是你可以指定一个规则,即 MyApplicationException 必须总是导致回滚。
使用:
- @Transactional 注解来注解你的类,开始事务
- @EnableTransactionManagement 添加到你的配置中
示例:
1 | // the service class that we want to make transactional |
@Transactional 设置
@Transactional 注解是指定接口、类或方法必须具有事务性语义的元数据
@Transactional 设置如下:
propagation (传播)设置为 PROPAGATION_REQUIRED。
隔离级别是 ISOLATION_DEFAULT。
事务是读写的。
事务超时默认为底层事务系统的默认超时,如果不支持超时,则默认为无。
任何 RuntimeException 或 Error 都会触发回滚,而任何被检查的 Exception 则不会。
事务绑定的事件
事件的监听器可以被绑定到事务的某个阶段。典型的例子是在事务成功完成时处理该事件。
使用 @EventListener 注解来注册一个普通的事件监听器。如果你需要将其绑定到事务上,请使用 @TransactionalEventListener。当你这样做的时候,监听器默认被绑定到事务的提交阶段。
示例:假设一个组件发布了一个创建订单的事件,我们想定义一个监听器,它只在发布该事件的事务成功提交后处理该事件
1 |
|
数据访问对象(DAO)
Spring 中的数据访问对象(DAO)支持旨在使数据访问技术(如 JDBC、Hibernate 或 JPA)以一致的方式轻松工作。这可以让你在上述持久化技术之间轻松切换,也可以让你在编码时不必担心 catch 每种技术特有的异常。
我们在 DAO 层编码时无需关注异常声明
配置 DAO 或 Repository 类
保证你的数据访问对象(DAO)或 Repository 提供异常翻译的最好方法是使用 @Repository 注解。这个注解还可以让组件扫描支持找到并配置你的 DAO 和 Repository,而不需要为它们提供 XML 配置条目。
任何 DAO 或 repository 的实现都需要访问一个持久化资源,这取决于所使用的持久化技术。例如,基于 JDBC 的 repository 需要访问 JDBC DataSource,而基于 JPA 的 repository 需要访问 EntityManager。
JDBC 介绍
Spring 框架的 JDBC 抽象框架由四个不同的包组成:
- core: 包包含 JdbcTemplate 类和它的各种回调接口,还有各种相关的类。
- datasource:包含了一个实用类,用于轻松访问 DataSource 和各种简单的 DataSource 实现
- object:包含的类将 RDBMS 的查询、更新和存储过程表现为线程安全的、可重用的对象。
- support:提供 SQLException 翻译功能和一些实用类。
使用 JdbcTemplate
JdbcTemplate 类:
运行 SQL 查询
更新语句和存储过程调用
对 ResultSet 实例进行迭代并提取返回的参数值。
Catch JDBC 异常,并将它们翻译成 org.springframework.dao 包中定义的通用的、信息量更大的异常层次结构。
查询:
1 | int rowCount = this.jdbcTemplate.queryForObject("select count(*) from t_actor", Integer.class); |
插入:
1 | this.jdbcTemplate.update( |
更新:
1 | this.jdbcTemplate.update( |
删除
1 | this.jdbcTemplate.update( |
其它操作
使用 execute(..) 方法来运行任何任意的 SQL。
示例:
1 | this.jdbcTemplate.update( |
使用 NamedParameterJdbcTemplate
1 | // some JDBC-backed DAO class... |
关于 JDBC 的更多操作请自行查阅,因为目前我们常用 mybatis 等框架不需要在自行写 JDBC 了