Spring自带的持久层模板类:JdbcTemplate+Spring框架声明式事务管理实战

06-28 1220阅读

模板技术

Spring框架中提供了很多模板类来简化编程,使用模板类编写程序会变的简单

持久层模板JdbcTemplate

Spring自带的持久层模板类:JdbcTemplate+Spring框架声明式事务管理实战

Spring自带的持久层模板类:JdbcTemplate+Spring框架声明式事务管理实战

JdbcTemplate是什么

JDBCTemplate是Spring Framework中的一个核心类,用于简化JDBC(Java数据库连接)代码的编写。它提供了一种更简单、更干净的方式来执行数据库操作,同时抽象了许多常见的数据库任务,如连接管理、异常处理和资源释放。使用JDBCTemplate,开发人员可以更专注于业务逻辑,而不必担心底层数据库操作的细节。

JDBCTemplate和Mybatis的区别

1. JDBCTemplate相当于Spring框架自带的Mybatis的弱化版,mybatis支持声明式事务管理,JDBCTemplate则不支持;

  1. mybatis是一种ORM模型,JDBCTemplate则是对连接池的直接封装,本质上是纯SQL;

  2. mybatis由于实体关系映射,实际的性能会比JDBCTemplate低一些,但是更加灵活

参考文章:

【Java 进阶篇】深入了解JDBCTemplate:简化Java数据库操作

弃用MyBatis!我们最终选择了 JDBCTemplate!

JdbcTemplate实战

0. maven依赖

    
        org.springframework
        spring-context
        5.0.2.RELEASE
    
    
        commons-logging
        commons-logging
        1.2
    
    
        log4j
        log4j
        1.2.12
    
    
        junit
        junit
        4.12
    
    
        org.springframework
        spring-test
        5.0.2.RELEASE
    
    
    
        aopalliance
        aopalliance
        1.0
    
    
        org.springframework
        spring-aspects
        5.0.2.RELEASE
    
    
        org.aspectj
        aspectjweaver
        1.8.13
    
    
        mysql
        mysql-connector-java
        5.1.6
    
    
        org.springframework
        spring-jdbc
        5.0.2.RELEASE
    
    
        org.springframework
        spring-tx
        5.0.2.RELEASE
    
  

1. JdbcTemplate相比于原生的DataSource的优势:简写代码

1.1 连接池DataSource代码实例

这是原生的连接池DataSource

