Spring JDBC框架
JDBC框架概述:
在使用普通的 JDBC 数据库时,就会很麻烦的写不必要的代码来处理异常,打开和关闭数据库连接等。但 Spring JDBC 框架负责所有的低层细节,从开始打开连接,准备和执行 SQL 语句,处理异常,处理事务,到最后关闭连接。
所以当从数据库中获取数据时,你所做的是定义连接参数,指定要执行的 SQL 语句,每次迭代完成所需的工作。
Spring JDBC 提供几种方法和数据库中相应的不同的类与接口。我将给出使用 JdbcTemplate 类框架的经典和最受欢迎的方法。这是管理所有数据库通信和异常处理的中央框架类。
JdbcTemplate类型:
JdbcTemplate 类执行 SQL 查询、更新语句和存储过程调用,执行迭代结果集和提取返回参数值。它也捕获 JDBC 异常并转换它们到 org.springframework.dao 包中定义的通用类、更多的信息、异常层次结构。
JdbcTemplate 类的实例是线程安全配置的。所以你可以配置 JdbcTemplate 的单个实例,然后将这个共享的引用安全地注入到多个 DAOs 中。
使用 JdbcTemplate 类时常见的做法是在你的 Spring 配置文件中配置数据源,然后共享数据源 bean 依赖注入到 DAO 类中,并在数据源的设值函数中创建了 JdbcTemplate。
1 | <bean id="dataSource" |
数据访问对象(DAO):
DAO 代表常用的数据库交互的数据访问对象。DAOs 提供一种方法来读取数据并将数据写入到数据库中,它们应该通过一个接口显示此功能,应用程序的其余部分将访问它们。
在 Spring 中,数据访问对象(DAO)支持很容易用统一的方法使用数据访问技术,如 JDBC、Hibernate、JPA 或者 JDO。
Spring JDBC 示例:
目标:通过Spring JDBC 框架,来实现创建一个数据表。
1 | CREATE TABLE Student( |
StudentDAO.java
1 | package jdbc; |
Student.java
1 | package jdbc; |
StudentMapper.java
1 | package jdbc; |
下面是为定义的 DAO 接口 StudentDAO 的实现类文件 StudentJDBCTemplate.java:
1 | package jdbc; |
MainApp.java
1 | package jdbc; |
配置文件 JDBC.xml 的内容 :
1 |
|
运行结果:
1 | ------创建记录-------- |
Spring事务管理
事物管理:
一个数据库事务是一个被视为单一的工作单元的操作序列。这些操作应该要么完整地执行,要么完全不执行。事务管理是一个重要组成部分,RDBMS 面向企业应用程序,以确保数据完整性和一致性。事务的概念可以描述为具有以下四个关键属性说成是 ACID:
- 原子性:事务应该当作一个单独单元的操作,这意味着整个序列操作要么是成功,要么是失败的。
- 一致性:这表示数据库的引用完整性的一致性,表中唯一的主键等。
- 隔离性:可能同时处理很多有相同的数据集的事务,每个事务应该与其他事务隔离,以防止数据损坏。
- 持久性:一个事务一旦完成全部操作后,这个事务的结果必须是永久性的,不能因系统故障而从数据库中删除。
一个真正的 RDBMS 数据库系统将为每个事务保证所有的四个属性。使用 SQL 发布到数据库中的事务的简单视图如下:
- 使用 begin transaction 命令开始事务。
- 使用 SQL 查询语句执行各种删除、更新或插入操作。
- 如果所有的操作都成功,则执行提交操作,否则回滚所有操作。
Spring 框架在不同的底层事务管理 APIs 的顶部提供了一个抽象层。Spring 的事务支持旨在通过添加事务能力到 POJOs 来提供给 EJB 事务一个选择方案。Spring 支持编程式和声明式事务管理。EJBs 需要一个应用程序服务器,但 Spring 事务管理可以在不需要应用程序服务器的情况下实现。
局部事物和全局事物:
局部事务是特定于一个单一的事务资源,如一个 JDBC 连接,而全局事务可以跨多个事务资源事务,如在一个分布式系统中的事务。
局部事务管理在一个集中的计算环境中是有用的,该计算环境中应用程序组件和资源位于一个单位点,而事务管理只涉及到一个运行在一个单一机器中的本地数据管理器。局部事务更容易实现。
全局事务管理需要在分布式计算环境中,所有的资源都分布在多个系统中。在这种情况下事务管理需要同时在局部和全局范围内进行。分布式或全局事务跨多个系统执行,它的执行需要全局事务管理系统和所有相关系统的局部数据管理人员之间的协调。
Spring支持两种类型的事物管理:
- 编程式事务管理 :这意味着你在编程的帮助下有管理事务。这给了你极大的灵活性,但却很难维护。
- 声明式事务管理 :这意味着你从业务代码中分离事务管理。你仅仅使用注释或 XML 配置来管理事务。
声明式事务管理比编程式事务管理更可取,尽管它不如编程式事务管理灵活,但它允许你通过代码控制事务。但作为一种横切关注点,声明式事务管理可以使用 AOP 方法进行模块化。Spring 支持使用 Spring AOP 框架的声明式事务管理。
Spring事物抽象:
Spring 事务抽象的关键是由 org.springframework.transaction.PlatformTransactionManager 接口定义,如下所示:
1 | public interface PlatformTransactionManager { |
序号 | 方法 & 描述 |
---|---|
1 | TransactionStatus getTransaction(TransactionDefinition definition)根据指定的传播行为,该方法返回当前活动事务或创建一个新的事务。 |
2 | void commit(TransactionStatus status)该方法提交给定的事务和关于它的状态。 |
3 | void rollback(TransactionStatus status)该方法执行一个给定事务的回滚。 |
TransactionDefinition 是在 Spring 中事务支持的核心接口,它的定义如下:
1 | public interface TransactionDefinition { |
序号 | 方法 & 描述 |
---|---|
1 | int getPropagationBehavior()该方法返回传播行为。Spring 提供了与 EJB CMT 类似的所有的事务传播选项。 |
2 | int getIsolationLevel()该方法返回该事务独立于其他事务的工作的程度。 |
3 | String getName()该方法返回该事务的名称。 |
4 | int getTimeout()该方法返回以秒为单位的时间间隔,事务必须在该时间间隔内完成。 |
5 | boolean isReadOnly()该方法返回该事务是否是只读的。 |
下面是隔离级别的可能值:
序号 | 隔离 & 描述 |
---|---|
1 | TransactionDefinition.ISOLATION_DEFAULT这是默认的隔离级别。 |
2 | TransactionDefinition.ISOLATION_READ_COMMITTED表明能够阻止误读;可以发生不可重复读和虚读。 |
3 | TransactionDefinition.ISOLATION_READ_UNCOMMITTED表明可以发生误读、不可重复读和虚读。 |
4 | TransactionDefinition.ISOLATION_REPEATABLE_READ表明能够阻止误读和不可重复读;可以发生虚读。 |
5 | TransactionDefinition.ISOLATION_SERIALIZABLE表明能够阻止误读、不可重复读和虚读。 |
下面是传播类型的可能值:
序号 | 传播 & 描述 |
---|---|
1 | TransactionDefinition.PROPAGATION_MANDATORY支持当前事务;如果不存在当前事务,则抛出一个异常。 |
2 | TransactionDefinition.PROPAGATION_NESTED如果存在当前事务,则在一个嵌套的事务中执行。 |
3 | TransactionDefinition.PROPAGATION_NEVER不支持当前事务;如果存在当前事务,则抛出一个异常。 |
4 | TransactionDefinition.PROPAGATION_NOT_SUPPORTED不支持当前事务;而总是执行非事务性。 |
5 | TransactionDefinition.PROPAGATION_REQUIRED支持当前事务;如果不存在事务,则创建一个新的事务。 |
6 | TransactionDefinition.PROPAGATION_REQUIRES_NEW创建一个新事务,如果存在一个事务,则把当前事务挂起。 |
7 | TransactionDefinition.PROPAGATION_SUPPORTS支持当前事务;如果不存在,则执行非事务性。 |
8 | TransactionDefinition.TIMEOUT_DEFAULT使用默认超时的底层事务系统,或者如果不支持超时则没有。 |
TransactionStatus 接口为事务代码提供了一个简单的方法来控制事务的执行和查询事务状态。
1 | public interface TransactionStatus extends SavepointManager { |
序号 | 方法 & 描述 |
---|---|
1 | boolean hasSavepoint()该方法返回该事务内部是否有一个保存点,也就是说,基于一个保存点已经创建了嵌套事务。 |
2 | boolean isCompleted()该方法返回该事务是否完成,也就是说,它是否已经提交或回滚。 |
3 | boolean isNewTransaction()在当前事务时新的情况下,该方法返回 true。 |
4 | boolean isRollbackOnly()该方法返回该事务是否已标记为 rollback-only。 |
5 | void setRollbackOnly()该方法设置该事务为 rollback-only 标记。 |
Spring编程式事物管理:
编程式事务管理方法允许你在对你的源代码编程的帮助下管理事务。这给了你极大地灵活性,但是它很难维护。
首先得创建两张表:
Student表:
1 | CREATE TABLE Student( |
第二个表是 Marks,用来存储基于年份的学生的标记。这里 SID 是 Student 表的外键。
1 | CREATE TABLE Marks( |
直接使用 PlatformTransactionManager 来实现编程式方法从而实现事务。要开始一个新事务,你需要有一个带有适当的 transaction 属性的 TransactionDefinition 的实例。这个例子中,我们使用默认的 transaction 属性简单的创建了 DefaultTransactionDefinition 的一个实例。
当 TransactionDefinition 创建后,你可以通过调用 getTransaction() 方法来开始你的事务,该方法会返回 TransactionStatus 的一个实例。 TransactionStatus 对象帮助追踪当前的事务状态,并且最终,如果一切运行顺利,你可以使用 PlatformTransactionManager 的 commit() 方法来提交这个事务,否则的话,你可以使用 rollback() 方法来回滚整个操作。
下面是数据访问对象接口文件 StudentDAO.java 的内容:
1 | package transaction; |
StudentMarks.java
1 | package transaction; |
StudentMarksMapper.java
1 | package transaction; |
下面是定义的 DAO 接口 StudentDAO 实现类文件 StudentJDBCTemplate.java:
1 | package transaction; |
MainApp.java
1 | package transaction; |
配置文件:transacation.xml
1 |
|
程序运行结果:
1 | ------创建记录-------- |
Spring声明式事务管理:
声明式事务管理方法允许你在配置的帮助下而不是源代码硬编程来管理事务。这意味着你可以将事务管理从事务代码中隔离出来。你可以只使用注释或基于配置的 XML 来管理事务。 bean 配置会指定事务型方法。下面是与声明式事务相关的步骤:
- 我们使用标签,它创建一个事务处理的建议,同时,我们定义一个匹配所有方法的切入点,我们希望这些方法是事务型的并且会引用事务型的建议。
- 如果在事务型配置中包含了一个方法的名称,那么创建的建议在调用方法之前就会在事务中开始进行。
- 目标方法会在 try / catch 块中执行。
- 如果方法正常结束,AOP 建议会成功的提交事务,否则它执行回滚操作。
StudentDAO.java
1 | package transaction; |
StudentMarks.java
1 | package transaction; |
StudentMarksMapper.java
1 | package transaction; |
StudentJDBCTemplate.java:
1 | package transaction; |
MainApp.java
1 | package transaction; |
配置文件transcation2.xml
1 |
|
运行结果:
1 | ------创建记录-------- |