Spring中对持久层也进行了封装,SpringJDBC提供了数据持久层的功能,SpringJDBC中主要包括了JdbcTemplate类(提供数据访问功能)与事务管理功能,其中JdbcTemplate目前已经逐步被mybatis代替了,SpringJDBC中最常使用的是事务管理功能
SpringJDBC
Spring中提供了数据访问层的功能,该部分的功能主要包括Spring JdbcTemplate与Spring事物管理
Spring JdbcTemplate
Spring JdbcTemplate是早期比较流行的数据访问层的框架,在现在的企业开发中使用的较少
开发步骤
1. 导入Spring JdbcTemplate 的 jar依赖
<!-- spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<!-- 阿里数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
2.如果有属性文件的话,导入属性文件<context:property-placeholder location="config.properties"/>
3.注入数据源类的对象到Ioc容器中
<bean id="dataSource"class="com.alibaba.druid.pool.DruidDataSource">
<propertyname="driverClassName" value="${driverClassName}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${uname}"></property>
<property name="password" value="${pwd}"></property>
<property name="initialSize" value="10"></property>
<property name="minIdle" value="5"></property>
<property name="maxActive" value="20"></property>
</bean>
注意在配置xml文件是建议单独写一个xml配置文件然后再主配置文件中导入该文件,例如将上述配置写入db.xml文件中然后在主配置文件中导入
<import resource="classpath:db.xml"></import>
3.在Dao层的对象中依赖注入 JdbcTemplate类的对象,可以使用注解的方式注入
4.在dao层中写入JdbcTemplate代码
public class AdminDao {
@Autowired
JdbcTemplate jdbcTemplate;
//使用事物注解
@Transactional
public void saveAdmin(Admin admin){
//新增操作
jdbcTemplate.update("insert into admin(account,password) value(?,?)","aaa","111");
//删除操作
//jdbcTemplate.update("delete from admin where id=?","3");
//查询单条记录
/*Admin admin1 = jdbcTemplate.queryForObject("select * from admin where id = ?",
new RowMapper<Admin>() {
@Override
public Admin mapRow(ResultSet resultSet, int i) throws SQLException {
Admin admin2 = new Admin();
admin2.setId(resultSet.getInt("id"));
admin2.setAccount(resultSet.getString("account"));
return admin2;
}
},"1");
System.out.println(admin1);*/
//查询多条记录
/*List<Admin> list = jdbcTemplate.query("select * from admin",
new RowMapper<Admin>() {
@Override
public Admin mapRow(ResultSet resultSet, int i) throws SQLException {
Admin admin1 = new Admin();
admin1.setId(resultSet.getInt("id"));
admin1.setAccount(resultSet.getString("account"));
return admin1;
}
});
System.out.println(list);*/
}
}
事务管理
什么是事务?
事务是数据库为了保障数据一致性而提供的功能
事务是由多个数据库操作组成的一个执行单元,例如一个据插入操作与一个数据删除操作就可以组成一个执行单元
什么是事务管理?
事物管理就是对执行单元的管理,由于在业务处理中每个执行单元都有可能出现错误或者异常,在一个执行单元中间出现了错误或者异常,那么在异常之前的操作的数据并不可靠,需要进行回退
经典案例:转账
现在要将A账户中的1000元转入B账户中,那么该事务的执行流程如下
开启事务
A账户减少1000元
B账户增加1000元
提交事务
如果上述步骤中有一步出现异常则整个操作需要回退
关系型数据库事物的基本特征:
1.原子性,一个事务中的多条sql要么不执行,要么全部一起执行
2.隔离性
3.持久性
4.一致性
Spring中的事务管理
Spring中的事物管理主要是帮助我们进行事务的提交,这一步是通过AOP的思想实现的
Spring中的事务管理有两种分别是编程式事务管理与声明式事务管理
编程式事务管理
现在在项目中很少使用这种方式了,首先需要注入事务管理对象TransactionTemplate ,然后在我们代码中需要提交事务或回滚事务时自己写代码实现
声明式事务管理
声明式事务管理是方法基本的,其实现的思想是通过AOP的方式对方法的前后进行拦截
Spring的声明式事务管理实现有两种
1.xml配置实现
2.注解方式实现
Spring 针对不同的 dao 框架,提供了不同的实现类,Jdbc,mybatis 事物管理实现类是DataSourceTransactionManager.
注解方式实现:
1.配置事物管理器类,注意这一步需要注入数据源
<!-- 配置 spring 事务管理类, 并注入数据源 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
2.开启事务管理的注解
<!-- 开启注解事务管理 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
3.使用@Transactional注解在方法的字段上声明
@Transactional
public void saveAdmin(Admin admin){
jdbcTemplate.update("insert into admin(account,password) value(?,?)","aaa","111");
System.out.println(10/0);
jdbcTemplate.update("insert into admin(account,password) value(?,?)","bbb","111");
}
4.@Transactional注解可以对类进行修饰
如果对类进行修饰,则类中的所有方法都会被事务控制,
此时如果类中的方法调用了dao层的方法且dao层的方法中被@Transactional注解修饰则会报出异常
@Transactional注解一般对service层中的类与方法进行修饰,这是由于在后面mybatis框架继承到spring框架后,dao层都是单接口开发,所以要进行多条sql的事物控制一般对service层的类或方法进行修饰
@Transactional注解失效的六种情况
1.@Transactional修饰非public方法时,该事物失效,注解的底层权限只支持public权限
2.事物的内的异常被catch关键字捕获时
3.事物内出现编译期异常时事物失效
此时可以通过修改@Transactional注解的rollbackFor属性值, 将此属性修改为Exception.class即可
4.事物传播行为设置错误
5.数据库引擎不支持事物
常见的数据库引擎有myisam与innodb,前者不支持事物,后者支持事物
6.在同一个类中一个非事物控制的方法调用了另一个有事务控制的方法会导致事物失效
事物传播行为
什么是事物传播行为?
首先,事物传播行为是是spring框架提供的功能,与数据库本身无关
事物传播行为是指一个被事务控制的方法去调用另外一个被控制的方法
注意,在java中事物传播行为必须发生在不同的类中
为什么会有事物传播行为?
如果一个被事务控制的方法去调用另一个被事务控制的方法,那么此时是执行该方法的事务还是执行被调用方法的事务呢?spring中为了应对不同的情况而设置了不同的事物传播行为
七种事务传播行为
传播行为通过@Transactional标签中的propagation属性设置
1.PROPAGATION_REQUIRED
如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。
2.PROPAGATION_SUPPORTS
支持当前事务,如果当前没有事务,就以非事务方式执行。
3.PROPAGATION_MANDATORY
使用当前的事务,如果当前没有事务,就抛出异常。
4.PROPAGATION_REQUIRES_NEW
新建事务,如果当前存在事务,把当前事务挂起。
5.PROPAGATION_NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6.PROPAGATION_NEVER
以非事务方式执行,如果当前存在事务,则抛出异常。
7.PROPAGATION_NESTED
如果当前存在事务,则在嵌套事务内执行。如果当前没有事务, 则执行与 PROPAGATION_REQUIRED 类似的操作。