@Repository("carDao")
public class CarDaoImpl implements CarDao{
    @Autowired
    private DataSource dataSource;
    public List findAll() {
        Connection conn=null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        List carList=new ArrayList();
        //2.获取连接对象
        try{
            conn = dataSource.getConnection();
            //3.编写sql
            String sql = "select * from car";
            //4.获取执行sql的stmt对象
            stmt=conn.prepareStatement(sql);
            //5.执行sql
            rs = stmt.executeQuery();
            //6.遍历结果集
            while(rs.next()){
                //实体类  account的实体类
                Car car = new Car();
                car.setId(rs.getInt("id"));
                car.setCarName(rs.getString("car_name"));
                car.setSize(rs.getInt("size"));
                car.setColor(rs.getString("color"));
                // 存储
                carList.add(car);
            }
            //7.关闭
            conn.close();
            stmt.close();
            rs.close();
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println("持久层:操作数据库保存订单");
        return  carList;
    }

获取连接,创建执行对象,编写sql,执行sql,遍历sql执行结果,关闭资源一步都不能少

1.2 new方式创建JdbcTemplate

先创建连接池对象,然后再创建JdbcTemplate对象

    /**
     * 使用new对象方式完成
     */
    public void test(){
        // 创建连接池对象,Spring框架内置了连接池对象
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        // 设置4个参数
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///spring_db");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        
        // 提供模板,创建对象
        JdbcTemplate template = new JdbcTemplate(dataSource);
        // 完成数据的增删改查
        template.update("insert into account values (null,?,?)","熊大",1000);
    }
1.3 控制反转,依赖注入的方式创建JdbcTemplate的bean对象(使用Spring框架来管理模板类)

先创建连接池dataSource的bean对象,再将这个bean对象依赖注入JdbcTemplate的bean对象中


    
    
        
        
        
        
    
    
    
        
    

使用时直接autowired即可

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext_jdbc.xml")
public class Demo1_1 {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    /**
     * 测试的方式
     */
    @Test
    public void run1(){
        jdbcTemplate.update("insert into account values (null,?,?)","熊二",500);
    }
}

2. JdbcTemplate的多种导入方式

2.1 一般的三种方式


    
    
    
    
        
        
        
        
    
    
    
        
        
        
        
    
    
    
    
        
    
    
    
    
    
        
        
        
        
    
    
    
        
    
    
    
        
    
    
    
        
    

导入连接池对象的方式有多种,所以注入dataSource给JdbcTemplate对象时的方式也就有许多种

最推荐的还是读取.properties文件/.yml文件的方式,最为灵活

jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql:///mybatis_demo?serverTimezone=UTC
jdbc.username=root
jdbc.password=980708


    
        
    
    
    
    
    
        
        
        
        
    

    
        
    

2.2 简写的形式

 
    
        
    
    
    
    
    
        
    

我们可以发现,第二种形式的dao不需要注入JdbcTemplate,而是直接注入dataSource即可,但是DaoImpl的实现稍有不同

import org.springframework.jdbc.core.support.JdbcDaoSupport;
public class AccountDaoImpl2 extends JdbcDaoSupport implements AccountDao {
    @Override
    public void outMoney(String out, double money) {
        this.getJdbcTemplate().update("update account set money = money - ? where name = ?",
                money, out);
    }
    @Override
    public void inMoney(String in, double money) {
        this.getJdbcTemplate().update("update account set money = money - ? where name = ?",
                money, in);
    }
}

需要额外继承JdbcDaoSupport父类

3. JdbcTemplate可以直接与Spring自带的事务管理集成

相比于正常的AOP,两个都是Spring的亲儿子,所以可以少写很多代码,比如AOP配置类不用写

PlatformTransactionManager接口是平台事务管理器。该接口有具体的实现类,根据不同的持久层框架,需要选择不同的实现类!

接口方法如下:

void commit(TransactionStatus status)

void rollback(TransactionStatus status)

  1. 如果使用的Spring的JDBC模板或者MyBatis框架,需要选择DataSourceTransactionManager实现类

  2. 如果使用的是Hibernate的框架,需要选择HibernateTransactionManager实现类

3.1 xml文件配置Spring框架声明式事务管理

不需要我们自己写切面类,也不需要我们自己写增强的方法,Spring帮我们做好了

JdbcTemplate模板,dataSource,还有dao和service的bean导入略


    
    
        
    
    
    
    
        
            
            
            
        
    
    
    
        
        
    
    

3.2 半注解的配置Spring框架声明式事务管理

    
        
    

    

@Transactional可以加在类上,也可以加在方法上

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
@Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, timeout = 10)
@Service
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }
    /**
     * 转账方法
     *
     * @param out   付款人
     * @param in    收款人
     * @param money 金额
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void pay(String out, String in, double money) {
        // 调用dao方法
        accountDao.outMoney(out, money);
        accountDao.inMoney(in, money);
    }
}

3.3 全注解

import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    import org.springframework.jdbc.datasource.DriverManagerDataSource;
    
    @Configuration
    @ComponentScan(basePackages="cn.qcby")
    @EnableTransactionManagement        // 开启事务注解
    public class SpringTransactionConfig {
        
        /**
         * @return
         * @throws Exception 
         */
        @Bean(name="dataSource")
        public DataSource createDataSource() throws Exception{
            // 创建连接池对象,Spring框架内置了连接池对象
            DriverManagerDataSource dataSource = new DriverManagerDataSource();
            // 设置4个参数
            dataSource.setDriverClassName("com.mysql.jdbc.Driver");
            dataSource.setUrl("jdbc:mysql:///spring_db");
            dataSource.setUsername("root");
            dataSource.setPassword("root");
            return dataSource;
        }
        
        /**
         * 创建模板对象
         * @return
         */
        @Resource(name="dataSource")        // 不仅可以作用在属性上,也可以作用方法上。
        @Bean(name="jdbcTemplate")          // 把JdbcTemplate保存到IOC容器中
        public JdbcTemplate createJdbcTemplate(DataSource dataSource){
            JdbcTemplate template = new JdbcTemplate(dataSource);
            return template;
        }
        
        /**
         * 创建平台事务管理器对象
         * @param dataSource
         * @return
         */
        @Resource(name="dataSource")
        @Bean(name="transactionManager")
        public PlatformTransactionManager createTransactionManager(DataSource dataSource){
            DataSourceTransactionManager manager = new DataSourceTransactionManager(dataSource);
            return manager;
        }

@Resource注解是依赖注入的注解,根据name唯一查找bean

@Autowired也是依赖注入的注解,但是@Autowired只能根据类型注入

所以@Autowired一般和@Controller,@Component,@Service,@Repository配合使用

而@Resource一般和@Bean使用

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]