Spring自带的持久层模板类:JdbcTemplate+Spring框架声明式事务管理实战
模板技术
Spring框架中提供了很多模板类来简化编程,使用模板类编写程序会变的简单
持久层模板JdbcTemplate
JdbcTemplate是什么
JDBCTemplate是Spring Framework中的一个核心类,用于简化JDBC(Java数据库连接)代码的编写。它提供了一种更简单、更干净的方式来执行数据库操作,同时抽象了许多常见的数据库任务,如连接管理、异常处理和资源释放。使用JDBCTemplate,开发人员可以更专注于业务逻辑,而不必担心底层数据库操作的细节。
JDBCTemplate和Mybatis的区别
1. JDBCTemplate相当于Spring框架自带的Mybatis的弱化版,mybatis支持声明式事务管理,JDBCTemplate则不支持;
-
mybatis是一种ORM模型,JDBCTemplate则是对连接池的直接封装,本质上是纯SQL;
-
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)
-
如果使用的Spring的JDBC模板或者MyBatis框架,需要选择DataSourceTransactionManager实现类
-
如果使用的是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使用