Spring知识点整合(下)

此处 @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)");
    }
}

测试结果:


Spring知识点整合(下)_第1张图片
测试结果

现在使用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)");
    }
}

测试结果:


Spring知识点整合(下)_第2张图片
测试结果

实现最基本的增删改查

创建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知识点整合(下)_第3张图片
Spring提供的JdbcDaoSupport.java

区别就是 :如果使用注解开发 可以使用我们自己手写的 如果使用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知识点整合(中)

你可能感兴趣的:(Spring知识点整合(下))