当前位置: 首页 > news >正文

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

模板技术

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

持久层模板JdbcTemplate

在这里插入图片描述
在这里插入图片描述

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依赖

<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.12</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>aopalliance</groupId><artifactId>aopalliance</artifactId><version>1.0</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.13</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.6</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>5.0.2.RELEASE</version></dependency></dependencies>

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

1.1 连接池DataSource代码实例

这是原生的连接池DataSource

@Repository("carDao")
public class CarDaoImpl implements CarDao{@Autowiredprivate DataSource dataSource;public List<Car> findAll() {Connection conn=null;PreparedStatement stmt = null;ResultSet rs = null;List<Car> carList=new ArrayList<Car>();//2.获取连接对象try{conn = dataSource.getConnection();//3.编写sqlString sql = "select * from car";//4.获取执行sql的stmt对象stmt=conn.prepareStatement(sql);//5.执行sqlrs = 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对象中

<?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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!--配置连接池--><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver" /><property name="url" value="jdbc:mysql:///spring_db" /><property name="username" value="root" /><property name="password" value="root" /></bean><!--配置jdbc模板--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource" /></bean></beans>

使用时直接autowired即可

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

2. JdbcTemplate的多种导入方式

2.1 一般的三种方式

<?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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!--导入DataSource的bean对象或者JdbcTemplate的bean对象到bean容器中--><!--1. 导入DataSource的bean对象--><!--1.1 导入Spring框架内置的连接池--><bean id="dataSource11" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql:///mybatis_demo"/><property name="username" value="root"/><property name="password" value="980708"/></bean><!--1.2 导入使用开源连接池druid--><bean id="dataSource12" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql:///mybatis_demo"/><property name="username" value="root"/><property name="password" value="980708"/></bean><!--PropertyPlaceholderConfigurer是PlaceholderConfigurerSupport的一个子类,用来解析${…} 占位符的,可以使用setLocation和setProperties设置系统属性和环境变量。--><!--1.3.1 加载属性的文件,进而解析${…}占位符--><bean id="placeholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><property name="location" value="classpath:druid.properties"/></bean><!--1.3.2 第二种写法:使用提供标签的方式--><context:property-placeholder location="classpath:druid.properties"/><!--1.3 使用加载属性的文件配置druid连接池--><bean id="dataSource13" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driverClassName}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean><!--2.1 使用模板,Spring框架内置的连接池--><bean id="jdbcTemplate1" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource11"/></bean><!--2.2 使用模板,开源连接池druid配置jdbc模板--><bean id="jdbcTemplate2" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource12"/></bean><!--2.3 使用模板,开源连接池druid的配置文件加载jdbc模板--><bean id="jdbcTemplate3" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource13"/></bean>
</beans>

导入连接池对象的方式有多种,所以注入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
<?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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!--1.3.1 加载属性的文件,进而解析${…}占位符--><bean id="placeholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><property name="location" value="classpath:druid.properties"/></bean><!--1.3.2 第二种写法:使用提供标签的方式--><context:property-placeholder location="classpath:druid.properties"/><!--1.3 使用加载属性的文件配置druid连接池--><bean id="dataSource13" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driverClassName}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean><!--2.3 使用模板,开源连接池druid的配置文件加载jdbc模板--><bean id="jdbcTemplate3" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource13"/></bean>
</beans>

2.2 简写的形式

