SSM框架之Spring

目录 一、Spring JdbcTemplate 1.1JdbcTemplate概述 1.2JdbcTempl…

目录

一、Spring JdbcTemplate

1.1JdbcTemplate概述

1.2JdbcTemplate开发步骤

1.3Spring产生JdbcTemplate对象

1.4抽取数据库配置文件

1.5JdbcTemplate的常用操作

1.5.1添加数据

1.5.2修改数据

1.5.3删除数据

1.5.4查询数据

二、 Spring的事务控制

2.1编程式事务控制相关对象

2.1.1PlatformTransactionManager

2.1.2TransactionDefinition

2.1.3TransactionStatus

2.2转账业务Demo及存在的问题

2.2基于XML的声明式事务控制

2.3基于注解的声明式事务控制


一、Spring JdbcTemplate

1.1JdbcTemplate概述

JdbcTemplate它是 Spring 框架中提供的一个对象,是对原始繁琐的Jdbc API对象的简单封装

原始Jdbc开发需要先注册驱动,接着获得Connection对象,然后获取Statement对象,执行对应的sql语句,最后获得ResultSet对象。这个过程比较繁琐。

JdbcTemplate对这些操作进行了简单的封装,为我们的数据库开发提供了简便。

Spring框架为我们提供了很多的操作模板类,这些模板将原来复杂的操作进行了简单封装,简化了开发步骤。例如:

  • 操作关系型数据的 JdbcTemplate HibernateTemplate
  • 操作nosql数据库的 RedisTemplate
  • 操作消息队列的 JmsTemplate 等等

1.2JdbcTemplate开发步骤

JdbcTemplate的开发步骤如下:

  • 导入 spring-jdbcspring-tx(控制事务的包) 坐标
  • 创建数据库表和实体
  • 创建 JdbcTemplate 对象
  • 执行数据库操作

首先我们新建一个spring-jdbc项目,在 pom.xml 中导入jar包坐标,除了这两个还要导入mysql、c3p0、druid、junit、spring-context、spring-test这些包,

然后我们在数据库中创建数据表,并给表对象创建对应的实体类。表这里我们还是用mydb1数据库的user表,

给该表传概念对应的实体类User,

然后我们创建JdbcTemplate对象执行数据库操作,

1.3Spring产生JdbcTemplate对象

我们可以将JdbcTemplate的创建权交给Spring,将数据源DataSource的创建权也交给Spring,

在Spring容器内部将数据源DataSource注入到JdbcTemplate模版对象中,配置如下:

注意我们在test文件夹下进行测试(而不是main),所以要在test文件夹下也创建一个Test resources文件夹根目录(没有的话新建一个目录然后右键修改属性为测试资源的根目录),

然后我们进行测试,

1.4抽取数据库配置文件

我们将上面数据源的配置属性抽取为单独的数据库配置文件jdbc.properties,我们在test resources根目录下创建jdbc配置文件,以键值对的形式存储数据库配置属性,

然后我们在Spring配置文件中加载外部的jdbc配置,

然后就可以连接数据库了。

1.5JdbcTemplate的常用操作

数据库无非就是增删改查,接下来我们看看如何操作。

我们使用Spring集成Junit来测试,将JdbcTemplate对象直接注入到测试类中,不用通过应用上下文对象的getBean方法进行获取。

1.5.1添加数据

1.5.2修改数据

1.5.3删除数据

1.5.4查询数据

我们之前通过getBean的方法获取了JdbcTemplate对象,查询了所有用户的数据,这里我们可以修改一下,通过注入的方法获取JdbcTemplate对象,进行查询,

然后我们看看查询单个用户的数据,

接着是查询聚合属性数据,比如我们查询一下用户表中的用户总数,

二、 Spring的事务控制

Spring 支持两种事务控制的方法,分别为编程式声明式

  • 编程式:使用TransactionTemplate或者直接使用底层的PlatformTransactionManager利用代码的方式实现事务控制
  • 声明式:是建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。利用配置的方式实现事务控制

Spring 声明式事务控制底层就是AOP。

声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。

和编程式事务相比,声明式事务唯一不足地方是,它的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。但是即便有这样的需求,也存在很多变通的方法,比如,可以将需要进行事务管理的代码块独立为方法等等。

首先我们学习一下编程式事务控制的三大相关对象。

2.1编程式事务控制相关对象

2.1.1PlatformTransactionManager

PlatformTransactionManager 接口是 Spring 的事务管理器,它里面提供了我们常用的操作事务的方法。

方法

说明

TransactionStatus getTransaction(TransactionDefination defination)

获取事务的状态信息

void commit(TransactionStatus status)

提交事务

void rollback(TransactionStatus status)

回滚事务

注意:PlatformTransactionManager 是接口类型,不同的 Dao 层技术则有不同的实现类,例如:

Dao 层技术是 jdbc mybatis 时,实现类为:

org.springframework.jdbc.datasource.DataSourceTransactionManager

Dao 层技术是 hibernate 时,实现类为:

org.springframework.orm.hibernate5.HibernateTransactionManager

2.1.2TransactionDefinition

TransactionDefinition 是事务的定义信息对象,里面有如下方法:

方法

说明

int getIsolationLevel()

获得事务的隔离级别

int getPropogationBehavior()

获得事务的传播行为

int getTimeout()

获得超时时间

boolean isReadOnly()

是否只读

1、事务的隔离级别

