刚更新了一篇SpringBoot整合mybatis。突然想mybatis虽然功能强大,但是对sql的要求还是算高的。Spring Data Jpa对于某些用户来说 ,还是个比较简单的选择。毕竟不用写较复杂的sql语句,于是就想,来一个SpringBoot+mybatis + jpa的大杂烩。
说到底,多数据源整合其实就是要保证项目中有且仅有一个primaryDataSource,即主数据源,它是无可替代的。
先看application.yml 有多少个数据源就的配置多少个数据库链接
spring:
## multipart datasource configuration ##
datasource:
primary:
jdbc-url: jdbc:mysql://localhost:3306/javashop
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
secondary:
jdbc-url: jdbc:mysql://localhost:3306/test
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
master:
jdbc-url: jdbc:mysql://localhost:3306/javashop
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
cluster:
jdbc-url: jdbc:mysql://localhost:3306/test
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
jpa:
hibernate:
ddl-auto: update
naming:
physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
show-sql: true
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
项目结构图
└─src
├─main
│ ├─java
│ │ └─com
│ │ └─developlee
│ │ └─multipartdatasource
│ │ │ MultipartDatasourceApplication.java
│ │ │
│ │ ├─config
│ │ │ ├─jpa
│ │ │ │ DataSourceConfig.java
│ │ │ │ PrimaryDataSourceConfig.java
│ │ │ │ SecondaryDataSourceConfig.java
│ │ │ │
│ │ │ └─mybatis
│ │ │ ClusterDataSourceConfig.java
│ │ │ MasterDataSourceConfig.java
│ │ │
│ │ ├─dao
│ │ │ ├─jpa
│ │ │ │ ├─primary
│ │ │ │ │ UserRepository.java
│ │ │ │ │
│ │ │ │ └─secondary
│ │ │ │ CityRepository.java
│ │ │ │
│ │ │ └─mybatis
│ │ │ ├─cluster
│ │ │ │ CityDao.java
│ │ │ │
│ │ │ └─master
│ │ │ UserDao.java
│ │ │
│ │ ├─entity
│ │ │ ├─jpa
│ │ │ │ ├─primary
│ │ │ │ │ UserEntity.java
│ │ │ │ │
│ │ │ │ └─secondary
│ │ │ │ CityEntity.java
│ │ │ │
│ │ │ └─mybatis
│ │ │ ├─cluster
│ │ │ │ MybatisCityEntity.java
│ │ │ │
│ │ │ └─master
│ │ │ MybatisUserEntity.java
│ │ │
│ │ └─service
│ │ │ CityService.java
│ │ │ UserService.java
│ │ │
│ │ └─impl
│ │ CityServiceImpl.java
│ │ UserServiceImpl.java
│ │
│ └─resources
│ │ application.yml
│ │
│ ├─mapper
│ │ ├─cluster
│ │ │ city.xml
│ │ │
│ │ └─master
│ │ user.xml
│ │
│ ├─static
│ └─templates
└─test
└─java
└─com
└─developlee
└─multipartdatasource
MultipartDatasourceApplicationTests.java
从文件树可以看到,对每个数据源要操作的实体类和数据接口都进行隔离。
jpa数据源配置
@Configuration
public class DataSourceConfig {
@Bean(name = "primaryDataSource")
@Qualifier("primaryDataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondaryDataSource")
@Qualifier("secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
}
JPA-primary主数据源配置
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "primaryEntityManagerFactory",
transactionManagerRef = "primaryTransactionManager",
basePackages = { PrimaryDataSourceConfig.REPO_PACKAGE } // 设置 Repository 所在位置
)
public class PrimaryDataSourceConfig {
static final String REPO_PACKAGE = "com.developlee.multipartdatasource.dao.jpa.primary";
static final String ENTITY_PACKAGE = "com.developlee.multipartdatasource.entity.jpa.primary";
@Resource
@Qualifier("primaryDataSource")
private DataSource primaryDataSource;
@Resource
private JpaProperties jpaProperties;
@Primary
@Bean(name = "primaryEntityManager")
public EntityManager primaryEntityManager(EntityManagerFactoryBuilder builder) {
return primaryEntityManagerFactory(builder).getObject().createEntityManager();
}
@Primary
@Bean(name = "primaryEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(EntityManagerFactoryBuilder builder) {
return builder.dataSource(primaryDataSource)
.properties(jpaProperties.getHibernateProperties(new HibernateSettings()))
.persistenceUnit("primaryPersistenceUnit")
.packages(ENTITY_PACKAGE)
.build();
}
@Primary
@Bean(name = "primaryTransactionManager")
public PlatformTransactionManager primaryTransactionManager(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(primaryEntityManagerFactory(builder).getObject());
}
}
jpa-secondary的从数据源与此类似。
mybatis-master数据源配置
@Configuration
@MapperScan(basePackages = MasterDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "masterSqlSessionFactory")
public class MasterDataSourceConfig {
// 精确到master目录和其他数据源隔离
static final String PACKAGE = "com.developlee.multipartdatasource.dao.mybatis.master";
static final String MAPPER_LOCATION = "classpath:mapper/master/*.xml";
@Value("${spring.datasource.master.jdbc-url}")
private String url;
@Value("${spring.datasource.master.username}")
private String user;
@Value("${spring.datasource.master.password}")
private String password;
@Value("${spring.datasource.master.driver-class-name}")
private String driverClass;
@Bean(name = "masterDataSource")
public DataSource masterDataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driverClass);
dataSource.setUrl(url);
dataSource.setUsername(user);
dataSource.setPassword(password);
return dataSource;
}
@Bean(name = "masterTransactionManager")
@Primary
public DataSourceTransactionManager masterTransactionManager() {
return new DataSourceTransactionManager(masterDataSource());
}
@Bean(name = "masterSqlSessionFactory")
@Primary
public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource masterDataSource)
throws Exception {
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(masterDataSource);
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources(MasterDataSourceConfig.MAPPER_LOCATION));
return sessionFactory.getObject();
}
}
mybatis-cluster数据源配置与此类似。
测试
说明下,业务逻辑代码就不贴了,可在我的github中找到。
@RunWith(SpringRunner.class)
@SpringBootTest
public class MultipartDatasourceApplicationTests {
@Autowired
UserServiceImpl userService;
@Autowired
CityServiceImpl cityService;
@Test
public void contextLoads() {
UserEntity userEntity = new UserEntity();
userEntity.setUsername("JPA-Lensen");
userEntity.setPwd("123456");
userEntity.setMobile("137****8661");
CityEntity cityEntity = new CityEntity();
cityEntity.setUserId(1024L);
cityEntity.setDescription("JPA-Lensen-Desc");
MybatisUserEntity mybatisUserEntity = new MybatisUserEntity();
mybatisUserEntity.setUsername("Mybatis-Lensen");
mybatisUserEntity.setPwd("654321");
mybatisUserEntity.setMobile("137****1024");
MybatisCityEntity mybatisCityEntity = new MybatisCityEntity();
mybatisCityEntity.setDesc("MyBatis-Lensen-Desc");
mybatisCityEntity.setUserId(2048L);
mybatisCityEntity.setId(10L);
userService.saveUserByJpa(userEntity);
cityService.saveCityByJpa(cityEntity);
userService.saveUserByMybatis(mybatisUserEntity);
cityService.saveCityByMybatis(mybatisCityEntity);
}
}
截图看看效果
看看数据库的数据
tb_user表
tb_city表
最后: 此项目代码可在我的github.com中找到。
我的个人公众号:developlee的潇洒人生。
关注了也不一定更新,更新就不得了了。