同一个项目有时会涉及到多个数据库,这时我们就要配置多个数据源。配置多数据源的常见情况有以下两种:
1)同一个项目中涉及两个或多个业务数据库,它们之间相互独立,这种情况也可以作为两个或多个项目来开发
2)两个或多个数据库之间是主从关系,主库负责写,从库负责读
下面我们通过一个示例来说明多数据源的配置
1、配置文件配置
在配置文件application-dev.yml中配置我们需要链接的数据库:blog和user
spring:
datasource:
blog:
jdbc-url: jdbc:mysql://localhost:3306/blog
username: root
password: test
driver-class-name: com.mysql.cj.jdbc.Driver
user:
jdbc-url: jdbc:mysql://localhost:3306/user
username: root
password: test
driver-class-name: com.mysql.cj.jdbc.Driver
注意:
1)我们在spring.datasource之后多设置了一个数据源名称blog和user来区分不同的数据源配置
2)如果报下面错误,则把url改为jdbc-url即可
nested exception is java.lang.IllegalArgumentException: jdbcUrl is required with driverClassName.
3)com.mysql.jdbc.Driver 与 com.mysql.cj.jdbc.Driver 的区别
com.mysql.jdbc.Driver 是 mysql-connector-java 5中的
com.mysql.cj.jdbc.Driver 是 mysql-connector-java 6中的
2、数据源配置
配置文件配置好之后,我们创建两个配置类来加载配置信息,初始化数据源
blog的配置类:
@Configuration
@MapperScan(basePackages = "com.tn666.demo.dao.blog", sqlSessionTemplateRef = "blogSqlSessionTemplate")
public class DataSourceBlogConfig {
@Primary
@Bean(name = "blogDataSource")
@ConfigurationProperties(prefix = "spring.datasource.blog")
public DataSource blogDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "blogSqlSessionFactory")
public SqlSessionFactory blogSqlSessionFactory(@Qualifier("blogDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
return bean.getObject();
}
@Bean(name = "blogSqlSessionTemplate")
public SqlSessionTemplate blogSqlSessionTemplate(@Qualifier("blogSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
User的配置类:
@Configuration
@MapperScan(basePackages = "com.tn666.demo.dao.user", sqlSessionTemplateRef = "userSqlSessionTemplate")
public class DataSourceUserConfig {
@Bean(name = "userDataSource")
@ConfigurationProperties(prefix = "spring.datasource.user")
public DataSource userDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "userSqlSessionFactory")
public SqlSessionFactory userSqlSessionFactory(@Qualifier("userDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
return bean.getObject();
}
@Bean(name = "userSqlSessionTemplate")
public SqlSessionTemplate userSqlSessionTemplate(@Qualifier("userSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
注意:
1)类注解@MapperScan的属性basePackages配置的为对应DA层dao的位置
2)@Primary注解指定了主数据源
3、实体类和dao层配置
在blog数据库中,创建一个article表,在user数据库中创建一个user_info表,然后创建它们的实体类和dao层
创建article和user_info的实体类:
public class ArticlePo {
private Integer id;
private String articleId;
private String title;
// get、set...
}
public class UserInfoPo {
private Integer id;
private String userId;
private String name;
// get、set...
}
创建article和user_info的dao层:
@Repository
public interface ArticleDao {
@Select("select * from article where article_id = #{articleId}")
@Results({@Result(column = "article_id", property = "articleId")})
ArticlePo get(@Param("articleId") String articleId);
// 给article赋值自增主键id
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
@Insert("insert into article(article_id, title) values(#{article.articleId}, #{article.title})")
int insert(@Param("article") ArticlePo articlePo);
}
@Repository
public interface UserInfoDao {
@Select("select * from user_info where user_id=#{userId}")
@Results({@Result(column = "user_id", property = "userId")})
UserInfoPo get(@Param("userId") String userId);
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
@Insert("insert into user_info(user_id, name) values(#{userInfo.userId}, #{userInfo.name})")
int insert(@Param("userInfo") UserInfoPo userInfoPo);
}
4、测试验证
编写ArticleController和UserInfoController:
@RestController
@RequestMapping("/article")
public class ArticleController {
@Resource
private ArticleDao articleDao;
@GetMapping(value = "/get")
public ArticlePo get(@RequestParam("articleId") String articleId) {
ArticlePo articlePo = articleDao.get(articleId);
return articlePo;
}
@PostMapping(value = "/insert")
public Boolean insert(@RequestBody ArticlePo articlePo) {
articleDao.insert(articlePo);
Boolean res = false;
if (articlePo.getId() > 0) {
res = true;
}
return res;
}
}
@RestController
@RequestMapping("/user")
public class UserInfoController {
@Resource
private UserInfoDao userInfoDao;
@GetMapping(value = "/get")
public UserInfoPo get(@RequestParam("userId") String userId) {
UserInfoPo res = userInfoDao.get(userId);
return res;
}
@PostMapping(value = "/insert")
public Boolean insert(@RequestBody UserInfoPo userInfoPo) {
userInfoDao.insert(userInfoPo);
Boolean res = false;
if (userInfoPo.getId() > 0) {
res = true;
}
return res;
}
}
业务逻辑复杂时,Controller和Mapper中间会有Service层来处理业务逻辑,现在我们就简单的测试一下多数据源,所以直接使用Controller调用Mapper了
更多内容,请关注公众号图南随笔: