当前位置: 首页 > news >正文

Spring Boot 3 + JPA多模块系统对MySQL和DORIS进行多数据源集成实战(荣耀典藏版)

前言大家好我是月夜枫没错这个不是凑数的。背景最近公司要求系统内使用DORIS做数据分析同时需要保留原来MySQL部分因此需要从配置上对多数据源进行集成。主模块配置spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://ip:port/database username: username password: password type: com.alibaba.druid.pool.DruidDataSource druid: # https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter # 连接池的配置信息 # 初始化大小最小最大 initial-size: 2 min-idle: 2 # 最大连接数建议 CPU核核数 * 2 1 max-active: 5 validation-query: SELECT 1 FROM DUAL validation-query-timeout: 1 # 设置从连接池获取连接时是否检查连接有效性true时如果连接空闲时间超过manEvictableIdleTimeMillis进行检查否则不检查;false时不检查 test-while-idle: true # 指明是否在从池中取出连接时进行检查,每次都检查 validation-query 不能为空 test-on-borrow: false # 指明是否在归还到池中前进行检查 test-on-return: false # 打开后增强timeBetweenEvictionRunsMillis的周期性连接检查minIdle内的空闲连接每次检查强制验证连接有效性. 参考https://github.com/alibaba/druid/wiki/KeepAlive_cn keep-alive: true # 打开PSCacheOracle等支持游标的数据库打开此开关会以数量级提升性能具体查阅PSCache相关资料 pool-prepared-statements: true # 指定每个连接上PSCache的大小 max-pool-prepared-statement-per-connection-size: 20 #filters: stat,wall,slf4j #配置监控统计拦截的filters去掉后监控界面sql无法统计wall用于防火墙 filters: stat,slf4j # 配置DruidStatFilter web-stat-filter: enabled: true url-pattern: /druid/* exclusions: /druid/*,*.html,*.htm,*.js,*.css,*.gif,*.jpg,*.bmp,*.png,*.ico,*.svg,*.ttf,*.woff,*.woff2 # 配置 DruidStatViewServlet stat-view-servlet: enabled: true url-pattern: /druid/* # 禁用HTML页面上的“Reset All”功能 reset-enable: false # 登录名 login-username: druid # 登录密码 login-password: druid filter: # 数据库监控统计 StatFilter stat: # 记录慢 sql 配置 enabled: true db-type: mysql log-slow-sql: true merge-sql: true # 慢 sql 标准 slow-sql-millis: 5000 # 防火墙防 sql 注入 wall: db-type: mysql slf4j: enabled: true >if (StringUtils.hasText(ddlAuto) !none.equals(ddlAuto)) { result.put(hibernate.hbm2ddl.auto, ddlAuto); } else { result.remove(hibernate.hbm2ddl.auto); }在org.springframework.boot.autoconfigure.orm.jpa包下的HibernateProperties中determineHibernateProperties方法内有上述逻辑判断当ddl-auto设置为none时Hibernate不会再对表结构做处理。import com.querydsl.jpa.impl.JPAQueryFactory; import jakarta.annotation.Resource; import jakarta.persistence.EntityManager; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties; import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings; import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.SharedEntityManagerCreator; import org.springframework.transaction.PlatformTransactionManager; import javax.sql.DataSource; import java.util.Map; import java.util.Objects; Configuration EnableJpaRepositories(basePackages com.mysqlPackages.**.dao.jpa, entityManagerFactoryRef mySQLEntityManagerFactory, transactionManagerRef mySQLTransactionManager) public class MySQLConfiguration { Resource private JpaProperties jpaProperties; Resource private HibernateProperties hibernateProperties; Bean Primary ConfigurationProperties(spring.datasource) public DataSourceProperties mySQLDataSourceProperties() { return new DataSourceProperties(); } Bean Primary ConfigurationProperties(spring.datasource) public DataSource mySQLDataSource() { return mySQLDataSourceProperties().initializeDataSourceBuilder().build(); } Bean Primary public LocalContainerEntityManagerFactoryBean mySQLEntityManagerFactory(EntityManagerFactoryBuilder builder) { MapString, Object properties hibernateProperties.determineHibernateProperties( this.jpaProperties.getProperties(), new HibernateSettings() ); return builder .dataSource(mySQLDataSource()) .packages(com.mysqlPackages.**.entity, com.core.**)//可配置多个扫描路径包括Entity和Converter等类的扫描 .properties(properties) .persistenceUnit(mySQLPersistenceUnit) .build(); } Bean Primary public PlatformTransactionManager mySQLTransactionManager(EntityManagerFactoryBuilder builder) { JpaTransactionManager transactionManager new JpaTransactionManager(); transactionManager.setEntityManagerFactory(mySQLEntityManagerFactory(builder).getObject()); return transactionManager; } Bean public EntityManager mySQLEntityManager(EntityManagerFactoryBuilder builder) { return SharedEntityManagerCreator.createSharedEntityManager(Objects.requireNonNull(mySQLEntityManagerFactory(builder).getObject())); } Bean public JPAQueryFactory jpaQueryFactory(EntityManagerFactoryBuilder builder) { return new JPAQueryFactory(mySQLEntityManager(builder)); } }配置类中首先注意通过EnableJpaRepositories配置扫描dao包路径要与DORIS的路径做区分避免同时加载到容器中。添加了注解Primary标注作为最高优先级的bean该注解是Spring Boot 3引入的。引入了DataSourceProperties在源码上它默认获取的是spring.datasource下的配置因此实际ConfigurationProperties注解是不需要进行标注的这里是为了提供代码可读性依旧标注在配置bean上ConfigurationProperties( prefix spring.datasource ) public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean { // 内容 }同样的在org.springframework.boot.autoconfigure.orm.jpa包下JPA的配置引入也是有源码支持的ConfigurationProperties( prefix spring.jpa ) public class JpaProperties { // 内容 }EntityManagerFactory的properties将JPA和Hibernate的配置通过HibernateProperties的determineHibernateProperties方法注入到Map中。由之前提到的HibernateProperties源码可知假设需要在配置类中的properties内单独加入ddl-auto的配置在目前的版本就不能使用spring.jpa.hibernate.ddl-auto而应该使用hibernate.hbm2ddl.auto。DORIS模块配置spring: datasource: doris: driverClassName: com.mysql.cj.jdbc.Driver url: jdbc:mysql://ip:port/database username: username password: password type: com.alibaba.druid.pool.DruidDataSource druid: # https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter # 连接池的配置信息 # 初始化大小最小最大 initial-size: 2 min-idle: 2 # 最大连接数建议 CPU核核数 * 2 1 max-active: 5 validation-query: SELECT 1 FROM DUAL validation-query-timeout: 1 # 设置从连接池获取连接时是否检查连接有效性true时如果连接空闲时间超过manEvictableIdleTimeMillis进行检查否则不检查;false时不检查 test-while-idle: true # 指明是否在从池中取出连接时进行检查,每次都检查 validation-query 不能为空 test-on-borrow: false # 指明是否在归还到池中前进行检查 test-on-return: false # 打开后增强timeBetweenEvictionRunsMillis的周期性连接检查minIdle内的空闲连接每次检查强制验证连接有效性. 参考https://github.com/alibaba/druid/wiki/KeepAlive_cn keep-alive: true # 打开PSCacheOracle等支持游标的数据库打开此开关会以数量级提升性能具体查阅PSCache相关资料 pool-prepared-statements: true # 指定每个连接上PSCache的大小 max-pool-prepared-statement-per-connection-size: 20 #filters: stat,wall,slf4j #配置监控统计拦截的filters去掉后监控界面sql无法统计wall用于防火墙 filters: stat,slf4j # 配置DruidStatFilter web-stat-filter: enabled: true url-pattern: /druid/* exclusions: /druid/*,*.html,*.htm,*.js,*.css,*.gif,*.jpg,*.bmp,*.png,*.ico,*.svg,*.ttf,*.woff,*.woff2 # 配置 DruidStatViewServlet stat-view-servlet: enabled: true url-pattern: /druid/* # 禁用HTML页面上的“Reset All”功能 reset-enable: false # 登录名 login-username: druid # 登录密码 login-password: druid filter: # 数据库监控统计 StatFilter stat: # 记录慢 sql 配置 enabled: true db-type: mysql log-slow-sql: true merge-sql: true # 慢 sql 标准 slow-sql-millis: 5000 # 防火墙防 sql 注入 wall: db-type: mysql slf4j: enabled: true >import com.querydsl.jpa.impl.JPAQueryFactory; import jakarta.annotation.Resource; import jakarta.persistence.EntityManager; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties; import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings; import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.SharedEntityManagerCreator; import org.springframework.transaction.PlatformTransactionManager; import javax.sql.DataSource; import java.util.Map; import java.util.Objects; Configuration EnableJpaRepositories(basePackages com.dorisPackadges.**.dao.jpa, entityManagerFactoryRef dorisEntityManagerFactory, transactionManagerRef dorisTransactionManager) public class DorisConfiguration { Resource private JpaProperties jpaProperties; Resource private HibernateProperties hibernateProperties; Bean ConfigurationProperties(spring.datasource.doris) public DataSourceProperties dorisDataSourceProperties() { return new DataSourceProperties(); } Bean ConfigurationProperties(spring.datasource.doris) public DataSource dorisDataSource() { return dorisDataSourceProperties().initializeDataSourceBuilder().build(); } Bean public LocalContainerEntityManagerFactoryBean dorisEntityManagerFactory(EntityManagerFactoryBuilder builder) { MapString, Object properties hibernateProperties.determineHibernateProperties( this.jpaProperties.getProperties(), new HibernateSettings() ); LocalContainerEntityManagerFactoryBean entityManagerFactoryBean builder .dataSource(dorisDataSource()) .properties(properties) .packages(com.dorisPackadges.entity.doris, com.core.**)//可配置多个扫描路径包括Entity和Converter等类的扫描 .persistenceUnit(dorisPersistenceUnit) .build(); return entityManagerFactoryBean; } Bean public PlatformTransactionManager dorisTransactionManager(EntityManagerFactoryBuilder builder) { JpaTransactionManager transactionManager new JpaTransactionManager(); transactionManager.setEntityManagerFactory(dorisEntityManagerFactory(builder).getObject()); return transactionManager; } Bean public EntityManager dorisEntityManager(EntityManagerFactoryBuilder builder) { return SharedEntityManagerCreator.createSharedEntityManager(Objects.requireNonNull(dorisEntityManagerFactory(builder).getObject())); } Bean public JPAQueryFactory dorisJpaQueryFactory(EntityManagerFactoryBuilder builder) { return new JPAQueryFactory(dorisEntityManager(builder)); } }DORIS的配置类变化也不是很大主要有以下几点扫描包路径更改为DORIS对应路径DataSourceProperties需要指定配置ConfigurationProperties(spring.datasource.doris)JPA的配置可共用与MySQL差别不大。其他配置由于使用到了多模块的配置除了不同环境的yml配置文件集成外不同模块的配置文件也需要集成因此我的application.yml设计如下spring: profiles: # 动态环境 active: dev # env # 采坑记录使用 获取 pom.xml 环境变量时必须指定 build resources resource filteringtrue/filtering include: dorisinclude实际指向的是DORIS模块下的application-doris.yml配置文件。Configuration public class JpaConfiguration { public static JPAQueryFactory getJpaQueryFactory() { return BeanUtils.getBean(jpaQueryFactory); } }如果用到了QueryDSL那么不同数据源对应的不同的JpaQueryFactory需要做不同的引用这里就只能用beanName在容器中做bean的指定了。最后说一句(求关注别白嫖我)如果这篇文章对您有所帮助或者有所启发的话帮忙关注一下您的支持是我坚持写作最大的动力。求一键三连点赞、转发、在看。我从清晨走过也拥抱夜晚的星辰人生没有捷径你我皆平凡你好陌生人一起共勉。
http://www.rkmt.cn/news/1405062.html

