摘要:概念的异常体系建立在运行期异常的基础上,封装了源异常数据访问流程准备资源启动事务在事务中执行具体数据访问操作提交回滚事务关闭资源,处理异常将相同的数据访问流程固化到模板类中,把数据访问中固定和变化的部分分开,同时保证模板类是线程安全的。
1. 概念
Spring的DAO异常体系建立在运行期异常的基础上,封装了源异常
JDBC数据访问流程:
准备资源
启动事务
在事务中执行具体数据访问操作
提交/回滚事务
关闭资源,处理异常
Spring将相同的数据访问流程固化到模板类中,把数据访问中固定和变化的部分分开,同时保证模板类是线程安全的。Spring为不同的持久化技术都提供了简化操作的模板和回调
数据库事务:原子性,一致性,隔离性和持久性(ACID)
5类数据库并发问题:
脏读:A事务读取到B事务尚未提交的数据
不可重复读:A事务中读取到B事务已经提交的==更新==数据,即连续两次读取结果不同
幻读:A事务读取B事务的==新增==数据
第一类更新丢失:A事务撤销时覆盖了B事务的提交
第二类更新丢失:A事务覆盖B事务已经提交的数据
JDBC默认情况下自动提交,即每条执行的SQL语句都对应一个事务,AutoCommit = TRUE
Spring基于ThreadLocal解决有状态的Connetion的并发问题,事务同步管理器org.springframework.transaction.support.TransactionSynchronizationManager使用ThreadLocal为不同事务线程提供独立的资源副本
Spring事务管理基于3个接口:TransactionDefinition,TransactionStatus和PlatformTransactionManager
Spring为不同持久化技术提供了从TransactionSynchronizationManager获取对应线程绑定资源的工具类,如DataSourceUtils.getConnection(DataSource dataSource)。模板类在内部通过工具类访问TransactionSynchronizationManager中的线程绑定资源
Spring通过事务传播行为控制当前的事务如何传播到被嵌套调用的目标服务接口方法中
使用
@Transactional注解的属性
事务传播行为:propagation,默认PROPAGATION_REQUIRED,即如果当前没有事务,就新建一个事务;否则加入到当前事务
事务隔离级别:isolation,默认ISOLATION_DEFAULT
读写事务属性:readOnly
超时时间:timeout
回滚设置:rollbackFor,rollbackForClassName,noRollbackFor,noRollbackForClassName
在相同线程中进行相互嵌套调用的事务方法工作于相同的事务中;如果在不同线程中,则工作在独立的事务中
特殊方法:
注解不能被继承,所以业务接口中的@Transactional注解不会被业务实现类继承;方法处的注解会覆盖类定义处的注解
对于基于接口动态代理的AOP事务,由于接口方法都是public的,实现类的实现方法必须是public的,同时不能使用static修饰符。因此,可以通过接口动态代理实施AOP增强、实现Spring事务的方法只能是public或public final的
基于CGLib动态代理实施AOP的时候,由于使用final、static、private的方法不能被子类覆盖,相应的,这些方法不能实施AOP增强,实现事务
不能被Spring进行AOP事务增强的方法不能启动事务,但是外层方法的事务上下文仍然可以传播到这些方法中
2. Spring中使用JDBC编程示例本地mysql建表
</>复制代码
CREATE TABLE `t_user` (
`user_id` varchar(256) NOT NULL,
`user_name` varchar(256) DEFAULT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
springDAO.xml
</>复制代码
User
</>复制代码
package com.data;
public class User {
private String userId;
private String userName;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
BaseDAO
</>复制代码
package com.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
public class BaseDAO {
@Autowired
protected JdbcTemplate jdbcTemplate;
}
UserDAO
</>复制代码
package com.dao;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.data.User;
import com.mapper.UserRowMapper;
@Repository
public class UserDAO extends BaseDAO {
private static final String SQL_GET_USER = "select * from t_user where " + "user_id = ?;";
private static final String SQL_INSERT_USER = "insert into t_user values(?, ?);";
private static final String SQL_CLEAN_USER = "delete from t_user where 1=1;";
@Transactional
public User getUserById(String userId) {
return jdbcTemplate.queryForObject(SQL_GET_USER, new Object[]{userId}, new UserRowMapper());
}
@Transactional
public int insertUser(User user) {
return jdbcTemplate.update(SQL_INSERT_USER, user.getUserId(), user.getUserName());
}
@Transactional
public int cleanUser() {
return jdbcTemplate.update(SQL_CLEAN_USER);
}
}
UserRowMapper
</>复制代码
package com.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
import com.data.User;
public class UserRowMapper implements RowMapper{
public User mapRow(ResultSet rs, int rowNumber) throws SQLException {
User user = new User();
user.setUserId(rs.getString("user_id"));
user.setUserName(rs.getString("user_name"));
return user;
}
}
BaseTestCase
</>复制代码
package com;
import org.junit.Assert;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/springDAO.xml"})
public class BaseTestCase extends Assert {
}
TestUserDAO
</>复制代码
package com.dao;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import com.BaseTestCase;
import com.data.User;
public class TestUserDAO extends BaseTestCase{
@Before
@After
public void clean() {
dao.cleanUser();
}
@Autowired
private UserDAO dao;
@Test
public void getUserById() {
User user = new User();
String id = "id";
String name = "name";
user.setUserId(id);
user.setUserName(name);
assertEquals(dao.insertUser(user), 1);
user = dao.getUserById(id);
assertEquals(user.getUserId(), id);
assertEquals(user.getUserName(), name);
}
}
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/66616.html
摘要:我们会写切面来拦截对这些业务类和类的调用。切面定义何时拦截一个方法以及做什么和在一起成为切面连接点当代码开始执行,并且切点的条件满足时,通知被调用。 前言 这篇文章会帮助你使用Spring Boot Starter AOP实现AOP。我们会使用AspectJ实现四个不同的通知(advice),并且新建一个自定义的注解来追踪方法的执行时间。 你将会了解 什么是交叉分割关注点(cross...
摘要:简单快速了解是前端视图填充数据的工具,是个页面模板,可以像表达式那样操作数据,那样公共代码引用,很多好用的方法。目录结构快速接入深入了解待续。。。 简单快速了解 Beetl 是前端视图填充数据的工具,是个页面模板,可以像 el 表达式那样操作数据,jsp 那样公共代码引用,很多好用的方法。官方模板对比:showImg(https://segmentfault.com/img/bVbfa...
摘要:连接对象执行命令对象执行关闭值得注意的是,对数据库连接池是有很好的支持的。给我们提供了事务的管理器类,事务管理器类又分为两种,因为的事务和的事务是不一样的。 前言 上一篇Spring博文主要讲解了如何使用Spring来实现AOP编程,本博文主要讲解Spring的DAO模块对JDBC的支持,以及Spring对事务的控制... 对于JDBC而言,我们肯定不会陌生,我们在初学的时候肯定写过非...
摘要:这个文件包含对对数据访问进行封装的所有类。为等提供的一致的声明式和编程式事务管理。 SSM 环境搭建 目录创建 pom.xml SSM 逐层配置 一、目录 1.1 src/main/java 目录下的包(以下包要放在项目包下,如:com.imooc.项目名) entity: 存放实体类 web: 存放controller,相当于Struts中的action service: 业务...
摘要:何为简单点来定义就是切面,是一种编程范式。定义一个切面的载体定义一个切点定义一个为,并指定对应的切点一个注册配置类,启动容器,初始化时期获取对象,获取对象时期,并进行打印好了,这样我们整体的代理就已经完成。 问题:Spring AOP代理中的运行时期,是在初始化时期织入还是获取对象时期织入? 织入就是代理的过程,指目标对象进行封装转换成代理,实现了代理,就可以运用各种代理的场景模式。 ...
阅读 2927·2021-07-30 15:30
阅读 623·2019-08-30 15:55
阅读 1689·2019-08-26 17:04
阅读 720·2019-08-26 11:36
阅读 2184·2019-08-26 10:58
阅读 3648·2019-08-23 14:34
阅读 1629·2019-08-22 18:48
阅读 2607·2019-08-21 17:51