spring boot(学习笔记第九课)
- MyBatis多数据库配置,Spring Data JPA多数据库配置
学习内容:
- MyBatis多数据库配置
- Spring Data JPA多数据库配置
1. MyBatis多数据库配置
-
准备多个数据库,配置数据库连接信息。
#database spring.datasource.one.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.one.url=jdbc:mysql://127.0.0.1:3306/springboot spring.datasource.one.username=finlay spring.datasource.one.password=123456 spring.datasource.two.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.two.url=jdbc:postgresql://127.0.0.1:5432/springboot spring.datasource.two.username=finlay spring.datasource.two.password=123456
-
因为使用一个
Entity
类,所以在两个库里面加一个表book
。
-
需要将
MyBatis
的xml
文件加载,所以加入resources
。<build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> <resource> <directory>src/main/resources</directory> </resource> </resources> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
-
加入必要的依赖。
mybatis
的依赖。druild
的连接池依赖。postgreSQL
的依赖。mysql
的依赖。<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.9</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.9</version> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> <scope>runtime</scope> </dependency>
-
定义
DataSourceConfig
的@Configuration
的配置类,将application.properties
中定义的接续信息加载成bean
。@Configuration public class DataSourceConfig { @Bean(value = "dsOne") @ConfigurationProperties(value = "spring.datasource.one") DataSource dsOne() { return DruidDataSourceBuilder.create().build(); } @Bean(value = "dsTwo") @ConfigurationProperties(value = "spring.datasource.two") DataSource dsTwo() { return DruidDataSourceBuilder.create().build(); } }
-
分别定义两个
repository
下面的包,分别是datasource1
和datasource2
。因为需要将不同的数据库指定给不同的包。
-
在
datasource1
分别定义BookMapper1
和BookMapper1.xml
。同样定义BookMapper2
和BookMapper2.xml
在datasource2
中,和MyBatis
单数据库相同。BookMapper1.java
@Mapper public interface BookMapper1 { public List<Book> getAllBooks(); }
BookMapper1.xml
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.demo.repository.datasource1.BookMapper1"> <select id="getAllBooks" resultType="com.example.demo.entity.Book"> select * from book; </select> </mapper>
BookMapper2.java
* @Mapper public interface BookMapper2{ public List<Book> getAllBooks(); }
BookMapper2.xml
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.demo.repository.datasource2.BookMapper2"> <select id="getAllBooks" resultType="com.example.demo.entity.Book"> select * from book; </select> </mapper>
-
对
BookMapper1.java
进行配置,让其指向datasource1
。@Configuration @MapperScan(value = "com.example.demo.repository.datasource1", sqlSessionFactoryRef = "sqlSessionFactoryBean1") public class MyBatisConfigOne { @Autowired @Qualifier("dsOne") DataSource dsOne; @Bean public SqlSessionFactory sqlSessionFactoryBean1() throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dsOne); return sqlSessionFactoryBean.getObject(); } @Bean public SqlSessionTemplate sqlSessionTemplate1() throws Exception { return new SqlSessionTemplate(sqlSessionFactoryBean1()); } }
-
对
BookMapper2.java
进行配置,让其指向datasource2
。@Configuration @MapperScan(value = "com.example.demo.repository.datasource2", sqlSessionFactoryRef = "sqlSessionFactoryBean2") public class MyBatisConfigTwo { @Autowired @Qualifier("dsTwo") DataSource dsTwo; @Bean public SqlSessionFactory sqlSessionFactoryBean2() throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dsTwo); return sqlSessionFactoryBean.getObject(); } @Bean public SqlSessionTemplate sqlSessionTemplate2() throws Exception { return new SqlSessionTemplate(sqlSessionFactoryBean2()); } }
-
定义
controller
,使用BookMapper1
和BookMapper2
分别从两个数据库读出数据@GetMapping("/multidb") @ResponseBody public String multidb() { List<Book> book1 = bookMapper1.getAllBooks(); List<Book> book2 = bookMapper2.getAllBooks(); return book1.toString() + book2.toString(); }
11.访问https://localhost:8080/multidb
,会显示从两个数据库的数据。
2. Spring Data JPA多数据库配置
- 加入必要的
Spring Data JPA
依赖<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
- 在
application.properties
中加入Spring Data JAP
的配置。#database spring.datasource.one.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.one.url=jdbc:mysql://127.0.0.1:3306/springboot spring.datasource.one.username=finlay spring.datasource.one.password=123456 spring.datasource.two.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.two.url=jdbc:postgresql://127.0.0.1:5432/springboot spring.datasource.two.username=finlay spring.datasource.two.password=123456 spring.jpa.properties.hibernate.hbm2ddl.auto=update spring.jpa.properties.show-sql=true
hbm2ddl.auto=updatehbm2ddl.auto
表示没有表的场合,会建立表,但是如果表已经存在,数据不会清空。 - 创建
dataSource
的配置bean
。
*注意,务必在一个dataSource
*上增加@primary
注解。@Configuration public class DataSourceConfig { @Bean(value = "dsOne") @ConfigurationProperties(value = "spring.datasource.one") @Primary DataSource dsOne() { return DruidDataSourceBuilder.create().build(); } @Bean(value = "dsTwo") @ConfigurationProperties(value = "spring.datasource.two") DataSource dsTwo() { return DruidDataSourceBuilder.create().build(); } }
- 在
package com.example.demo.repository.jpa.datasource1;
中增加@Configration
,设定该package
下面的repository
都使用该dsOne
的数据库配置。
注意,entityManagerFactoryBeanOne
的上面增加@primary
注解。@Configuration @EnableTransactionManagement @EnableJpaRepositories(basePackages = "com.example.demo.repository.jpa.datasource1", entityManagerFactoryRef = "entityManagerFactoryBeanOne", transactionManagerRef = "platformTransactionManagerOne") public class JpaConfigOne { @Resource(name = "dsOne") public DataSource dsOne; @Autowired JpaProperties jpaProperties; @Bean @Primary public LocalContainerEntityManagerFactoryBean entityManagerFactoryBeanOne( EntityManagerFactoryBuilder builder ) { return builder.dataSource(dsOne).properties( jpaProperties.getProperties()) .packages("com.example.demo.entity") .persistenceUnit("pu2") .build(); } @Bean PlatformTransactionManager platformTransactionManagerOne( EntityManagerFactoryBuilder builder ) { LocalContainerEntityManagerFactoryBean factoryBeanOne = entityManagerFactoryBeanOne(builder); return new JpaTransactionManager(Objects.requireNonNull(factoryBeanOne.getObject())); } }
- 在
package com.example.demo.repository.jpa.datasource1
里面,定义UserDaoOne
。public interface UserDaoTwo extends JpaRepository<UserMaster,Integer> { }
- 在
package com.example.demo.repository.jpa.datasource1;
中增加@Configration
,设定该package
下面的repository
都使用该dsOne
的数据库配置。
注意,entityManagerFactoryBeanOne
的上面增加@primary
注解。@Configuration @EnableTransactionManagement @EnableJpaRepositories(basePackages = "com.example.demo.repository.jpa.datasource2", entityManagerFactoryRef = "entityManagerFactoryBeanTwo", transactionManagerRef = "platformTransactionManagerTwo") public class JpaConfigTwo { @Resource(name = "dsTwo") public DataSource dsTwo; @Autowired JpaProperties jpaProperties; @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactoryBeanTwo( EntityManagerFactoryBuilder builder ){ return builder.dataSource(dsTwo).properties( jpaProperties.getProperties()) .packages("com.example.demo.entity") .persistenceUnit("pu2") .build(); } @Bean PlatformTransactionManager platformTransactionManagerTwo( EntityManagerFactoryBuilder builder ){ LocalContainerEntityManagerFactoryBean factoryBeanTwo = entityManagerFactoryBeanTwo(builder); return new JpaTransactionManager(Objects.requireNonNull(factoryBeanTwo.getObject())); } }
- 在
package com.example.demo.repository.jpa.datasource2
里面,定义UserDaoTwo
。public interface UserDaoTwo extends JpaRepository<UserMaster,Integer> { }
- 定义
@Entity
类。@Entity(name = "user_master") @Data public class UserMaster { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private Integer age; private String name; private String gender; }
- 在
controller
中定义DAO
,进行测试。@Autowired UserDaoOne userDaoOne; @Autowired UserDaoTwo userDaoTwo; @GetMapping("/multidb_jpa") @ResponseBody public void multiDBJpa(){ UserMaster user = new UserMaster(); user.setAge(10); user.setGender("boy"); user.setName("allen"); userDaoOne.save(user); user.setName("finlay"); userDaoTwo.save(user); }
- 执行完
https://localhost:8080/multidb_jpa
之后两个数据库都会建立user_master
的表,数据会增加一条。