前言:
使用2个数据库,数据库A:phm 数据库B:mcs 。
在项目中主要使用hibernate实现全自动ORM,但是在复杂的业务中,需要使用mybatis来实现业务需求。
一、入门
1、添加依赖
<!-- 整合mybatis --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.1.1</version></dependency><!-- JPA 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency>
1、多数据源配置
spring:#druid多数据源配置datasource:health:#健康管理数据库配置username: rootpassword: rootjdbc-url: jdbc:mysql://localhost:3306/PHM724?serverTimezone=UTC&useSSL=falsedriver-class-name: com.mysql.cj.jdbc.Drivermcs:#状态数据库配置username: rootpassword: rootjdbc-url: jdbc:mysql://localhost:3306/PHM724DB?serverTimezone=UTC&useSSL=falsedriver-class-name: com.mysql.cj.jdbc.Driver
#mybatis配置
mybatis:mapper-locations: classpath:/mapper/phm/*.xml,classpath:/mapper/mcs/*.xml configuration:map-underscore-to-camel-case: true #开启驼峰映射
2、创建配置类来配置多个数据源
通过NamedParameterJdbcTemplate 对JdbcTemplate的扩展
/*** @Author:suntingting* @Date:2023/7/31 17:01* @Desc: 创建一个配置类来配置多个数据源* @Filename:DataSourceConfig*/
@Configuration
public class DataSourceConfig {@Bean(name = "healthDataSource")@Qualifier("healthDataSource")@ConfigurationProperties(prefix = "spring.datasource.health")//来设置每个数据源的配置参数,来自于yml@Primary //设置主要数据源public DataSource healthDataSource() {return DataSourceBuilder.create().build();}@Bean(name = "mcsDataSource")@Qualifier("mcsDataSource")@ConfigurationProperties(prefix = "spring.datasource.mcs") //来设置每个数据源的配置参数,来自于ymlpublic DataSource mcsDataSource() {return DataSourceBuilder.create().build();}/*** 可以方便地替代JdbcTemplate,用于执行带有命名参数的SQL语句。* NamedParameterJdbcTemplate是对JdbcTemplate的扩展,* 它允许我们使用命名参数而不是?占位符来设置SQL语句的参数。* 使用命名参数可以使SQL语句更加易读和易于维护,而不需要关注参数的位置。* @param dataSource* @return*/@Bean(name = "healthJdbcTemplate")@Qualifier("healthJdbcTemplate")@Primarypublic NamedParameterJdbcTemplate healthJdbcTemplate(@Qualifier("healthDataSource") DataSource dataSource) {return new NamedParameterJdbcTemplate(dataSource);}@Bean(name = "mcsJdbcTemplate")@Qualifier("mcsJdbcTemplate")public NamedParameterJdbcTemplate mcsJdbcTemplate(@Qualifier("mcsDataSource") DataSource dataSource) {return new NamedParameterJdbcTemplate(dataSource);}}
3、mybatis集成配置
/*** @Author:suntingting* @Date:2023/7/31 17:01* @Desc: 配置 MyBatis 的health数据源 和 SqlSessionFactory* @Filename:HealthDBConfig*/
@Configuration
@MapperScan(basePackages = {"com.sinux.health.system.dao.phmDao.mapper"}, sqlSessionTemplateRef = "healthSqlSessionTemplate")
public class HealthDBConfig {@Autowired@Qualifier("healthDataSource")private DataSource healthDataSource;@Bean(name = "healthSessionFactory")public SqlSessionFactory healthSessionFactory() throws Exception{SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();factoryBean.setDataSource(healthDataSource);Resource[] mapperLocations = new PathMatchingResourcePatternResolver().getResources("classpath:mapper/phm/*.xml");// 配置 MyBatis Mapper 扫描路径factoryBean.setMapperLocations(mapperLocations);//用于设置MyBatis的配置文件的位置factoryBean.setConfigLocation(new PathMatchingResourcePatternResolver().getResource("classpath:config/phmDB/mybatis-config.xml"));return factoryBean.getObject();}@Bean(name = "healthTransactionManager")public DataSourceTransactionManager healthDataSourceTransactionManager(@Qualifier("healthDataSource") DataSource dataSource){return new DataSourceTransactionManager(dataSource);}@Bean(name="healthSqlSession")public SqlSession healthSqlSession(@Qualifier("healthSessionFactory")SqlSessionFactory sqlSessionFactory){return sqlSessionFactory.openSession();}@Bean(name = "healthSqlSessionTemplate")public SqlSessionTemplate healthSqlSessionTemplate( @Qualifier("healthSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception{SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory);return template;}}
/*** @Author:suntingting* @Date:2023/7/31 17:01* @Desc: 数据库 MSC 的配置* @Filename:MCSDBConfig*/
@Configuration
@MapperScan(basePackages = {"com.sinux.health.system.dao.mcsDao.mapper"}, sqlSessionTemplateRef = "mcsSqlSessionTemplate")
public class MCSDBConfig {@Autowired@Qualifier("mcsDataSource")private DataSource mcsDataSource;@Bean(name = "mcsSessionFactory")public SqlSessionFactory mcsSessionFactory() throws Exception{SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();factoryBean.setDataSource(mcsDataSource);Resource[] mapperLocations = new PathMatchingResourcePatternResolver().getResources("classpath:mapper/mcs/*.xml");factoryBean.setMapperLocations(mapperLocations);factoryBean.setConfigLocation(new PathMatchingResourcePatternResolver().getResource("classpath:config/mcsDB/mybatis-config.xml"));return factoryBean.getObject();}@Bean(name = "mcsTransactionManager")public DataSourceTransactionManager mcsDataSourceTransactionManager(@Qualifier("mcsDataSource") DataSource dataSource){return new DataSourceTransactionManager(dataSource);}@Bean(name="mcsSqlSession")public SqlSession mcsSqlSession(@Qualifier("mcsSessionFactory")SqlSessionFactory sqlSessionFactory){return sqlSessionFactory.openSession();}@Bean(name = "mcsSqlSessionTemplate")public SqlSessionTemplate mcsSqlSessionTemplate() throws Exception{SqlSessionTemplate template = new SqlSessionTemplate(mcsSessionFactory());return template;}}
4、jpa配置
/**** @Author:suntingting* @Date:2023/8/1 15:01* @Desc: 数据源1 health 配置类* 配置对应的映射类和repository、或者mapper和mappper.xml的完整路径* 如何取连接数据库* 配置实体扫描以及事务管理* @Filename:HealthDBJPAConfig*/
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = {"com.sinux.health.system.dao.phmDao.jpa"},entityManagerFactoryRef = "entityManagerFactoryHealth",transactionManagerRef = "transactionManagerHealth")
public class HealthDBJPAConfig {@Autowired@Qualifier("healthDataSource")private DataSource healthDataSource; //health数据源注入@Resourceprivate JpaProperties jpaProperties;@Resourceprivate HibernateProperties hibernateProperties;/*** EntityManagerFactory类似于Hibernate的SessionFactory,mybatis的SqlSessionFactory* 总之,在执行操作之前,我们总要获取一个EntityManager,这就类似于Hibernate的Session,* mybatis的sqlSession.* @param builder* @return*/@Bean(name = "entityManagerHealth")@Primarypublic EntityManager entityManagerHealth(EntityManagerFactoryBuilder builder) {
// return entityManagerFactoryHealth(builder).getObject().createEntityManager();return SharedEntityManagerCreator.createSharedEntityManager(entityManagerFactoryHealth(builder).getObject());}@Bean(name = "entityManagerFactoryHealth") //实体工厂@Primarypublic LocalContainerEntityManagerFactoryBean entityManagerFactoryHealth(EntityManagerFactoryBuilder builder) {Map<String, Object> properties = hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = builder.dataSource(healthDataSource).properties(properties).packages("com.sinux.health.system.domain.phmDB") // JPA 实体类所在的包路径.persistenceUnit("healthPersistenceUnit").build();return entityManagerFactoryBean;}/*** 配置事物管理器* @param builder* @return*/@Bean(name = "transactionManagerHealth")@Primarypublic PlatformTransactionManager transactionManagerHealth(EntityManagerFactoryBuilder builder) {return new JpaTransactionManager(entityManagerFactoryHealth(builder).getObject());}}
**** @Author:suntingting* @Date:2023/8/1 15:01* @Desc: 数据源1 mcs 配置类* 配置对应的映射类和repository、或者mapper和mappper.xml的完整路径* @Filename:MCSDBJPAConfig*/
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = {"com.sinux.health.system.dao.mcsDao.jpa"}, //这个数据源对应的repositoryentityManagerFactoryRef = "entityManagerFactoryMcs",transactionManagerRef = "transactionManagerMcs")
public class MCSDBJPAConfig {@Autowired@Qualifier("mcsDataSource") //value要和DataSourceConfig的值一致private DataSource mcsDataSource;@Autowiredprivate JpaProperties jpaProperties;@Autowiredprivate HibernateProperties hibernateProperties;@Bean(name = "entityManagerMcs")public EntityManager entityManagerMcs(EntityManagerFactoryBuilder builder) {
// return entityManagerFactoryMcs(builder).getObject().createEntityManager();//Mark 必须用SharedEntityManagerCreator,不然会报懒加载异常return SharedEntityManagerCreator.createSharedEntityManager(entityManagerFactoryMcs(builder).getObject());}@Bean(name = "entityManagerFactoryMcs")public LocalContainerEntityManagerFactoryBean entityManagerFactoryMcs(EntityManagerFactoryBuilder builder) {Map<String, Object> properties = hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = builder.dataSource(mcsDataSource).properties(properties).packages("com.sinux.health.system.domain.mcsDB") //设置实体类所在位置.persistenceUnit("mcsPersistenceUnit").build();return entityManagerFactoryBean;}@Bean(name = "transactionManagerMcs")public PlatformTransactionManager transactionManagerMcs(EntityManagerFactoryBuilder builder) {return new JpaTransactionManager(entityManagerFactoryMcs(builder).getObject());}}
二、遇到的问题
问题1:
No MyBatis mapper was found in '[com.sinux.health.system.dao.mcsDao.mapper]' package. Please check your configuration.
原因:配置了XML ,但是dao里面没有添加文件
问题2:
The bean 'userDao', defined in com.sinux.health.system.dao.phmDao.mapper.UserDao defined in @EnableJpaRepositories declared on HealthDBJPAConfig, could not be registered. A bean with that name has already been defined in file [D:\sinux_2023\project\phm\724_3\code\PHMServer\target\classes\com\sinux\health\system\dao\phmDao\mapper\UserDao.class] and overriding is disabled.
原因:重复注入了bean
问题3:
Caused by: java.lang.IllegalStateException: Cannot convert value of type 'org.mybatis.spring.SqlSessionTemplate' to required type 'org.apache.ibatis.session.SqlSessionFactory' for property 'sqlSessionFactory': no matching editors or conversion strategy found
原因:配置文件有错误
问题4:如果报某个Bean找不到
原因:你需要在resource中的mapper中添加xml文件