1.数据源pom依赖spring-jdbc:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.7.RELEASE</version></dependency>
mysql5.7的话, 留神依赖的版本:
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.49</version></dependency>
2.dao层:
2.1 数据库表构造:
CREATE TABLE `t_user` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT NULL, `age` int(3) DEFAULT NULL, `gender` varchar(20) DEFAULT NULL, `is_active` tinyint(1) NOT NULL DEFAULT '1', PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
2.2 实体类 TUser.java
package com.niewj.bean;import lombok.Data;@Datapublic class TUser { private int id; private String name; private int age; private String gender ;}
2.3 数据拜访DAO:
TUserDao.java
package com.niewj.dao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Repository;import java.util.Random;import java.util.UUID;@Repository("userDao")public class TUserDao { @Autowired private JdbcTemplate jdbcTemplate; public int saveUser() { String name = UUID.randomUUID().toString().replaceAll("-",""); int age = new Random().nextInt(35); String gender = "male"; // 这里写了单引号会报错 String insertSql = "insert into t_user(name, age, gender) values(?, ?, ?)"; int updated = jdbcTemplate.update(insertSql, name, age, gender); // --------- doCalc(); return updated; } // 做一些运算, 有可能异样, 如除法 public void doCalc(){ int value = 20/0; }}
3.service层
TUserService.java
package com.niewj.service;import com.niewj.dao.TUserDao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;@Service("userService")public class TUserService { @Autowired private TUserDao userDao; @Transactional public void insertUser(){ userDao.saveUser(); }}
4.配置类:
4.1 依赖properties
db.properties:
dev.mysql.url = jdbc:mysql://127.0.0.1/devdev.mysql.username = niewjdev.mysql.password = 1234dev.mysql.validationQuery = SELECT 1dev.mysql.connectionProperties = useUnicode=true;characterEncoding=UTF8;rewriteBatchedStatements=true;socketTimeout=60000;autoReconnectForPools=true
4.2 注册spring的配置类:
TxConfig.java
package com.niewj.config;import com.alibaba.druid.pool.DruidDataSource;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.PropertySource;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.jdbc.datasource.DataSourceTransactionManager;import org.springframework.transaction.PlatformTransactionManager;import org.springframework.transaction.annotation.EnableTransactionManagement;import javax.sql.DataSource;@ComponentScan({"com.niewj.service", "com.niewj.dao"})@Configuration@EnableTransactionManagement@PropertySource("classpath:/db.properties")public class TxConfig { /** * dev 配置 */ @Value("${dev.mysql.url}") private String urlDev; @Value("${dev.mysql.username}") private String usernameDev; @Value("${dev.mysql.password}") private String passwordDev; @Value("${dev.mysql.connectionProperties}") private String connectionProperties; // 1. 注册 DataSource 数据源 @Bean public DataSource dataSource() { DruidDataSource ds = new DruidDataSource(); ds.setUrl(urlDev); ds.setUsername(usernameDev); ds.setPassword(passwordDev); ds.setValidationQuery("SELECT 1"); ds.setConnectionProperties(connectionProperties); System.out.println("初始化-dev-DataSource"); return ds; } /** * 2. 注册 JdbcTemplate 工具 * @param dataSource 容器会主动从其内找到bean注入 * @return */ @Bean public JdbcTemplate jdbcTemplate(DataSource dataSource){// return new JdbcTemplate(dataSource()); // 调用也能够, 不会反复创立 return new JdbcTemplate(dataSource); } /** * 3. 注册 事务管理器 PlatformTransactionManager(DataSourceTransactionManager) * 这里应用调用 dataSource()办法, 也能够写入参传入 * @return */ @Bean public PlatformTransactionManager transactionManager(){ return new DataSourceTransactionManager(dataSource()); }}
留神:
- 事务性能须要
事务管理器TransactionManager
, 事务管理器依赖数据源DataSource
; - Dao操作依赖
JdbcTemplate
, JdbcTemplate也依赖数据源DataSource
; - 注入@Bean依赖,能够通过参数, 也能够通过调用办法:
3.1: JdbcTemplate是通过
办法入参
指定依赖的数据源对象;3.2: PlatformTransactionManager是通过
办法调用
指定数据源对象;这两种形式都能够实现IOC容器从容器中自动检索注入依赖对象的性能;
留神这里的几个要点
@ComponentScan({"com.niewj.service", "com.niewj.dao"})
扫描须要注册到容器中的bean的地位;
@Configuration
申明以后类为配置类, 须要注册到spring上下文而后从新refresh加载上下文;
@EnableTransactionManagement
开启事务管理反对, 相当于xml的:
<tx:annotation-driven />
@PropertySource("classpath:/db.properties")
类中应用到的@Value属性定位的指标配置文件;
5. 测试用例入口:
package com.niewj;import com.niewj.config.TxConfig;import com.niewj.service.TUserService;import org.junit.Test;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import java.util.stream.Stream;/** * spring 申明式事务-测试 */public class TxTest { @Test public void testTx() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(TxConfig.class); // 打印spring容器中的 BeanDefinition Stream.of(ctx.getBeanDefinitionNames()).forEach(e -> System.out.println(e)); System.out.println("============================="); TUserService userService = ctx.getBean(TUserService.class); userService.insertUser(); ctx.close(); }}
output: 控制台输入:
留神须要的bean都被初始化了:
txConfiguserService
userDao
dataSource
jdbcTemplate
transactionManager
初始化-dev-DataSourceorg.springframework.context.annotation.internalConfigurationAnnotationProcessororg.springframework.context.annotation.internalAutowiredAnnotationProcessororg.springframework.context.annotation.internalCommonAnnotationProcessororg.springframework.context.event.internalEventListenerProcessororg.springframework.context.event.internalEventListenerFactorytxConfigbookServiceproductServiceuserServicebookDaouserDaoorg.springframework.transaction.annotation.ProxyTransactionManagementConfigurationorg.springframework.transaction.config.internalTransactionAdvisortransactionAttributeSourcetransactionInterceptororg.springframework.transaction.config.internalTransactionalEventListenerFactorydataSourcejdbcTemplatetransactionManagerorg.springframework.aop.config.internalAutoProxyCreator=============================七月 20, 2020 5:19:29 下午 com.alibaba.druid.support.logging.JakartaCommonsLoggingImpl info信息: {dataSource-1} initedMon Jul 20 17:19:29 CST 2020 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.java.lang.ArithmeticException: / by zero at com.niewj.dao.TUserDao.doCalc(TUserDao.java:33) at com.niewj.dao.TUserDao.saveUser(TUserDao.java:26) at com.niewj.service.TUserService.insertUser(TUserService.java:16) at com.niewj.service.TUserService$$FastClassBySpringCGLIB$$5996298d.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218).............
在操作遇到 除零异样时, 会发现mysql事务会回滚! over~