此处 @Spring知识点整合(上) 和 @Spring知识点整合(中)
建议先看了上再看下嗷,大佬请无视此句话
我的环境
idea 2019.1
jdk 1.8
Spring 5
Lombok插件 这里是使用和安装链接(包括idea和eclipse) @简单粗暴节省JavaBean代码插件 Lombok.jar
上2篇是 @ 1 - 11 和 @ 12 - 15
16.Spring中的JDBCTemplate详解
1、spring中的JdbcTemplate
JdbcTemplate的作用:
它就是用于和数据库交互的,实现对表的CRUD操作
如何创建该对象: 代码中写
对象中的常用方法: 代码中写
2、作业:
spring基于AOP的事务控制
3、spring中的事务控制
基于XML的
基于注解的
首先写一个案例:不使用注解的操作
创建一个 maven 项目
添加坐标
4.0.0
cn.icanci
jdbcTemplate
1.0-SNAPSHOT
jar
org.springframework
spring-context
5.2.2.RELEASE
org.springframework
spring-jdbc
5.2.2.RELEASE
org.springframework
spring-tx
5.2.2.RELEASE
mysql
mysql-connector-java
5.1.35
org.projectlombok
lombok
1.18.8
provided
Account.java
package cn.icanci.domain;
import lombok.Data;
/**
* @Author: icanci
* @ProjectName: jdbcTemplate
* @PackageName: cn.icanci.domain
* @Date: Created in 2020/1/10 17:13
* @ClassAction: Account的实体类
*/
@Data
public class Account {
private Integer id;
private String name;
private Float money;
}
JdbcTemplateDemo1 .java
package cn.icanci.jdbcTemplate;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
/**
* @Author: icanci
* @ProjectName: jdbcTemplate
* @PackageName: cn.icanci.jdbcTemplate
* @Date: Created in 2020/1/10 17:20
* @ClassAction: JDBCTemplate的最基本用法
*/
public class JdbcTemplateDemo1 {
public static void main(String[] args) {
//准备数据源 : Spring的内置数据源
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/icanci");
ds.setUsername("root");
ds.setPassword("ok");
//1.创建JdbcTemplate
JdbcTemplate jdbcTemplate = new JdbcTemplate();
//设置数据源
jdbcTemplate.setDataSource(ds);
//2.执行操作
jdbcTemplate.execute("insert into account (name,money) values ('hash',1000)");
}
}
测试结果:
现在使用xml配置的方式
首先配置bean.xml
创建一个类: JdbcTemplateDemo2 .java
package cn.icanci.jdbcTemplate;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
/**
* @Author: icanci
* @ProjectName: jdbcTemplate
* @PackageName: cn.icanci.jdbcTemplate
* @Date: Created in 2020/1/10 17:20
* @ClassAction: JDBCTemplate的最基本用法
*/
public class JdbcTemplateDemo2 {
public static void main(String[] args) {
//1.获取容器
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//2.获取对象
JdbcTemplate jdbcTemplate = ac.getBean("jdbcTemplate",JdbcTemplate.class);
//3.执行操作
jdbcTemplate.execute("insert into account (name,money) values ('hashTable',4000)");
}
}
测试结果:
实现最基本的增删改查
创建Account 的IAccountDao.java接口
package cn.icanci.dao;
import cn.icanci.domain.Account;
/**
* @Author: icanci
* @ProjectName: jdbcTemplate
* @PackageName: cn.icanci.dao
* @Date: Created in 2020/1/10 20:51
* @ClassAction: 账户的持久层接口
*/
public interface IAccountDao {
/**
* 根据id查询账户
* @param id 需要查询的id
* @return 返回查询出的的Account对象
*/
Account findAccountById(Integer id);
/**
* 根据姓名查询用户
* @param name 需要查询的用户
* @return 返回查询的的Account对象
*/
Account findAccountByName(String name);
/**
* 更新操作
* @param account 需要更新的对象
*/
void updateAccount(Account account);
}
IAccountDao.java的实现类 AccountDaoImpl.java
package cn.icanci.dao.impl;
import cn.icanci.dao.IAccountDao;
import cn.icanci.domain.Account;
import lombok.Setter;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
/**
* @Author: icanci
* @ProjectName: jdbcTemplate
* @PackageName: cn.icanci.dao.impl
* @Date: Created in 2020/1/10 21:06
* @ClassAction: 账户的持久层实现类
*/
public class AccountDaoImpl implements IAccountDao {
@Setter
private JdbcTemplate jdbcTemplate;
@Override
public Account findAccountById(Integer id) {
//这个是装x的写法 因为有两次查询 效率会低
// return jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id).size() == 1 ? jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id).get(0) : null;
List listAccount = jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id);
return listAccount.size() == 1 ? listAccount.get(0) : null;
}
@Override
public Account findAccountByName(String name) {
//这个是装x的写法 因为有两次查询 效率会低
//return jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name).size() == 1 ? jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name).get(0) : null;
List listAccount = jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name);
if (listAccount.isEmpty()) {
return null;
}
if (listAccount.size() > 1) {
throw new RuntimeException("结果集不唯一");
}
return listAccount.get(0);
}
@Override
public void updateAccount(Account account) {
jdbcTemplate.update("update account set name = ?,money = ? where id = ?", account.getName(), account.getMoney(), account.getId());
}
}
配置文件 bean.xml
测试类:
package cn.icanci.jdbcTemplate;
import cn.icanci.dao.IAccountDao;
import cn.icanci.domain.Account;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
/**
* @Author: icanci
* @ProjectName: jdbcTemplate
* @PackageName: cn.icanci.jdbcTemplate
* @Date: Created in 2020/1/10 17:20
* @ClassAction: JDBCTemplate的最基本用法
*/
public class JdbcTemplateDemo4 {
public static void main(String[] args) {
//1.获取容器
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//2.获取对象
IAccountDao accountDao = ac.getBean("accountDao", IAccountDao.class);
//3.执行操作
Account account = accountDao.findAccountById(100);
System.out.println(account);
}
}
测试结果: 因为我数据库没有100
null
上述代码的优化
编写 JdbcDaoSupport.java 用于抽取Dao中的重复代码
package cn.icanci.dao.impl;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
/**
* @Author: icanci
* @ProjectName: jdbcTemplate
* @PackageName: cn.icanci.dao.impl
* @Date: Created in 2020/1/10 21:28
* @ClassAction: 用于抽取Dao中的重复代码
*/
public class JdbcDaoSupport {
@Getter
@Setter
private JdbcTemplate jdbcTemplate;
private DataSource dataSource;
public void setDataSource(DataSource dataSource){
this.dataSource = dataSource;
if(jdbcTemplate == null){
jdbcTemplate = createJdbcTemplate(dataSource);
}
}
private JdbcTemplate createJdbcTemplate(DataSource datasource){
return new JdbcTemplate(dataSource);
}
}
AccountDaoImpl.java只需要继承 JdbcDaoSupport.java就可以了
package cn.icanci.dao.impl;
import cn.icanci.dao.IAccountDao;
import cn.icanci.domain.Account;
import lombok.Setter;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
/**
* @Author: icanci
* @ProjectName: jdbcTemplate
* @PackageName: cn.icanci.dao.impl
* @Date: Created in 2020/1/10 21:06
* @ClassAction: 账户的持久层实现类
*/
public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {
@Override
public Account findAccountById(Integer id) {
//这个是装x的写法 因为有两次查询 效率会低
// return jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id).size() == 1 ? jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id).get(0) : null;
List listAccount = getJdbcTemplate().query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id);
return listAccount.size() == 1 ? listAccount.get(0) : null;
}
@Override
public Account findAccountByName(String name) {
//这个是装x的写法 因为有两次查询 效率会低
//return jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name).size() == 1 ? jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name).get(0) : null;
List listAccount = getJdbcTemplate().query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name);
if (listAccount.isEmpty()) {
return null;
}
if (listAccount.size() > 1) {
throw new RuntimeException("结果集不唯一");
}
return listAccount.get(0);
}
@Override
public void updateAccount(Account account) {
getJdbcTemplate().update("update account set name = ?,money = ? where id = ?", account.getName(), account.getMoney(), account.getId());
}
}
测试: 测试通过
null
当然 Spring 也提供了这个类.我们来看一下:
区别就是 :如果使用注解开发 可以使用我们自己手写的 如果使用Spring的,就必须使用xml来进行配置
17.Spring中的声明式事务控制 基于注解和基于xml
重点:基于xml配置的声明式事务控制
/**
* Spring中基于XML的声明式事务配置步骤
* 1.配置事务管理器
* 2.配置事务的通知
* 此时需要导入事务的约束 tx的命名空间和约束 同时也需要aop的
* 使用 配置
* 属性:id 唯一标识
* transaction-manager 给事务通知一个事务管理器
* 3.配置AOP的通用切入点表达式
* 4.建立事务和切入点的对应关系
* 5.配置事务的属性
* 实在 tx:advice内部
*/
配置事务的属性:
/**
* 配置事务的属性
* isolation 用于指定事务的隔离级别 默认是 DEFAULT
* propagation 用于指定事务的传播行为 默认值是 REQUIRED 表示一定有事物 查询方法可以是 SUPPORTS
* read-only 指定事务是否只读 只有查询方法才能设置为 true 默认值是 false
* timeout 用于指定事务的过期时间 默认值是 -1 表示永不超市 单位是秒
* rollback-for 用于指定一个异常 产生此异常 事务回滚 没有默认值 任何都回滚
* no-rollback-for 用于指定一个异常 产生此异常 事务不回滚 没有默认值 任何都回滚
*/
代码区
导入依赖
4.0.0
cn.icanci
springtx
1.0-SNAPSHOT
jar
org.springframework
spring-context
5.2.2.RELEASE
org.springframework
spring-jdbc
5.2.2.RELEASE
org.springframework
spring-tx
5.2.2.RELEASE
mysql
mysql-connector-java
5.1.35
org.aspectj
aspectjweaver
1.9.5
org.projectlombok
lombok
1.18.8
provided
junit
junit
4.12
org.springframework
spring-test
5.0.2.RELEASE
Account.java
package cn.icanci.domain;
import lombok.Data;
/**
* @Author: icanci
* @ProjectName: jdbcTemplate
* @PackageName: cn.icanci.domain
* @Date: Created in 2020/1/10 17:13
* @ClassAction: Account的实体类
*/
@Data
public class Account {
private Integer id;
private String name;
private Float money;
}
账户的持久层接口 IAccountDao .java
package cn.icanci.dao;
import cn.icanci.domain.Account;
/**
* @Author: icanci
* @ProjectName: jdbcTemplate
* @PackageName: cn.icanci.dao
* @Date: Created in 2020/1/10 20:51
* @ClassAction: 账户的持久层接口
*/
public interface IAccountDao {
/**
* 根据id查询账户
* @param id 需要查询的id
* @return 返回查询出的的Account对象
*/
Account findAccountById(Integer id);
/**
* 根据姓名查询用户
* @param name 需要查询的用户
* @return 返回查询的的Account对象
*/
Account findAccountByName(String name);
/**
* 更新操作
* @param account 需要更新的对象
*/
void updateAccount(Account account);
}
账户的持久层实现类 AccountDaoImpl .java
package cn.icanci.dao.impl;
import cn.icanci.dao.IAccountDao;
import cn.icanci.domain.Account;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import java.util.List;
/**
* @Author: icanci
* @ProjectName: jdbcTemplate
* @PackageName: cn.icanci.dao.impl
* @Date: Created in 2020/1/10 21:06
* @ClassAction: 账户的持久层实现类
*/
public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {
@Override
public Account findAccountById(Integer id) {
//这个是装x的写法 因为有两次查询 效率会低
// return jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id).size() == 1 ? jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id).get(0) : null;
List listAccount = getJdbcTemplate().query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id);
return listAccount.size() == 1 ? listAccount.get(0) : null;
}
@Override
public Account findAccountByName(String name) {
//这个是装x的写法 因为有两次查询 效率会低
//return jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name).size() == 1 ? jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name).get(0) : null;
List listAccount = getJdbcTemplate().query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name);
if (listAccount.isEmpty()) {
return null;
}
if (listAccount.size() > 1) {
throw new RuntimeException("结果集不唯一");
}
return listAccount.get(0);
}
@Override
public void updateAccount(Account account) {
getJdbcTemplate().update("update account set name = ?,money = ? where id = ?", account.getName(), account.getMoney(), account.getId());
}
}
账户的业务层接口 IAccountService .java
package cn.icanci.service;
import cn.icanci.domain.Account;
/**
* @Author: icanci
* @ProjectName: springtx
* @PackageName: cn.icanci.service
* @Date: Created in 2020/1/10 22:10
* @ClassAction: 账户的业务层接口
*/
public interface IAccountService {
/**
* 根据id查询账户
* @param id 需要查询的id
* @return 返回查询出的的Account对象
*/
Account findAccountById(Integer id);
/**
* 转账
* @param sourceName 转出
* @param targetName 转入
* @param money 转账金额
*/
void transfer(String sourceName,String targetName,Float money);
}
AccountServiceImpl .java
package cn.icanci.service.impl;
import cn.icanci.dao.IAccountDao;
import cn.icanci.domain.Account;
import cn.icanci.service.IAccountService;
import org.springframework.beans.factory.annotation.Autowired;
/**
* @Author: icanci
* @ProjectName: springtx
* @PackageName: cn.icanci.service.impl
* @Date: Created in 2020/1/10 22:12
* @ClassAction:
*/
public class AccountServiceImpl implements IAccountService {
@Autowired
private IAccountDao accountDao;
@Override
public Account findAccountById(Integer id) {
return accountDao.findAccountById(id);
}
@Override
public void transfer(String sourceName, String targetName, Float money) {
//第一步:根据名称查询转出账户
Account source = accountDao.findAccountByName(sourceName);
//第二步:根据名称查询转入账户
Account target = accountDao.findAccountByName(targetName);
//第三步:转出账户捡钱
source.setMoney(source.getMoney() - money);
//第四步:转入账户价钱
target.setMoney(target.getMoney() + money);
//第五步:更新转出账户
accountDao.updateAccount(source);
int i = 1 / 0;
//第六步:更新转入账户
accountDao.updateAccount(target);
}
}
bean.xml配置文件
测试类:
package cn.icanci.test;
import cn.icanci.dao.IAccountDao;
import cn.icanci.service.IAccountService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @Author: icanci
* @ProjectName: springtx
* @PackageName: cn.icanci.test
* @Date: Created in 2020/1/10 22:19
* @ClassAction:
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:bean.xml")
public class AccountServiceTest {
@Autowired
private IAccountService accountService;
@Test
public void testTransfer() {
accountService.transfer("aaa", "bbb", 111F);
}
}
测试通过的,可以完成事务的回滚
重点:基于注解配置的声明式事务控制 非纯注解
基于上一个修改的代码如下:
AccountDaoImpl.java
package cn.icanci.dao.impl;
import java.lang.ref.Reference;
import cn.icanci.dao.IAccountDao;
import cn.icanci.domain.Account;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @Author: icanci
* @ProjectName: jdbcTemplate
* @PackageName: cn.icanci.dao.impl
* @Date: Created in 2020/1/10 21:06
* @ClassAction: 账户的持久层实现类
*/
@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public Account findAccountById(Integer id) {
//这个是装x的写法 因为有两次查询 效率会低
// return jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id).size() == 1 ? jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id).get(0) : null;
List listAccount = jdbcTemplate.query("select * from account where id = ?", new BeanPropertyRowMapper<>(Account.class), id);
return listAccount.size() == 1 ? listAccount.get(0) : null;
}
@Override
public Account findAccountByName(String name) {
//这个是装x的写法 因为有两次查询 效率会低
//return jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name).size() == 1 ? jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name).get(0) : null;
List listAccount = jdbcTemplate.query("select * from account where name = ?", new BeanPropertyRowMapper<>(Account.class), name);
if (listAccount.isEmpty()) {
return null;
}
if (listAccount.size() > 1) {
throw new RuntimeException("结果集不唯一");
}
return listAccount.get(0);
}
@Override
public void updateAccount(Account account) {
jdbcTemplate.update("update account set name = ?,money = ? where id = ?", account.getName(), account.getMoney(), account.getId());
}
}
AccountServiceImpl.java
package cn.icanci.service.impl;
import cn.icanci.dao.IAccountDao;
import cn.icanci.domain.Account;
import cn.icanci.service.IAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
/**
* @Author: icanci
* @ProjectName: springtx
* @PackageName: cn.icanci.service.impl
* @Date: Created in 2020/1/10 22:12
* @ClassAction:
*/
@Service("accountService")
@Transactional(propagation = Propagation.SUPPORTS,readOnly = true)
public class AccountServiceImpl implements IAccountService {
@Autowired
private IAccountDao accountDao;
@Override
public Account findAccountById(Integer id) {
return accountDao.findAccountById(id);
}
@Transactional(propagation = Propagation.REQUIRED,readOnly = false)
@Override
public void transfer(String sourceName, String targetName, Float money) {
//第一步:根据名称查询转出账户
Account source = accountDao.findAccountByName(sourceName);
//第二步:根据名称查询转入账户
Account target = accountDao.findAccountByName(targetName);
//第三步:转出账户捡钱
source.setMoney(source.getMoney() - money);
//第四步:转入账户价钱
target.setMoney(target.getMoney() + money);
//第五步:更新转出账户
accountDao.updateAccount(source);
// int i = 1 / 0;
//第六步:更新转入账户
accountDao.updateAccount(target);
}
}
bean.xml配置
其他不变:测试通过的
重点:基于注解配置的声明式事务控制 纯注解
现在可以直接删除掉 bean.xml 不过可以一边配置一边删除
依然使用上述的例子 这里只给出修改部分的代码
增加配置类 SpringConfiguration.java
package cn.icanci.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.annotation.Resource;
/**
* @Author: icanci
* @ProjectName: springtx
* @PackageName: cn.icanci.config
* @Date: Created in 2020/1/10 23:12
* @ClassAction: Spring的配置类 相当于 bean.xml
*/
@Configuration
@ComponentScan("cn.icanci")
@Import({JdbcConfiguration.class,TransactionConfiguration.class})
@PropertySource("jdbcConfigurate.properties")
@EnableTransactionManagement
public class SpringConfiguration {
}
增加配置类 配置数据库链接 JdbcConfiguration .java
package cn.icanci.config;
import java.beans.Beans;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
/**
* @Author: icanci
* @ProjectName: springtx
* @PackageName: cn.icanci.config
* @Date: Created in 2020/1/10 23:13
* @ClassAction: 和练级数据库相关的配置类
*/
public class JdbcConfiguration {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
/**
* 创建JdbcTemplate
* @param datasource
* @return
*/
@Bean(name="jdbcTemplate")
public JdbcTemplate createJdbcTemplate(DataSource datasource){
return new JdbcTemplate(datasource);
}
@Bean(name = "datasource")
public DataSource createDataSource(){
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
return ds;
}
}
增加配置类 处理事务 TransactionConfiguration.java
package cn.icanci.config;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
/**
* @Author: icanci
* @ProjectName: springtx
* @PackageName: cn.icanci.config
* @Date: Created in 2020/1/10 23:26
* @ClassAction: 用于创建事务管理器的类
*/
public class TransactionConfiguration {
/**
* 用于创建事务管理器
* @param dataSource
* @return
*/
@Bean(name = "transactionManagement")
public PlatformTransactionManager createTransactionManager(DataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
}
增加配置文件 jdbcConfigurate.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/icanci
jdbc.username=root
jdbc.password=ok
修改测试类 AccountServiceTest.java 并且测试
package cn.icanci.test;
import cn.icanci.config.SpringConfiguration;
import cn.icanci.dao.IAccountDao;
import cn.icanci.service.IAccountService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @Author: icanci
* @ProjectName: springtx
* @PackageName: cn.icanci.test
* @Date: Created in 2020/1/10 22:19
* @ClassAction:
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class AccountServiceTest {
@Autowired
private IAccountService accountService;
@Test
public void testTransfer() {
accountService.transfer("aaa", "bbb", 111F);
}
}
最后是测试通过的
18.Spring中的编程式事务控制
这里暂时不写了,编程式事务控制开发中很少使用
至此 Spring的知识点整合到此告一段落
之后的学习中有需要的会进行补充
华丽的分割线
此处 @我自己 这是QQ聊天的链接 欢迎一起吹
此处 @Spring知识点整合(上) 和 @Spring知识点整合(中)