刚更新了一篇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数据源配置
@Configurationpublic 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)@SpringBootTestpublic 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表 最后: 此项目代码可在我的中找到。 我的个人公众号:developlee的潇洒人生。 关注了也不一定更新,更新就不得了了。