application.properties配置
#test01 datasource
spring.datasource.test1.driverClassName = com.mysql.jdbc.Driver
spring.datasource.test1.url = jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8
spring.datasource.test1.username = root
spring.datasource.test1.password = 123456
#test02 datasource
spring.datasource.test2.driverClassName = com.mysql.jdbc.Driver
spring.datasource.test2.url = jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8
spring.datasource.test2.username = root
spring.datasource.test2.password = 123456
jdbcUrl is required with driverClassName错误解决
spring.datasource.url
数据库的 JDBC URL。
spring.datasource.jdbc-url
用来重写自定义连接池
官方文档的解释是:
因为连接池的实际类型没有被公开,所以在您的自定义数据源的元数据中没有生成密钥,而且在IDE中没有完成(因为DataSource接口没有暴露属性)。另外,如果您碰巧在类路径上有Hikari,那么这个基本设置就不起作用了,因为Hikari没有url属性(但是确实有一个jdbcUrl属性)。在这种情况下,您必须重写您的配置如下:
#test01 datasource
spring.datasource.test1.driverClassName = com.mysql.jdbc.Driver
spring.datasource.test1.jdbc-url = jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.test1.username = root
spring.datasource.test1.password = 123456
#test02 datasource
spring.datasource.test2.driverClassName = com.mysql.jdbc.Driver
spring.datasource.test2.jdbc-url = jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.test2.username = root
spring.datasource.test2.password = 123456
配置两个数据源
package cn.com.javakf.datasource;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
@Configuration // 注册到springboot容器中
@MapperScan(basePackages = "cn.com.javakf.test1", sqlSessionFactoryRef = "test1SqlSessionFactory")
public class DataSource1Config {
/**
* 功能描述:(配置test1数据库)
*/
@Bean(name = "test1DataSource")
@ConfigurationProperties(prefix = "spring.datasource.test1")
@Primary // 默认数据源
public DataSource testDataSource() {
return DataSourceBuilder.create().build();
}
/**
* 功能描述:(test1 sql会话工厂)
*/
@Bean(name = "test1SqlSessionFactory")
@Primary
public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
// mybatis写配置文件
// bean.setMapperLocations(
// new
// PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/test1/*.xml"));
return bean.getObject();
}
/**
* 功能描述:(test1 事物管理)
*/
@Bean(name = "test1TransactionManager")
@Primary
public DataSourceTransactionManager testTransactionManager(@Qualifier("test1DataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "test1SqlSessionTemplate")
@Primary
public SqlSessionTemplate testSqlSessionTemplate(
@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
package cn.com.javakf.datasource;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
@Configuration // 注册到springboot容器中
@MapperScan(basePackages = "cn.com.javakf.test2", sqlSessionFactoryRef = "test2SqlSessionFactory")
public class DataSource2Config {
/**
* 功能描述:(配置test2数据库)
*/
@Bean(name = "test2DataSource")
@ConfigurationProperties(prefix = "spring.datasource.test2")
public DataSource testDataSource() {
return DataSourceBuilder.create().build();
}
/**
* 功能描述:(test2 sql会话工厂)
*/
@Bean(name = "test2SqlSessionFactory")
public SqlSessionFactory testSqlSessionFactory(@Qualifier("test2DataSource") DataSource dataSource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
// mybatis写配置文件
// bean.setMapperLocations(
// new
// PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/test2/*.xml"));
return bean.getObject();
}
/**
* 功能描述:(test2 事物管理)
*/
@Bean(name = "test2TransactionManager")
public DataSourceTransactionManager testTransactionManager(@Qualifier("test2DataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "test2SqlSessionTemplate")
public SqlSessionTemplate testSqlSessionTemplate(
@Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
Controller
@Controller
public class TestController {
@Autowired
private UserMapperTest1 userMapperTest1;
@Autowired
private UserMapperTest2 userMapperTest2;
@Autowired
private UserServiceTest1 userServiceTest1;
/**
* 多数据源
*
* @param name
* @param age
* @return
*/
@ResponseBody
@RequestMapping("/insertTest1")
public String insertTest1(String name, Integer age) {
userMapperTest1.insert(name, age);
return "success";
}
/**
* 多数据源
*
* @param name
* @param age
* @return
*/
@ResponseBody
@RequestMapping("/insertTest2")
public String insertTest2(String name, Integer age) {
userMapperTest2.insert(name, age);
return "success";
}
/**
* 测试事务
*
* @param name
* @param age
* @return
*/
@ResponseBody
@RequestMapping("/insertTest")
public String insertTest(String name, Integer age) {
userServiceTest1.insertTest1(name, age);
return "success";
}
}
Service
@Service
public class UserServiceTest1 {
@Autowired
private UserMapperTest1 userMapperTest1;
@Autowired
private UserMapperTest2 userMapperTest2;
@Autowired
private UserServiceTest2 userServiceTest2;
@Transactional
public String insertTest1(String name, Integer age) {
userMapperTest1.insert(name, age);
userMapperTest2.insert(name, age);// 不回滚
// userServiceTest2.insertTest2(name, age);// 不回滚
int i = 1 / 0;
System.out.println(i);
return "success";
}
}
@Service
public class UserServiceTest2 {
@Autowired
private UserMapperTest2 userMapperTest2;
@Transactional
public String insertTest2(String name, Integer age) {
userMapperTest2.insert(name, age);
int i = 1 / 0;
System.out.println(i);
return "success";
}
}
Dao
public interface UserMapperTest1 {
@Insert("INSERT INTO USERS(NAME, AGE) VALUES(#{name}, #{age})")
int insert(@Param("name") String name, @Param("age") Integer age);
}
public interface UserMapperTest2 {
@Insert("INSERT INTO USERS(NAME, AGE) VALUES(#{name}, #{age})")
int insert(@Param("name") String name, @Param("age") Integer age);
}
项目结构
测试:数据源1,2能分别插入数据管理事务。数据源1数据源2存在调用关系时,不能保证事务一致性,不推荐使用。
下一节介绍分布式事物管理