目录
JdbcTemplate
JdbcTemplate:Spring框架对JDBC进行封装,使用JdbcTemplate方便实现对数据库操作
准备工作
一、引入相关jar包:
- 新建项目
spring5_txdemo1
,将以下jar包复制到lib
文件夹中
- 再将上面这些jar包引入项目:
二、在spring配置文件src/bean1.xml
中配置数据库连接池
<!-- 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="jdbc:mysql:///user_db" />
<property name="username" value="root" />
<property name="password" value="root" />
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
</bean>
当然,你也可以将上面这些配置写在property配置文件中,然后在spring配置文件src/bean1.xml
中通过表达式取值
三、在spring配置文件src/bean1.xml
中配置JdbcTemplate对象,注入DataSource
<!-- 配置JdbcTemplate对象
class:指定JdbcTemplate对象
-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入dataSource
name="dataSource"是固定写法,表示注入dataSource
ref="dataSource"这个dataSource指的是你上面数据库连接池时bean的id
-->
<property name="dataSource" ref="dataSource"></property>
</bean>
四、创建service类,创建dao类及其实现类:
public class UserService {}
public interface UserDao {}
public class UserDaoImpl implements UserDao {}
使用注解实现在service类中注入dao,在dao中注入jdbcTemplate对象。
- 在spring配置文件
src/bean1.xml
中开启注解扫描:<context:component-scan base-package="com.atguigu"></context:component-scan>
- 创建service对象、dao对象,在service类和dao实现类上面添加注解:
@Service
public class UserService {}
@Repository
public class UserDaoImpl implements UserDao {}
- 在service类中注入dao
@Service
public class UserService {
//注入dao
@Autowired
private UserDao userDao;
}
- 在dao中注入jdbcTemplate对象,jdbcTemplate对象是在配置文件中创建的,所以他会根据类型,把配置文件的jdbcTemplate对象注入进来
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
}
操作数据库
添加
一、本文用的数据库t_book
对应内容如下:
二、对应数据库t_book
创建实体类out/production/spring5_demo5/com/atguigu/spring5/entity/Book.class
,代码如下:
public class Book {
private String userId;
private String username;
private String ustatus;
public Book() {}
public String toString() {
return "Book{userId='" + this.userId + '\'' + ", username='" + this.username + '\'' + ", ustatus='" + this.ustatus + '\'' + '}';
}
public void setUserId(String userId) {this.userId = userId;}
public void setUsername(String username) {this.username = username;}
public void setUstatus(String ustatus) {this.ustatus = ustatus;}
public String getUserId() {return this.userId;}
public String getUsername() {return this.username;}
public String getUstatus() {return this.ustatus;}
}
三、编写service和dao
- 新建
out/production/spring5_demo5/com/atguigu/spring5/service/BookService.class
代码如下:
@Service
public class BookService {
@Autowired
private BookDao bookDao;
// 添加的方法,调用dao中的方法实现。
public void addBook(Book book) {
bookDao.add(book);
}
}
- 在dao中进行数据库添加操作,创建
out/production/spring5_demo5/com/atguigu/spring5/dao/BookDao.class
及其实现类out/production/spring5_demo5/com/atguigu/spring5/dao/BookDaoImpl.class
,BookDao
类中代码如下:
public interface BookDao {
// 添加的方法
void add(Book var1);
}
- 在
BookDaoImpl
中调用JdbcTemplate对象里面的update(String sql, Object... args)
方法实现添加操作
(1)有两个参数:
第一个参数:sql语句
第二个参数:可变参数,设置sql语句值
(2)BookDao
的实现类BookDaoImpl
中代码如下:
@Repository
public class BookDaoImpl implements BookDao {
//注入 JdbcTemplate,JdbcTemplate对象我们通过配置文件已经创建了
@Autowired
private JdbcTemplate jdbcTemplate;
//添加的方法
@Override
public void add(Book book) {
//1 创建 sql 语句
// t_book是数据库名称
// values(?,?,?)代表该数据库中有三个字段,每个字段用?表示
String sql = "insert into t_book values(?,?,?)";
//2 调用方法实现
Object[] args = new Object[]{book.getUserId(), book.getUsername(), book.getUstatus()};
int update = this.jdbcTemplate.update(sql, args);
System.out.println(update);
}
}
四、测试
@Test
public void testJdbcTemplate() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService",
BookService.class);
Book book = new Book();
book.setUserId("1");
book.setUsername("java");
book.setUstatus("a");
bookService.addBook(book);
}
修改和删除
在service中新增两个方法updateBook
和deleteBook
:
@Service
public class BookService {
@Autowired
private BookDao bookDao;
public void addBook(Book book) {
this.bookDao.add(book);
}
// 修改的方法
public void updateBook(Book book) {
this.bookDao.updateBook(book);
}
// 删除的方法,根据id删除,所以传入的参数是id
public void deleteBook(String id) {
this.bookDao.delete(id);
}
}
在BookDao中新增两个方法updateBook
和delete
:
public interface BookDao {
void add(Book var1);
void updateBook(Book var1);
void delete(String var1);
}
BookDaoImpl中完成修改、删除操作,新增以下代码:
@Override
public void updateBook(Book book) {
// 根据用户id修改username和ustatus的值
String sql = "update t_book set username=?,ustatus=? where user_id=?";
Object[] args = {book.getUsername(), book.getUstatus(),book.getUserId()};
int update = jdbcTemplate.update(sql, args);
System.out.println(update);
}
@Override
public void delete(String id) {
String sql = "delete from t_book where user_id=?";
int update = jdbcTemplate.update(sql, id);
System.out.println(update);
}
测试修改:
@Test
public void testJdbcTemplate() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService",
BookService.class);
Book book = new Book();
book.setUserId("1");
book.setUsername("javaupup");
book.setUstatus("atguigu");
bookService.addBook(book);
}
测试删除:
@Test
public void testJdbcTemplate() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService",
BookService.class);
bookService。deleteBook("1");
}
查询
查询返回某个值
一、查询表里面有多少条记录,返回是某个值
二、在service中添加以下代码,查询表记录数:public int findCount() {return bookDao.selectCount();}
三、在DAO中创建方法int selectCount();
四、在实现类BookDaoImpl中使用JdbcTemplate的queryForObject(String sql, Class<T> requiredType)
方法实现查询返回某个值,该方法有两个参数:
- 第一个参数:sql语句
- 第二个参数:返回类型的Class
//查询表记录数
@Override
public int selectCount() {
String sql = "select count(*) from t_book";
Integer count = jdbcTemplate.queryForObject(sql, Integer.class);
return count;
}
五、测试:
@Test
public void testJdbcTemplate() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService",
BookService.class);
// 查询返回某个值
int count = bookService.findCount();
System.out.println(count);
}
查询返回对象
一、需求:查询图书详情
二、在service中添加以下代码,查询返回对象,因为是根据id查询,所以将id作为参数传进去:public Book findOne(String id) {return bookDao.findBookInfo(id);}
三、在DAO中创建方法Book findBookInfo(String var1);
四、在实现类BookDaoImpl中使用JdbcTemplate的queryForObject(String sql, RowMapper<T> rowMapper,Object.. args)
方法实现查询返回某个对象,该方法有三个参数:
- 第一个参数:sql语句
- 第二个参数:RowMapper是接口,针对返回不同类型数据,使用这个接口里面实现类完成数据封装,在实际中写
new BeanPropertyRowMapper<返回的对象的名字>(返回的对象的类型的class)
- 第三个参数:sql语句值,也就是sql语句中?的值
//查询返回对象
@Override
public Book findBookInfo(String id) {
String sql = "select * from t_book where user_id=?";
//调用方法
Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>(Book.class), id);
return book;
}
五、测试:
@Test
public void testJdbcTemplate() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService",
BookService.class);
// 查询返回对象
Book book = bookService.findOne("1");
System.out.println(book);
}
JdbcTemplate帮你把查询的数据取到,帮你调Book类中的set方法,把值依次设置进去,然后再通过System.out.println(book);
输出值
查询返回集合
一、需求:查询图书列表分页
二、在service中添加以下代码,查询返回对象,因为是根据id查询,所以将id作为参数传进去:public List<Book> findAll() {return this.bookDao.findAllBook();}
三、在DAO中创建方法List<Book> findAllBook();
四、在实现类BookDaoImpl中使用JdbcTemplate的query(String sql, RowMapper<T> rowMapper,Object.. args)
方法实现查询返回某个对象,该方法有三个参数:
- 第一个参数:sql语句
- 第二个参数:RowMapper是接口,针对返回不同类型数据,使用这个接口里面实现类完成数据封装
- 第三个参数:sql语句值,可以省略不写
//查询返回集合
@Override
public int selectCount() {
String sql = "select count(*) from t_book";
Integer count = (Integer)this.jdbcTemplate.queryForObject(sql, Integer.class);
return count;
}
五、测试:
@Test
public void testJdbcTemplate() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService",
BookService.class);
// 查询返回对象
List<Book> all = bookService.findAll();
System.out.println(all);
}
JdbcTemplate帮你把查询的数据取到,先放到Book对象中,然后将多个Book对象放在List<Book>
集合中返回
批量操作
一、批量操作:操作表里面多条记录
二、使用JdbcTemplate的batchUpdate(String sql, List<Object[]> batchArgs)
实现批量操作,该方法有两个参数:
- 第一个参数:sql语句
- 第二个参数:List集合,添加多条记录数据
批量添加
一、在service中添加以下代码,进行批量添加:public void batchAdd(List<Object[]> batchArgs) {bookDao.batchAddBook(batchArgs);}
二、在DAO中创建方法void batchAddBook(List<Object[]> var1);
三、在实现类BookDaoImpl中使用JdbcTemplate实现批量添加操作
//批量添加
@Override
public void batchAddBook(List<Object[]> batchArgs) {
String sql = "insert into t_book values(?,?,?)";
int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
System.out.println(Arrays.toString(ints));
}
底层逻辑:遍历List<Object[]> batchArgs
集合,给每个对象Object[]
执行"insert into t_book values(?,?,?)"
语句进行添加,
四、测试:
@Test
public void testJdbcTemplate() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService",
BookService.class);
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 = {"3","java","a"};
Object[] o2 = {"4","c++","b"};
Object[] o3 = {"5","MySQL","c"};
batchArgs.add(o1);
batchArgs.add(o2);
batchArgs.add(o3);
//调用批量添加
bookService.batchAdd(batchArgs);
}
批量修改
一、在service中添加以下代码,进行批量添加:public void batchUpdate(List<Object[]> batchArgs) {bookDao.batchUpdateBook(batchArgs);}
二、在DAO中创建方法void batchUpdateBook(List<Object[]> var1);
三、在实现类BookDaoImpl中使用JdbcTemplate实现批量修改操作
@Override
public void batchUpdateBook(List<Object[]> batchArgs) {
String sql = "update t_book set username=?,ustatus=? where user_id=?";
int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
System.out.println(Arrays.toString(ints));
}
四、测试:
@Test
public void testJdbcTemplate() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService",
BookService.class);
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 = {"java0909","a3","3"};
Object[] o2 = {"c++1010","b4","4"};
Object[] o3 = {"MySQL1111","c5","5"};
batchArgs.add(o1);
batchArgs.add(o2);
batchArgs.add(o3);
//调用方法实现批量修改
bookService.batchUpdate(batchArgs);
}
批量删除
一、在service中添加以下代码,进行批量添加:public void batchDelete(List<Object[]> batchArgs) {this.bookDao.batchDeleteBook(batchArgs);}
二、在DAO中创建方法void batchDeleteBook(List<Object[]> var1);
三、在实现类BookDaoImpl中使用JdbcTemplate的batchUpdate(String sql, List<Object[]> batchArgs)
实现删除操作
@Override
public void batchDeleteBook(List<Object[]> batchArgs) {
String sql = "delete from t_book where user_id=?";
int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
System.out.println(Arrays.toString(ints));
}
四、测试:
@Test
public void testJdbcTemplate() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService",
BookService.class);
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 = {"3"};
Object[] o2 = {"4"};
batchArgs.add(o1);
batchArgs.add(o2);
//调用方法实现批量删除
bookService.batchDelete(batchArgs);
}
事务
一、什么事务
- 事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个失败所有操作都失败
- 典型场景:银行转账,如lucy转账100元给mary,lucy少100,mary多100
二、事务四个特性(ACID)
- 原子性:这个过程不可分割,要么都成功,一个失败都失败
- 一致性:操作前和操作后总量不变
- 隔离性:多事务操作时,每个事务不会有影响
- 持久性:事务提交后,表中数据真正发生变化
搭建事务操作环境
一、创建数据库表,添加记录
二、创建service,搭建dao,完成对象创建和注入关系
- service注入dao,在dao注入JdbcTemplate,代码如下:
@Service
public class UserService {
//注入 dao
@Autowired
private UserDao userDao;
}
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
}
- 在JdbcTemplate注入DataSource,配置文件
src/bean1.xml
代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 组件扫描 -->
<context:component-scan base-package="com.atguigu"></context:component-scan>
<!-- 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="url" value="jdbc:mysql:///user_db" />
<property name="username" value="root" />
<property name="password" value="root" />
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
</bean>
<!-- JdbcTemplate对象
class:指定JdbcTemplate对象
-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入dataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
三、在dao创建两个方法:多钱和少钱的方法,在service创建方法(转账的方法)
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
//lucy 转账 100 给 mary
//少钱
@Override
public void reduceMoney() {
String sql = "update t_account set money=money-? where username=?";
jdbcTemplate.update(sql,100,"lucy");
}
//多钱
@Override
public void addMoney() {
String sql = "update t_account set money=money+? where username=?";
jdbcTemplate.update(sql,100,"mary");
}
}
@Service
public class UserService {
//注入 dao
@Autowired
private UserDao userDao;
//转账的方法
public void accountMoney() {
//lucy 少 100
userDao.reduceMoney();
//mary 多 100
userDao.addMoney();
}
}
四、测试
public class TestBook {
@Test
public void testAccount() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.accountMoney();
}
}
五、上面代码,如果正常执行没有问题的,但是如果代码执行过程中出现异常,就会出现问题,可能Lucy少了100,但是Mary没有增加,那么需要使用事务解决。事务操作过程:
Spring事务管理
一、JavaEE中有三层结构:WEB、Service、DAO,将事务添加到Service 层(业务逻辑层)
二、在Spring进行事务管理操作有两种方式:编程式事务管理和声明式事务管理(使用)。不适用编程式事务管理方式是因为他需要通过代码来实现,会在每个需要事务管理的地方都写一些相同的代码,很冗余
三、声明式事务管理
- 基于注解方式(使用)
- 基于xml配置文件方式
四、在Spring进行声明式事务管理,底层使用AOP原理
五、创建对象不是new接口,而是new接口的实现类
六、Spring事务管理API:提供了一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类
注解声明式事务管理
一、在spring配置文件src/bean1.xml
引入名称空间tx
二、在spring配置文件配置事务管理器
<!--创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源
name="dataSource":表示注入dataSource
ref="dataSource":指定注入的dataSource的id,也就是你在数据库连接池中设置的bean标签的id
-->
<property name="dataSource" ref="dataSource"></property>
</bean>
三、开启事务注解
<!--开启事务注解 transaction-manager="事务管理器,即创建事务管理器的bean的id"-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
四、在service类上面(或者service类里面方法上面)添加事务注解@Transactional
- 这个注解添加到类上面,也可以添加方法上面
- 如果把这个注解添加类上面,这个类里面所有的方法都添加事务,本文加在了类上面:
@Service
@Transactional
public class UserService {}
- 如果把这个注解添加方法上面,为这个方法添加事务
五、运行测试代码后显示:
声明式事务管理参数配置
在service类上面添加注解@Transactional
,在这个注解里面可以配置事务相关参数:
一、propagation:事务传播行为。事务传播行为指的是多事务方法直接进行调用,这个过程中事务是如何进行管理的,即一个事务的方法被另一个事务的方法调用时,这个事务该如何进行处理?
- REQUIRED:事务A中有方法2,事务B中有方法1。如果单独执行事务B中的方法1,这个方法肯定会开启一个事务,即开启事务B。如果方法A中的方法2调用事务B中的方法1,那么首先方法2会开启事务A,方法2调用方法1时,方法1会加入到当前事务A中
- REQUIRED_NEW:事务A中有方法A,事务B中有方法B。如果方法A中的方法A调用事务B中的方法B,那么首先方法A会开启事务A,方法A调用方法B时,方法B会开启事务B,将事务A称为外层事务,事务B称为内层事务,内外层事务互不相干,加入外层事务调完方法B后出现异常,方法B依然能提交,不会回滚
- SUPPORTS:事务A中有方法A且事务A是REQUIRED方式,事务B中有方法B且事务B是SUPPORTS方式。如果单独执行事务B中的方法B,那方法B可以在非事务状态下进行。如果方法A中的方法A调用事务B中的方法B,那么首先方法A会开启事务A,方法A调用方法B时,方法B会加入到当前事务A中
二、isolation:事务隔离级别
- 隔离级别是为了解决事务中的隔离性而出现的概念
- 事务隔离性:多事务操作之间不会产生影响。不考虑隔离性产生很多问题,如三个读问题:脏读、不可重复读、虚(幻)读
(1)脏读:一个未提交事务读取到另一个未提交事务的数据
数据库中有一条记录:Lucy有5000元。现在东方不败和岳不群都想操作这条记录,不管谁操作这条记录都会开启一个事务,东方不败开启的事务为事务A,岳不群开启的事务为事务B,他将Lucy的钱改成了60000,但还没有提交事务,在脏读情况下,事务A读取这条记录时,获得的是事务B修改后的数据60000,然后事务B回滚了,数据又变回了5000,那么事务A读到的数据就是不准的。脏读指的是两个事务都没有提交,事务B改变了数据,事务A可以读到改变后的数,但是事务可以回滚,事务B回滚了,事务A读到的数据就不对了
(2)不可重复读:一个未提交事务读取到另一提交事务修改数据
数据库中有一条记录:Lucy有5000元。现在东方不败和岳不群都想操作这条记录,不管谁操作这条记录都会开启一个事务,东方不败开启的事务为事务A,岳不群开启的事务为事务B,假如两个人都开启了事务并且都得到了这条记录,事务B将数据改成了900,然后马上提交了事务,事务A没有提交但可以读到900。假如事务A在统计工资,那么他每次得到的数据都不一样
(3)虚读:一个未提交事务读取到另一提交事务添加数据 - 通过设置事务隔离级别来解决以上三个读的问题:通过给service上的注解
@Transactional
添加参数来设置隔离级别:@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
。隔离级别isolation
可选参数如下:
MySQL中默认的隔离级别:REPEATABLE READ
三、timeout:超时时间
- 事务需要在一定时间timeout内进行提交,如果不提交进行回滚
- 默认值是-1 ,设置时间以秒单位进行计算
四、readOnly:是否只读 - 读:查询操作,写:添加修改删除操作
- readOnly 默认值 false,表示可以查询,可以添加修改删除操作
- 设置 readOnly 值是 true,设置成 true 之后,只能查询
五、rollbackFor:回滚。设置出现哪些异常进行事务回滚
六、noRollbackFor:不回滚。设置出现哪些异常不进行事务回滚
XML声明式事务管理
在spring配置文件src/bean2.xml
中进行配置:
- 配置事务管理器
- 配置通知
- 配置切入点和切面
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 组件扫描 -->
<context:component-scan base-package="com.atguigu"></context:component-scan>
<!-- 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="url" value="jdbc:mysql:///user_db" />
<property name="username" value="root" />
<property name="password" value="root" />
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
</bean>
<!-- JdbcTemplate对象 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入dataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--1 创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--2 配置通知-->
<tx:advice id="txadvice">
<!--配置事务参数-->
<tx:attributes>
<!--指定哪种规则的方法上面添加事务
我现在想在service的accountMoney方法上添加事务,所以name属性值为accountMoney,
name属性值也可以写作account*,表示方法名以account开头的都加上事务-->
<tx:method name="accountMoney" propagation="REQUIRED"/>
<!--<tx:method name="account*"/>-->
</tx:attributes>
</tx:advice>
<!--3 配置切入点和切面-->
<aop:config>
<!--配置切入点-->
<aop:pointcut id="pt" expression="execution(* com.atguigu.spring5.service.UserService.*(..))"/>
<!--配置切面
advice-ref:指定通知
pointcut-ref:指定切入点
下面这行代码的意思是将事务的通知设置到pt方法上
-->
<aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
</aop:config>
</beans>
完全注解声明式事务管理
1、创建配置类src/com/atguigu/spring5/config/TxConfig.java
,使用配置类替代xml配置文件
@Configuration //表明这是个配置类
@ComponentScan(basePackages = "com.atguigu") //开启组件扫描
@EnableTransactionManagement //开启事务
public class TxConfig {
//创建数据库连接池。配置文件中使用bean标签实现,我们这使用@Bean创建
@Bean
public DruidDataSource getDruidDataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///user_db");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
//创建JdbcTemplate对象 上面的getDruidDataSource()一执行,在IOC容器中就有了一个dataSource对象
// getJdbcTemplate(DataSource dataSource)把ataSource dataSource作为参数传进来
// 表示根据dataSource的类型在IOC容器中找到对象,把这个对象注入
@Bean
public JdbcTemplate getJdbcTemplate(DataSource dataSource) {
//到 ioc 容器中根据类型找到 dataSource
JdbcTemplate jdbcTemplate = new JdbcTemplate();
//注入 dataSource
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
//创建事务管理器
@Bean
public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
}