相关文章:

  • 告别Excel.dll!在Unity 2018+中用ExcelDataReader轻松搞定.xlsx表格读取(保姆级避坑指南)
  • SDRPlusPlus:跨平台软件定义无线电架构解析与技术实现
  • 贵州旅游管理专业好的学校有哪些?5所中职强校推荐,择校不踩坑 - 深度智识库
  • Claude Code 接入 DeepSeek V4 Pro 完整指南:国产大模型赋能最强编程代理
  • C++ -- 哈希表实现
  • 3分钟掌握Mobox触控控制:Input Bridge手势映射完全指南
  • AntiDupl.NET深度解析:智能图片去重工具的效率革命与实战指南
  • FontCenter:AutoCAD字体缺失的智能自动化解决方案
  • 【元器件专题】三极管电路(饱和导通设计)
  • 汽车CAN总线安全增强:ID跳变机制原理与FPGA硬件实现
  • 凸包法解算法题——最大三角形面积
  • python学习-xx14-1 pandas【⭐】
  • 在模型频繁更新时代Taotoken提供的最新模型接入体验
  • 大气网格化监测气象站:一张网管住城市空气质量
  • Page Assist完整指南:浏览器侧边栏本地AI助手终极教程
  • 【AI时代绩效革命】:首次公开——ChatGPT岗位胜任力雷达图(含6项硬指标+3项灰度阈值)
  • Windows终极定制神器:Windhawk让系统完全按你的想法工作
  • 数据异构下联邦学习的拜占庭攻防:挑战、机制与评估
  • 为开源AI工具OpenClaw配置Taotoken作为模型供应商的指南
  • 2026 卫生型液体流量计(卡箍/卡盘)厂家一览:国产与进口流量计怎么选?卡箍/卡盘电磁流量计品牌选型 - 流量计品牌
  • FPGA近似计算设计空间探索:模型驱动与输入感知方法对比与实践
  • 为AI智能体构建可信工具搜索引擎:从意图理解到动态信任评估
  • 虚拟化- x86 频率调节方法
  • ESP32智能车牌识别系统:如何在嵌入式设备上实现边缘AI视觉处理?
  • ESP32视觉处理:从边缘计算到智能图像分析的技术演进
  • 基于容器编排的企业级IPAM和DCIM基础设施管理平台部署指南
  • 如何用LeagueAkari让你的英雄联盟游戏体验提升300%:一站式客户端工具箱完全指南
  • Zepp Life步数自动化同步:完整指南与深度技术解析
  • Window Resizer终极指南:3分钟掌握Windows窗口尺寸自由调整技巧
  • 经典算法题型之最大三角形面积(二)