 <!--配置dao1--><bean id="accountDao" class="com.qcby.mySpring04.mapper.impl.AccountDaoImpl"><property name="jdbcTemplate" ref="jdbcTemplate"/></bean><!--2. Dao的第二种使用方式--><!--区别在于:1. 不需要导入jdbcTemplate的bean对象;2. dao的bean对象依赖注入从jdbcTemplate对象改为dataSource,但是需要daoImpl继承JdbcDaoSupport类--><!--配置service--><bean id="accountDao2" class="com.qcby.mySpring04.mapper.impl.AccountDaoImpl2"><property name="dataSource" ref="dataSource"/></bean>

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

import org.springframework.jdbc.core.support.JdbcDaoSupport;public class AccountDaoImpl2 extends JdbcDaoSupport implements AccountDao {@Overridepublic void outMoney(String out, double money) {this.getJdbcTemplate().update("update account set money = money - ? where name = ?",money, out);}@Overridepublic 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导入略

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!--配置平台事务管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><!--Spring自带的事务切面通知管理--><!--配置事务的通知(没有自己编写切面类,通知方法也不是自己编写,Spring框架提供的)--><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><!--对pay进行增强,设置隔离级别,传播行为,超时的时间--><tx:method name="pay" isolation="DEFAULT" propagation="REQUIRED" /><tx:method name="find*" read-only="true" /></tx:attributes></tx:advice><!--配置AOP的增强--><aop:config><!--Spring框架提供系统通知,使用advisor标签--><aop:advisor advice-ref="txAdvice"pointcut="execution( * com.qcby.*.service.impl.*ServiceImpl.*(..))" /></aop:config><import resource="ApplicationContext_jdbc.xml"/>
</beans>

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

<!--配置平台事务管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><!--开启事务注解的支持--><tx:annotation-driven transaction-manager="transactionManager" />

@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 {@Autowiredprivate 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使用

相关文章:

  • C++_01
  • 【数据结构 之压栈,形参和局部变量入栈之前会发生什么?】三种解释回答 包含操作系统版
  • Word文档中公式的常用操作
  • 被裁了(9年)
  • 【C++/STL深度剖析】stack和queue的详细概念和使用(图文详解,初学者必看!!)
  • Spring Cloud 概述
  • 【鸿蒙学习笔记】@Prop装饰器:父子单向同步
  • spring boot读取yml配置注意点记录
  • [数据集][目标检测]围栏破损检测数据集VOC+YOLO格式1196张1类别
  • 封装stater时配置导入配置类提示功能
  • MacOS docker 安装与配置
  • 工具:颜色查询 / CMYK颜色查询RGB、HSL、HSV、XYZ的颜色值
  • 提升学生职务执行力的智慧校园学工管理策略
  • ubuntu中后台启动一个jar
  • 等保测评——云计算安全扩展(云计算关键技术)
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • Angular 2 DI - IoC DI - 1
  • Debian下无root权限使用Python访问Oracle
  • JavaScript中的对象个人分享
  • js继承的实现方法
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • select2 取值 遍历 设置默认值
  • SQLServer之创建数据库快照
  • TCP拥塞控制
  • 算法之不定期更新(一)(2018-04-12)
  • 无服务器化是企业 IT 架构的未来吗?
  • 移动端 h5开发相关内容总结(三)
  • 国内唯一,阿里云入选全球区块链云服务报告,领先AWS、Google ...
  • ​ssh-keyscan命令--Linux命令应用大词典729个命令解读
  • ​软考-高级-系统架构设计师教程(清华第2版)【第1章-绪论-思维导图】​
  • #14vue3生成表单并跳转到外部地址的方式
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • $$$$GB2312-80区位编码表$$$$
  • (11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】
  • (4.10~4.16)
  • (C语言)二分查找 超详细
  • (DFS + 剪枝)【洛谷P1731】 [NOI1999] 生日蛋糕
  • (pojstep1.1.2)2654(直叙式模拟)
  • (solr系列:一)使用tomcat部署solr服务
  • (void) (_x == _y)的作用
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • (未解决)macOS matplotlib 中文是方框
  • (详细版)Vary: Scaling up the Vision Vocabulary for Large Vision-Language Models
  • ****Linux下Mysql的安装和配置
  • .Net CoreRabbitMQ消息存储可靠机制
  • .NET 分布式技术比较
  • .NET/C# 将一个命令行参数字符串转换为命令行参数数组 args
  • .Net7 环境安装配置
  • .netcore 如何获取系统中所有session_如何把百度推广中获取的线索(基木鱼,电话,百度商桥等)同步到企业微信或者企业CRM等企业营销系统中...
  • .NET业务框架的构建
  • .net中生成excel后调整宽度
  • .php结尾的域名,【php】php正则截取url中域名后的内容
  • @Autowired自动装配
  • @converter 只能用mysql吗_python-MySQLConverter对象没有mysql-connector属性’...