Spring 中的 JDBC 事务
Spring 对 JDBC 的支持
JdbcTemplate 简介
•为了使 JDBC 更加易于使用, Spring 在 JDBC API 上定义了一个抽象层, 以此建立一个 JDBC 存取框架.
使用 JdbcTemplate 更新数据库
- <!-- 导入资源文件 -->
- <context:property-placeholder location="classpath:db.properties"/>
- <!-- 配置 C3P0 数据源 -->
- <bean id="dataSource"
- class="com.mchange.v2.c3p0.ComboPooledDataSource">
- <property name="user" value="${jdbc.user}"></property>
- <property name="password" value="${jdbc.password}"></property>
- <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
- <property name="driverClass" value="${jdbc.driverClass}"></property>
- <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>
- <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
- </bean>
- <!-- 配置 Spirng 的 JdbcTemplate -->
- <bean id="jdbcTemplate"
- class="org.springframework.jdbc.core.JdbcTemplate">
- <property name="dataSource" ref="dataSource"></property>
- </bean>
applicationContext.xml
- /**
- * 获取单个列的值, 或做统计查询
- * 使用 queryForObject(String sql, Class<Long> requiredType)
- */
- @Test
- public void testQueryForObject2(){
- String sql = "SELECT count(id) FROM employees";
- long count = jdbcTemplate.queryForObject(sql, Long.class);
- System.out.println(count);
- }
- /**
- * 查到实体类的集合
- * 注意调用的不是 queryForList 方法
- */
- @Test
- public void testQueryForList(){
- String sql = "SELECT id, last_name lastName, email FROM employees WHERE id > ?";
- RowMapper<Employee> rowMapper = new BeanPropertyRowMapper<>(Employee.class);
- List<Employee> employees = jdbcTemplate.query(sql, rowMapper,5);
- System.out.println(employees);
- }
- /**
- * 从数据库中获取一条记录, 实际得到对应的一个对象
- * 注意不是调用 queryForObject(String sql, Class<Employee> requiredType, Object... args) 方法!
- * 而需要调用 queryForObject(String sql, RowMapper<Employee> rowMapper, Object... args)
- * 1. 其中的 RowMapper 指定如何去映射结果集的行, 常用的实现类为 BeanPropertyRowMapper
- * 2. 使用 SQL 中列的别名完成列名和类的属性名的映射. 例如 last_name lastName
- * 3. 不支持级联属性. JdbcTemplate 到底是一个 JDBC 的小工具, 而不是 ORM 框架
- */
- @Test
- public void testQueryForObject(){
- String sql = "SELECT id, last_name lastName, email, dept_id as \"department.id\" FROM employees WHERE id = ?";
- RowMapper<Employee> rowMapper = new BeanPropertyRowMapper<>(Employee.class);
- Employee employee = jdbcTemplate.queryForObject(sql, rowMapper, 1);
- System.out.println(employee);
- }
- /**
- * 执行批量更新: 批量的 INSERT, UPDATE, DELETE
- * 最后一个参数是 Object[] 的 List 类型: 因为修改一条记录需要一个 Object 的数组, 那么多条不就需要多个 Object 的数组吗
- */
- @Test
- public void testBatchUpdate(){
- String sql = "INSERT INTO employees(last_name, email, dept_id) VALUES(?,?,?)";
- List<Object[]> batchArgs = new ArrayList<>();
- batchArgs.add(new Object[]{"AA", "aa@atguigu.com", 1});
- batchArgs.add(new Object[]{"BB", "bb@atguigu.com", 2});
- batchArgs.add(new Object[]{"CC", "cc@atguigu.com", 3});
- batchArgs.add(new Object[]{"DD", "dd@atguigu.com", 3});
- batchArgs.add(new Object[]{"EE", "ee@atguigu.com", 2});
- jdbcTemplate.batchUpdate(sql, batchArgs);
- }
- /**
- * 执行 INSERT, UPDATE, DELETE
- */
- @Test
- public void testUpdate(){
- String sql = "UPDATE employees SET last_name = ? WHERE id = ?";
- jdbcTemplate.update(sql, "Jack", 5);
- }
JDBCTest
简化 JDBC 模板查询
- @Repository
- public class EmployeeDao {
- @Autowired
- private JdbcTemplate jdbcTemplate;
- public Employee get(Integer id){
- String sql = "SELECT id, last_name lastName, email FROM employees WHERE id = ?";
- RowMapper<Employee> rowMapper = new BeanPropertyRowMapper<>(Employee.class);
- Employee employee = jdbcTemplate.queryForObject(sql, rowMapper, id);
- return employee;
- }
- }
EmployeeDao
- @Repository
- public class DepartmentDao extends JdbcDaoSupport{
- @Autowired
- public void setDataSource2(DataSource dataSource){
- setDataSource(dataSource);
- }
- public Department get(Integer id){
- String sql = "SELECT id, dept_name name FROM departments WHERE id = ?";
- RowMapper<Department> rowMapper = new BeanPropertyRowMapper<>(Department.class);
- return getJdbcTemplate().queryForObject(sql, rowMapper, id);
- }
- }
DepartmentDao
在 JDBC 模板中使用具名参数
- <!-- 配置 NamedParameterJdbcTemplate, 该对象可以使用具名参数, 其没有无参数的构造器, 所以必须为其构造器指定参数 -->
- <bean id="namedParameterJdbcTemplate"
- class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
- <constructor-arg ref="dataSource"></constructor-arg>
- </bean>
- /**
- * 使用具名参数时, 可以使用 update(String sql, SqlParameterSource paramSource) 方法进行更新操作
- * 1. SQL 语句中的参数名和类的属性一致!
- * 2. 使用 SqlParameterSource 的 BeanPropertySqlParameterSource 实现类作为参数.
- */
- @Test
- public void testNamedParameterJdbcTemplate2(){
- String sql = "INSERT INTO employees(last_name, email, dept_id) "
- + "VALUES(:lastName,:email,:dpetId)";
- Employee employee = new Employee();
- employee.setLastName("XYZ");
- employee.setEmail("xyz@sina.com");
- employee.setDpetId(3);
- SqlParameterSource paramSource = new BeanPropertySqlParameterSource(employee);
- namedParameterJdbcTemplate.update(sql, paramSource);
- }
- /**
- * 可以为参数起名字.
- * 1. 好处: 若有多个参数, 则不用再去对应位置, 直接对应参数名, 便于维护
- * 2. 缺点: 较为麻烦.
- */
- @Test
- public void testNamedParameterJdbcTemplate(){
- String sql = "INSERT INTO employees(last_name, email, dept_id) VALUES(:ln,:email,:deptid)";
- Map<String, Object> paramMap = new HashMap<>();
- paramMap.put("ln", "FF");
- paramMap.put("email", "ff@atguigu.com");
- paramMap.put("deptid", 2);
- namedParameterJdbcTemplate.update(sql, paramMap);
- }
TestNamedParameterJdbctemplate
Spring 中的事务管理
用事务通知声明式地管理事务
- <!-- 配置 bean -->
- <bean id="bookShopDao" class="com.atguigu.spring.tx.xml.BookShopDaoImpl">
- <property name="jdbcTemplate" ref="jdbcTemplate"></property>
- </bean>
- <bean id="bookShopService" class="com.atguigu.spring.tx.xml.service.impl.BookShopServiceImpl">
- <property name="bookShopDao" ref="bookShopDao"></property>
- </bean>
- <bean id="cashier" class="com.atguigu.spring.tx.xml.service.impl.CashierImpl">
- <property name="bookShopService" ref="bookShopService"></property>
- </bean>
- <!-- 1. 配置事务管理器 -->
- <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <!-- 2. 配置事务属性 -->
- <tx:advice id="txAdvice" transaction-manager="transactionManager">
- <tx:attributes>
- <!-- 根据方法名指定事务的属性 -->
- <tx:method name="purchase" propagation="REQUIRES_NEW"/>
- <tx:method name="get*" read-only="true"/>
- <tx:method name="find*" read-only="true"/>
- <tx:method name="*"/>
- </tx:attributes>
- </tx:advice>
- <!-- 3. 配置事务切入点, 以及把事务切入点和事务属性关联起来 -->
- <aop:config>
- <aop:pointcut expression="execution(* com.atguigu.spring.tx.xml.service.*.*(..))"
- id="txPointCut"/>
- <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
- </aop:config>
config
用 @Transactional 注解声明式地管理事务
•可以在方法或者类级别上添加 @Transactional 注解. 当把这个注解应用到类上时, 这个类中的所有公共方法都会被定义成支持事务处理的.
•如果事务处理器的名称是 transactionManager, 就可以在<tx:annotation-driven> 元素中省略 transaction-manager 属性. 这个元素会自动检测该名称的事务处理器.
- <!-- 配置事务管理器 -->
- <bean id="transactionManager"
- class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <!-- 启用事务注解 -->
- <tx:annotation-driven transaction-manager="transactionManager"/>
- //添加事务注解
- //1.使用 propagation 指定事务的传播行为, 即当前的事务方法被另外一个事务方法调用时
- //如何使用事务, 默认取值为 REQUIRED, 即使用调用方法的事务
- //REQUIRES_NEW: 事务自己的事务, 调用的事务方法的事务被挂起.
- //2.使用 isolation 指定事务的隔离级别, 最常用的取值为 READ_COMMITTED
- //3.默认情况下 Spring 的声明式事务对所有的运行时异常进行回滚. 也可以通过对应的
- //属性进行设置. 通常情况下去默认值即可.
- //4.使用 readOnly 指定事务是否为只读. 表示这个事务只读取数据但不更新数据,
- //这样可以帮助数据库引擎优化事务. 若真的事一个只读取数据库值的方法, 应设置 readOnly=true
- //5.使用 timeout 指定强制回滚之前事务可以占用的时间.
- @Transactional(propagation=Propagation.REQUIRES_NEW,
- isolation=Isolation.READ_COMMITTED,
- readOnly=false,
- timeout=3)
- @Override
- public void purchase(String username, String isbn) {
- //1. 获取书的单价
- int price = bookShopDao.findBookPriceByIsbn(isbn);
- //2. 更新数的库存
- bookShopDao.updateBookStock(isbn);
- //3. 更新用户余额
- bookShopDao.updateUserAccount(username, price);
- }
- }
事务传播属性
•事务的传播行为可以由传播属性指定. Spring 定义了 7 种类传播行为.第一和第二种最常用.
Spring 中的 JDBC 事务的更多相关文章
- Spring中的Jdbc事务管理
Spring提供了对事务的声明式事务管理,只需要在配置文件中做一些配置,即可把操作纳入到事务管理当中,解除了和代码的耦合. Spring声明式事务管理,核心实现就是基于Aop. Spring声明式事务 ...
- 【转】在Spring中基于JDBC进行数据访问时怎么控制超时
http://www.myexception.cn/database/1651797.html 在Spring中基于JDBC进行数据访问时如何控制超时 超时分类 超时根据作用域可做如下层级划分: Tr ...
- spring框架总结(04)----介绍的是Spring中的JDBC模板
1.1 Jdbc模板概述 它是spring框架中提供的一个对象,是对原始Jdbc API对象的简单封装.spring框架为我们提供了很多的操作模板类,入下图所示: 我们今天的主角在spring-jd ...
- Spring中使用JDBC
Spring中的数据库异常体系 使用JDBC(不使用Spring)的时候,我们需要强制捕获SQLException,否则无法使用JDBC处理任何事情.SQLException表示尝试访问数据库的时候出 ...
- Spring框架学习(10)Spring中如何使用事务?
内容源自:Spring中如何使用事务? 一.为什么要使用事务? 如果我们一个业务逻辑只执行一次sql,是不需要使用事务的.但如果要执行多条sql语句才能完成一个业务逻辑的话,这个时候就要使用事务了. ...
- spring中注解式事务不生效的问题
常用的解决方法可以百度,我针对我的问题描述一下 Mysql中InnoDB引擎才支持事务, MyISAM不支持事务. 当你尝试了各种方法解决spring中注解式事务不生效时, 一定要查看一下数据库中表的 ...
- Spring框架学习(3)spring中使用jdbc
内容源自:spring中使用jdbc spring dao层中对jdbc进行了封装,使用模板模式的设计模式,通过ioc被动注入的方式将jdbcTemplate这个模板类注入到数据对象中,进行数据库操作 ...
- 在Spring中配置jdbc为什么不能用${username}问题
楼主在spring中配置jdbc时,引用的是dbcp.jar包,在dataSource.properties配置文件中,有mysql用户名,楼主自然的选择了使用username,密码是root, 然后 ...
- 事务特性,事务的隔离级别以及spring中定义的事务传播行为
.katex { display: block; text-align: center; white-space: nowrap; } .katex-display > .katex > ...
随机推荐
- -XX:PermSize -XX:MaxPermSize 永久区参数设置
-XX:PermSize -XX:MaxPermSize –设置永久区的初始空间和最大空间 -XX:PermSize 设置持久代(perm gen)初始值,物理内存的1/64 -XX:MaxPe ...
- 助手系列之连接mysql数据库
import MySQLdbdef main(): try: conn=MySQLdb.connect(host='127.0.0.1',user='root',passwd='pass',db='a ...
- enbale blakboxing
chrome://flags/#enable-devtools-experiments
- android实现通过浏览器点击链接打开本地应用(APP)并拿到浏览器传递的数据
为了实现这个功能可折腾了我好久,先上一份代码,经楼主验证是绝对可以用的而且也比较清晰的代码!(ps:还是先剧透下吧,第三方大部分浏览器无法成功.) 点击浏览器中的URL链接,启动特定的App. 首先做 ...
- PHPCMS V9 框架代码分析(入口程序)
PHPCMS是采用MVC设计模式开发,基于模块和操作的方式进行访问,采用单一入口模式进行项目部署和访问,无论访问任何一个模块或者功能,只有一个统一的入口. 入口程序是在前期处理用户请求的引导程序.它是 ...
- 生产者-消费者问题【Java实现】
生产者-消费者问题是经典的并发问题, 非常适合并发入门的编程练习. 生产者-消费者问题是指, 有若干个生产者和若干个消费者并发地读写一个或多个共享存储空间:生产者创建对象并放入到共享存储空间,消费 ...
- xcode8集成百度地图(framwork包) archive是bitcode问题
(1)问题描述:真机和模拟器测试都能编译安装,但是需要打包archive的时候 总是编译出错,眼看就要上线了,还出现这问题,纠结啊.... 打印出来的错误: ld: bitcode bundle co ...
- web前段 弹出小例子
<html> <head> <meta charset="utf-8"> <meta name="viewport" ...
- php黑魔法之解析问题
code如下: <?php $a=$_GET[a]; $b=is_file($a); var_dump($b); ?> 可以看到1.ph< 返回了true 这样不就可以绕过这个的过滤 ...
- excel如何设置输入数字后单元格自动填充颜色
在使用excel的过程中,有时需要在输入数字时,突出显示这些单元格,突出显示可以用有填充颜色的单元格来表示.为了实现这样的效果,需要借助excel的条件格式. 工具/原料 电脑 Excel 2010 ...