设置隔离级别,可以解决事务并发产生的问题,如脏读、不可重复读和虚读。

  • ISOLATION_DEFAULT:即数据库的默认隔离级别,不同数据库默认级别不同
  • ISOLATION_READ_UNCOMMITTED:不能解决任何问题
  • ISOLATION_READ_COMMITTED:可以解决脏读问题
  • ISOLATION_REPEATABLE_READ:可以解决脏读、不可重复读问题
  • ISOLATION_SERIALIZABLE:可以解决脏读、不可重复读和虚读问题

2、事务的传播行为

事务传播行为是用来描述某一个事务传播行为修饰的方法被嵌套进另一个方法时事务如何传播。

主要有以下几种事务传播行为:

  • REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选择(默认值)
  • SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)
  • MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常
  • REQUERS_NEW:新建事务,如果当前在事务中,把当前事务挂起。
  • NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
  • NEVER:以非事务方式运行,如果当前存在事务,抛出异常
  • NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行 REQUIRED 类似的操作
  • 超时时间:默认值是-1,没有超时限制。如果有,以秒为单位进行设置
  • 是否只读:建议查询时设置为只读

2.1.3TransactionStatus

TransactionStatus 接口提供的是事务具体的运行状态,方法介绍如下:

方法

说明

boolean hasSavepoint()

是否存储回滚点

boolean isCompleted()

事务是否完成

boolean isNewTransaction()

是否是新事务

boolean isRollbackOnly()

事务是否回滚

2.2转账业务Demo及存在的问题

我们先实现一个转账业务的Demo,实现用户A给用户B转账的功能,并且后台数据库的数据也会发生相应改变。

第一步还是在pom.xml中带入jar包坐标(包括spring-context、AspectJ、spring-test、spring-jdbc、spring-tx、mysql、c3p0、druid、junit这些包)

第二步我们在数据库中建好数据表Account和对应的数据,

第三步我们创建对应的实体类对象Account,完成set和get方法,

第四步我们创建Dao层,建立接口和对应的实现函数,这里我们创建对应的JdbcTemplate对象,使用注入的方法进行赋值,

第五步我们创建Service层,定义接口并实现转账的基本方法,同样的我们通过注入的方式获取到Dao层的对象。

第六步我们创建一个假的web层(Controller包),去调用service层的方法,(这里我们同样可以创建service层变量,利用注入的方式进行赋值)

第七步我们对xml文件进行配置,包括上面Bean对象的创建,jdbc配置文件的读取,数据源对象的配置,JdbcTemplate对象的配置。

第八步我们利用Controller包里的代码进行测试,实施转账业务后数据库表数据如下:


这个转账业务有一个很致命的问题,我们的转账操作是先对A账户的金额进行减少,然后增加B账户的金额,如果这个间隔中发生了一个错误导致程序异常,那么就会产生A转账了,但是B却没有收到的结果。例如我们加入一个除数为0的异常:

运行之后发现有异常,查看数据库发现a的钱没了,但没进b的口袋里。。。。。

为了保证这个情况不会发生,我们需要进行事务控制,将转账业务定为一个事务,保证其原子性。

即转账业务中的转出和转入操作要么全部执行,要么都不执行,在某个操作失败后,要回滚到事务执行之前的状态。

事务的控制又分为编程式(写代码实现)和声明式(写配置实现)两种。

编程式事务控制利用代码实现,先开启事务,如果发生异常被捕捉后进行事务的回滚操作,如果没有异常则进行事务的提交。

如果我们需要控制的事务非常多,那么就必须要在每一个需要控制的地方都写上这段代码,冗余度较高。结合之前学习AOP的思路,我们可以将事务控制作为一种通知(增强的方法),将需要事务控制的方法作为切点(被增强的方法),利用Spring的AOP来织入进行动态代理,这样就可以利用配置的形式来进行事务控制,即声明式事务控制。

声明式事务管理也有两种常用的方式,一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional 注解。显然基于注解的方式更简单易用,更清爽。接下来我们将分别介绍声明式事务控制的xml实现和注解实现两种方法。

2.2基于XML的声明式事务控制

既然是配置的方式进行事务控制,那我们就要操作配置文件applicationContext.xml,

其中,<tx:method> 代表切点方法的事务参数的配置,例如:

有以下几种属性可以配置:

  • name:切点方法名称
  • isolation:事务的隔离级别
  • propogation:事务的传播行为
  • timeout:超时时间
  • read-only:是否只读

配置好了之后我们就直接开始测试,还是在转账业务中间加入一个人为的除数为0的异常,可以看到还是依然报错,但是数据库中没有出现少钱的情况,

2.3基于注解的声明式事务控制

基于注解的方式就更简单了,直接将XML中的功能以注解的方式来表达。

我们首先将Bean对象的创建用注解的方式实现,第一个是Dao层和Service层的对象,

接着是DataSource和JdbcTemplate对象,我们新建一个SpringConfiguration类作为Spring的核心配置类,然后引入DataSourceConfiguration数据源配置类,

到此我们的转账业务就可以进行了,但是还没有进行事务控制。我们加上事务控制的注解,

首先我们创建一个事务控制配置类TxConfiguration,在事务控制配置类总创建TransactionManager对象,并且设置数据源对象,最后在核心配置类中导入事务控制配置类

还有一个很关键的是,我们在要加强的类上面注明当前类需要被事务控制加强,在我们的转账业务Demo中,就是写在transfer方法上,

最后我们测试同样不会出现钱没了的情况。

本文来自网络,不代表软粉网立场,转载请注明出处:https://www.rfff.net/p/8489.html

作者: HUI

发表评论

您的电子邮箱地址不会被公开。

返回顶部