SpringJDBC
- JDBC模板技术概述
- JDBC的模板类的使用
- Spring框架的事务管理
- 配置文件方式
- 半注解的方式
- 纯注解的方式
JDBC模板技术概述
什么是 JDBC 模板技术?
JDBC 模板技术是 Spring 框架为简化持久层(数据库操作)编程而提供的一种封装机制,核心类为JdbcTemplate。它基于模板设计模式,将 JDBC 操作中重复、繁琐的底层代码进行封装,让开发者只需关注核心业务逻辑(如 SQL 语句编写、结果集处理)。
模板(template)技术的设计思想:
Spring 框架中提供了一系列以XxxTemplate命名的模板类(如JdbcTemplate、HibernateTemplate、RedisTemplate等),其核心思想是:将固定流程的代码封装为模板,将可变的业务逻辑通过回调接口暴露给开发者。
对于 JDBC 操作而言,固定流程包括:获取数据库连接(Connection)、创建 SQL 执行对象(Statement/PreparedStatement)、执行 SQL 语句、处理异常(如SQLException)、释放资源(关闭ResultSet、Statement、Connection)
JdbcTemplate将这些固定流程封装,开发者只需提供 SQL 语句和结果处理逻辑即可。
JDBC的模板类的使用
创建 maven java 工程,引入坐标依赖
<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>
new 对象的方式
编写测试代码
import org.junit.Test;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;public class Demo {/*** 使用的是 Spring 框架内置的连接池* 使用 new 对象方式完成*/@Testpublic void run1(){// 创建连接池对象,Spring 框架内置了连接池对象DriverManagerDataSource dataSource = new DriverManagerDataSource();// 设置 4 个参数dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql:///ssm");dataSource.setUsername("root");dataSource.setPassword("root");// 提供模板,创建对象JdbcTemplate template = new JdbcTemplate(dataSource);// 完成数据的增删改查template.update("insert into account values (null,?,?)","熊大 ",1000);}
}
使用 Spring 框架管理模板类
applicationContext_jdbc.xml
<!--配置连接池--><bean id="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql:///ssm" /><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>
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext_jdbc.xml")
public class Demo1 {@Autowiredprivate JdbcTemplate jdbcTemplate;/*** 测试的方式* 使用开源连接池*/@Testpublic void run1(){jdbcTemplate.update("insert into account values (null,?,?)"," 小丽",500);}
}
Spring 框架管理开源的连接池
配置开源的连接池,使用 Druid 开源的连接池,引入坐标依赖
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.10</version></dependency>
将数据库连接的信息配置到属性文件中
配置数据库访问相关的组件
<!--加载属性文件--><bean id="placeholderConfigurer"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><!-- 指定属性文件路径:classpath表示从类路径下查找 --><property name="location" value="classpath:jdbc.properties" /></bean><!--加载属性文件第二种写法:使用提供标签的方式--><!--<context:property-placeholderlocation="classpath:jdbc.properties" />--><!--配置数据库连接池,使用占位符引用属性--><bean id="dataSource"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><!--配置 jdbc 模板--><bean id="jdbcTemplate"class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource" /></bean>
- 加载外部属性文件(数据库配置信息)
<bean id="placeholderConfigurer">
定义了PropertyPlaceholderConfigurer组件,作用是加载类路径(classpath)下的jdbc.properties属性文件,通过这种方式,数据库连接信息可以写在外部的jdbc.properties文件中,而非硬编码在 XML 里,便于后期修改和维护。<context:property-placeholder>
是另一种更简洁的加载属性文件的方式,功能完全一致。 - 配置数据库连接池(Druid)
<bean id="dataSource">
定义了阿里巴巴的DruidDataSource(德鲁伊连接池),其中的driverClassName、url、username、password属性值使用${key}
格式的占位符,这些占位符会被前面加载的jdbc.properties文件中对应的键值对替换,通过配置连接池,应用可以高效地管理数据库连接,避免频繁创建 / 关闭连接的性能损耗。 - 配置 Spring JDBC 模板
<bean id="jdbcTemplate">
定义了 Spring 提供的JdbcTemplate组件,这是一个简化 JDBC 操作的模板类,通过dataSource属性引用了前面定义的dataSource(数据库连接池),从而关联到数据库。
通过这段配置,Spring 容器会自动读取外部 jdbc.properties 中的数据库配置、初始化 Druid 连接池管理数据库连接、初始化 JdbcTemplate 并关联连接池。最终,应用可以直接从 Spring 容器中获取 jdbcTemplate 对象,便捷地进行数据库操作,同时数据库配置可通过修改 jdbc.properties 灵活调整,无需改动 XML 配置。
增删改查代码编写
import com.qcby.Model.Account;
import com.qcby.Model.BeanMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import java.util.List;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext_jdbc.xml")
public class Demo2 {@Autowiredprivate JdbcTemplate jdbcTemplate;/*** 测试的方式* 加载属性文件的方式*/@Testpublic void run1(){jdbcTemplate.update("insert into account values (null,?,?)"," 熊四",800);}/*** 修改*/@Testpublic void run2(){jdbcTemplate.update("update account set name = ?,money = ? where id = ?","光头强",100,7);}/*** 删除*/@Testpublic void run3(){jdbcTemplate.update("delete from account where id = ?",7);}/*** 通过 id 查询*/@Testpublic void run4(){Account account = jdbcTemplate.queryForObject("select * from account where id = ?", new BeanMapper(), 6);System.out.println(account);}/*** 查询所有的数据*/@Testpublic void run5(){List<Account> list = jdbcTemplate.query("select * from account", new BeanMapper());for (Account account : list) {System.out.println(account);}}
}
public class Account {private int id;private String name;private double money;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getMoney() {return money;}public void setMoney(double money) {this.money = money;}@Overridepublic String toString() {return "Account{" +"id=" + id +", name='" + name + '\'' +", money=" + money +'}';}
}
Account类是account数据库表的映射实体类,属性对应数据表中的字段,作为数据载体,封装从数据库查询到的记录,或封装要插入或更新的数据。
import org.springframework.jdbc.core.RowMapper;import java.sql.ResultSet;
import java.sql.SQLException;/*** 实现类,用来进行数据封装的*/
public class BeanMapper implements RowMapper<Account>{public Account mapRow(ResultSet resultSet, int i) throws SQLException {/*** 逐行进行数据封装*/Account account = new Account();account.setId(resultSet.getInt("id"));account.setName(resultSet.getString("name"));account.setMoney(resultSet.getDouble("money"));return account;}
}
BeanMapper 类是结果集映射器的实现类,它实现了Spring JDBC的 RowMapper 函数式接口并指定泛型为 Account,核心职责是将数据库查询返回的 ResultSet 结果集逐行转换为 Account 类型对象。
RowMapper 接口仅定义抽象方法 mapRow,BeanMapper 通过实现该方法定义具体行映射逻辑:当 JdbcTemplate 执行查询并遍历 ResultSet 时,每处理一行数据便调用 mapRow 方法,传入当前行 ResultSet 实例及行索引;mapRow 从结果集中提取对应字段值,赋值给新创建的 Account 对象并返回。
此实现解决了数据库结果集与Java对象的映射问题,使 JdbcTemplate 查询可直接返回 Account 对象或其集合,便于以面向对象方式处理查询结果。
实现效果:
使用JDBC模板操作数据库实现模拟转账开发
Service 层代码的编写
public interface AccountService {/*** 转账的方法* @param out 付款人* @param in 收款人* @param money 金额*/public void pay(String out,String in,double money);
}
import com.qcby.dao.AccountDao;
import com.qcby.service.AccountService;public class AccountServiceImpl implements AccountService {private AccountDao accountDao;public void setAccountDao(AccountDao accountDao) {this.accountDao = accountDao;}public void pay(String out, String in, double money) {// 调用 dao 方法accountDao.outMoney(out,money);accountDao.inMoney(in,money);}
}
Dao 层代码的编写
public interface AccountDao {/*** 付款* @param out* @param money*/public void outMoney(String out,double money);/*** 收款* @param in* @param money*/public void inMoney(String in,double money);
}
import com.qcby.dao.AccountDao;
import org.springframework.jdbc.core.JdbcTemplate;public class AccountDaoImpl implements AccountDao{// 依赖Spring的JdbcTemplate,通过JdbcTemplate执行具体的SQL语句,操作数据库private JdbcTemplate jdbcTemplate;//提供setter方法,让Spring注入JdbcTemplatepublic void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}/*** 付款* @param out* @param money*/public void outMoney(String out, double money) {jdbcTemplate.update("update account set money = money - ? where name = ?",money,out);}/*** 收款* @param in* @param money*/public void inMoney(String in, double money) {jdbcTemplate.update("update account set money = money + ? where name = ?",money,in);}
}
配置文件代码编写
<!--加载jdbc.properties文件,使用提供标签的方式--><context:property-placeholder location="classpath:jdbc.properties" /><!--加载属性的文件,配置数据库连接池,负责管理数据库连接--><bean id="dataSource"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><!--配置Jdbc模板类,创建JdbcTemplate对象,并注入dataSource--><bean id="jdbcTemplate"class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource" /></bean><!--配置Service对象,注入Dao--><bean id="accountDao" class="com.qcby.dao.impl.AccountDaoImpl"><property name="jdbcTemplate" ref="jdbcTemplate" /></bean><!--配置Dao对象,注入JdbcTemplate--><bean id="accountService" class="com.qcby.service.impl.AccountServiceImpl"><property name="accountDao" ref="accountDao"/></bean>
测试代码编写
import com.qcby.service.AccountService;
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;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext_dao1.xml")
public class Demo3 {@Autowiredprivate AccountService accountService;/*** 测试转账的方法*/@Testpublic void testPay(){accountService.pay("熊大","熊二",100);}
}
Dao 层编写的第二种方式
import com.qcby.dao.AccountDao;
import org.springframework.jdbc.core.support.JdbcDaoSupport;public class AccountDaoImpl1 extends JdbcDaoSupport implements AccountDao {/*** 付款* @param out* @param money*/public void outMoney(String out, double money) {this.getJdbcTemplate().update("update account set money = money - ? where name = ?",money,out);}/*** 收款* @param in* @param money*/public void inMoney(String in, double money) {this.getJdbcTemplate().update("update account set money = money + ? where name = ?",money,in);}
}
AccountDaoImpl1 继承了 Spring 提供的 JdbcDaoSupport 类,该类是 Spring 为简化 JDBC 操作提供的工具类,内部已封装了 JdbcTemplate 对象,子类可直接通过 getJdbcTemplate() 方法获取 JdbcTemplate,无需手动定义和注入,减少重复代码。
配置文件编写
<!--第二种写法:使用提供标签的方式--><context:property-placeholder location="classpath:jdbc.properties" /><!--加载属性的文件--><bean id="dataSource" 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><!--配置 service--><bean id="accountServicePx"class="com.qcby.service.impl.AccountServiceImpl"><property name="accountDao" ref="accountDao"/></bean><bean id="accountDao" class="com.qcby.dao.impl.AccountDaoImpl1"><property name="dataSource" ref="dataSource" /></bean>
编写测试类
import com.qcby.service.AccountService;
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;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext_dao2.xml")
public class Demo4 {@Autowiredprivate AccountService accountService;/*** 测试转账的方法*/@Testpublic void testPay(){accountService.pay("熊大","熊二",100);}
}
Spring框架的事务管理
核心接口与实现类
平台事务管理器:PlatformTransactionManager
PlatformTransactionManager 是 Spring 事务管理的核心接口,定义了事务操作的标准规范,是事务执行器的角色。它屏蔽了不同持久层框架的事务差异,开发者需根据实际使用的持久层技术选择对应的实现类。Spring 为不同的持久层框架提供了对应的 PlatformTransactionManager 实现
如果使用的 Spring 的 JDBC 模板或者 MyBatis 框架,需要选择 DataSourceTransactionManager 实现类
如果使用的是 Hibernate 的框架,需要选择 HibernateTransactionManager 实现类
接口方法如下:
void commit(TransactionStatus status)
void rollback(TransactionStatus status)
事务规则定义:TransactionDefinition
TransactionDefinition 是事务规则描述的接口,定义了事务隔离级别、事务传播行为,这些属性决定了事务的运行规则。
配置文件方式
<?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"><!--第二种写法:使用提供标签的方式--><context:property-placeholderlocation="classpath:jdbc.properties" /><!--加载属性的文件--><bean id="dataSource"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><!--配置平台事务管理器--><bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><!--配置事务的通知(没有自己编写切面类,通知方法也不是自己编写,是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(public* com.qcby.service.impl.AccountServiceImpl1.pay(..))" /></aop:config><!--配置 service--><bean id="accountServicePx"class="com.qcby.service.impl.AccountServiceImpl"><property name="accountDao" ref="accountDao"/></bean><!--配置 dao --><bean id="accountDao" class="com.qcby.dao.impl.AccountDaoImpl1"><property name="dataSource" ref="dataSource" /></bean>
</beans>
这段 XML 配置文件是Spring 框架基于 XML 实现声明式事务管理的核心配置,同时整合了数据库连接、数据访问层、业务逻辑层的 Bean 定义,最终实现对AccountServiceImpl类中pay方法的事务增强。
tx:advice 是 Spring 提供的事务通知组件,无需手动编写切面类和通知方法,是事务规则的载体,transaction-manager=“transactionManager” 关联配置的事务管理器,通知需通过管理器执行事务操作,tx:attributes 定义哪些方法需要事务及事务的具体规则。
aop:advisor 是 Spring 的通知器,专门用于绑定事务通知(tx:advice)和切入点,区别于普通 AOP 的 aop:aspect,advisor 是 Spring 为事务等系统级通知提供的简化标签。advice-ref=“txAdvice” 关联定义的事务通知,pointcut=“execution(…)” 定义切入点。
测试
import com.qcby.service.AccountService;
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;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext_tx.xml")
public class Demo5 {@Autowiredprivate AccountService accountService;/*** 测试转账的方法*/@Testpublic void testPay(){accountService.pay("熊大","熊二",100);}
}
半注解的方式
<?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: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/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!--开启注解的扫描--><context:component-scan base-package="com.qcby" /><!--第二种写法:使用提供标签的方式--><context:property-placeholderlocation="classpath:jdbc.properties" /><!--加载属性的文件--><bean id="dataSource"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><!--配置平台事务管理器--><bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><!--配置 Jdbc 模板类--><bean id="jdbcTemplate"class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource" /></bean><!--开启事务注解的支持--><tx:annotation-driven transaction-manager="transactionManager" />
</beans>
Dao 层代码
@Repository("accountDao_1")
public class AccountDaoImpl_1 implements AccountDao {// 依赖Spring的JdbcTemplate,通过JdbcTemplate执行具体的SQL语句,操作数据库private JdbcTemplate jdbcTemplate;//提供setter方法,让Spring注入JdbcTemplate@Autowiredpublic void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}/*** 付款* @param out* @param money*/public void outMoney(String out, double money) {jdbcTemplate.update("update account set money = money - ? where name = ?",money,out);}/*** 收款* @param in* @param money*/public void inMoney(String in, double money) {jdbcTemplate.update("update account set money = money + ? where name = ?",money,in);}
}
Service 层代码
import com.qcby.dao.AccountDao;
import com.qcby.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;@Service
@Transactional(isolation = Isolation.DEFAULT)
public class AccountServiceImpl_1 implements AccountService{@Autowired@Qualifier("accountDao_1")private AccountDao accountDao;/*** 转账方法* @param out 付款人* @param in 收款人* @param money 金额*/public void pay(String out, String in, double money) {// 调用 dao 方法accountDao.outMoney(out,money);// 模拟异常//int a = 1/0;accountDao.inMoney(in,money);}
}
测试
import com.qcby.service.AccountService;
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;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext_tx1.xml")
public class Demo6 {@Autowiredprivate AccountService accountService;/*** 测试转账的方法*/@Testpublic void testPay(){accountService.pay("熊大","熊二",100);}
}
纯注解的方式
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.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;import javax.annotation.Resource;
import javax.sql.DataSource;/*** 配置类* @author Administrator*/
@Configuration
@ComponentScan(basePackages="com.qcby")
@EnableTransactionManagement // 开启事务注解
public class SpringConfig {@Bean(name = "dataSource")public DataSource createDataSource() throws Exception {// 创建连接池对象,Spring 框架内置了连接池对象DriverManagerDataSource dataSource = new DriverManagerDataSource();// 设置 4 个参数dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql:///ssm");dataSource.setUsername("root");dataSource.setPassword("root");return dataSource;}/*** 创建模板对象*/@Resource(name = "dataSource") // 不仅可以作用在属性上,也可以作用方法上。@Bean(name = "jdbcTemplate") // 把 JdbcTemplate 保存到 IOC容器中public JdbcTemplate createJdbcTemplate(DataSource dataSource) {JdbcTemplate template = new JdbcTemplate(dataSource);return template;}/*** 创建平台事务管理器对象*/@Resource(name = "dataSource")@Bean(name = "transactionManager")public PlatformTransactionManagercreateTransactionManager(DataSource dataSource) {DataSourceTransactionManager manager = new DataSourceTransactionManager(dataSource);return manager;}
}
@Configuration:标识当前类是一个 Spring 配置类,Spring 会扫描并解析其中的配置;
@ComponentScan(basePackages=“com.qcby”):开启组件扫描,扫描指定包及其子包下的类,被@Component等注解标记的类会被自动注册到 Spring 容器中;
@EnableTransactionManagement:半注解和纯注解形式需要开启 Spring 的注解式事务管理支持,与 XML 配置中的<tx:annotation-driven/>
作用相同;
创建并配置数据源DataSource,用于建立与数据库的连接;创建JdbcTemplate实例,并注册到 Spring 容器中,@Resource(name = “dataSource”) 用于指定注入名为 dataSource 的 Bean 到方法参数 dataSource 中,该注解不仅可以作用在属性上,也可以以作用方法上;创建平台事务管理器PlatformTransactionManager,是 Spring 事务管理的核心组件。使用DataSourceTransactionManager(基于数据源的事务管理器),同样依赖dataSource,因为事务需要绑定数据库连接。
测试
import com.qcby.config.SpringConfig;
import com.qcby.service.AccountService;
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;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class Demo7 {// 注入要测试的Service@Autowiredprivate AccountService accountService;@Testpublic void testNormalPay() {accountService.pay("熊大", "熊二", 100);System.out.println("正常转账测试完成");}
}