jpa多数据源时Hibernate配置自动生成表不生效的解决

作者:天涯泪小武 时间:2023-04-24 06:19:55 

jpa配置多数据源教程很多,在Springboot2之后有一些变化,来看一下。

application.yml如下

spring:
 application:
   name: t3cc
 datasource:
   primary:
       jdbc-url: jdbc:mysql://${MYSQL_HOST:localhost}:${MYSQL_PORT:3306}/${DB_NAME:anbang}?useUnicode=true&characterEncoding=UTF8&serverTimezone=Hongkong
       username: root
       password: root
   secondary:
       jdbc-url: jdbc:mysql://${MYSQL_HOST:localhost}:${MYSQL_PORT:3306}/${DB_NAME:anbang1}?useUnicode=true&characterEncoding=UTF8&serverTimezone=Hongkong
       username: root
       password: root
 jpa:
   database: mysql
   database-platform: org.hibernate.dialect.MySQL5InnoDBDialect  #不加这句则默认为myisam引擎
   hibernate:
     ddl-auto: update
     naming:
       physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
   open-in-view: true
   properties:
       enable_lazy_load_no_trans: true
   show-sql: true
 cloud:
   nacos:
     discovery:
       server-addr: ${NACOS_SERVER:localhost:8848}
###############################---log---##############################
logging:
 file: ./logback.log

yml里配置了两个数据源,和一些jpa和Hibernate的配置。

下面是DataSource的配置

/**
* @author wuweifeng wrote on 2019/3/5.
*/
@Configuration
public class DataSourceConfig {
   @Primary
   @Bean(name = "primaryDataSource")
   @ConfigurationProperties(prefix = "spring.datasource.primary")
   public DataSource dataSourceOrder() {
       return DataSourceBuilder.create().build();
   }

@Bean(name = "secondaryDataSource")
   @ConfigurationProperties(prefix = "spring.datasource.secondary")
   public DataSource dataSourceAuth() {
       return DataSourceBuilder.create().build();
   }
}

下面是第一个数据源的配置

package com.mm.dmp.t3cc.config;
import org.springframework.beans.factory.annotation.Qualifier;
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.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.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.sql.DataSource;

/**
* @author wuweifeng wrote on 2019/3/5.
*/
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
       entityManagerFactoryRef = "entityManagerFactoryPrimary",
       transactionManagerRef = "transactionManagerPrimary",
       basePackages = {"com.mm.dmp.t3cc.core.repository.one"})
public class OneConfig {

@Resource
   @Qualifier("primaryDataSource")
   private DataSource primaryDataSource;

@Primary
   @Bean(name = "entityManagerPrimary")
   public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
       return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
   }

@Resource
   private JpaProperties jpaProperties;

@Resource
   private HibernateProperties properties;

/**
    * 设置实体类所在位置
    */
   @Primary
   @Bean(name = "entityManagerFactoryPrimary")
   public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {
       LocalContainerEntityManagerFactoryBean entityManagerFactory = builder
               .dataSource(primaryDataSource)
               //.packages(classes)
               //设置实体类所在位置
               .packages("com.mm.dmp.t3cc.core.entity.one")
               .persistenceUnit("primaryPersistenceUnit")
               //.properties(jpaProperties.getProperties())
               .properties(properties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings()))
               .build();
       return entityManagerFactory;
   }

@Primary
   @Bean(name = "transactionManagerPrimary")
   public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
       return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
   }
}

这里会和别人的配置不一样,主要区别在于HibernateProperties。别人的在第61行,我注释掉的那行,会直接使用jpaProperties.getProperties()。当你这样写之后,会发现yml里配置的Hibernate的update自动生成表,和命名方式并没有生效。

原因我们可以看一下。

jpa多数据源时Hibernate配置自动生成表不生效的解决

这里就是jpaProperties.getProperties()的地方,如果打断点可以看到,只有箭头这一个配置被加载进去了。上面的Hibernate的ddl和naming并没有进去。

jpa多数据源时Hibernate配置自动生成表不生效的解决

来看一下HibernateProperties

jpa多数据源时Hibernate配置自动生成表不生效的解决

这里才是真正让自动建表生效的地方,然而并没有加载进去。那么就需要我们手工来添加了。

jpa多数据源时Hibernate配置自动生成表不生效的解决

这里面有个determineHibernateProperties方法,就是来组合jpaProperties和HibernateProperties的地方。我们应该使用这个方法来组合整个配置的map对象。

jpa多数据源时Hibernate配置自动生成表不生效的解决

也就是在OneConfig类中,把两个Properties都定义出来,然后组合一下,就是箭头的地方。在debug时,就可以看到Hibernate的配置也都加载进来了。

OK,以上就是动态数据源配置Hibernate自动建表不生效的原因。

下面是第二个数据源的配置

package com.mm.dmp.t3cc.config;
import org.springframework.beans.factory.annotation.Qualifier;
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.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.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.sql.DataSource;

/**
* @author wuweifeng wrote on 2019/3/5.
*/
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
       entityManagerFactoryRef = "entityManagerFactorySecondary",
       transactionManagerRef = "transactionManagerSecondary",
       basePackages = {"com.mm.dmp.t3cc.core.repository.two"}) //设置Repository所在位置
public class TwoConfig {

@Resource
   @Qualifier("secondaryDataSource")
   private DataSource secondaryDataSource;

@Resource
   private JpaProperties jpaProperties;

@Resource
   private HibernateProperties properties;

@Bean(name = "entityManagerSecondary")
   public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
       return entityManagerFactorySecondary(builder).getObject().createEntityManager();
   }

@Bean(name = "entityManagerFactorySecondary")
   public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary(EntityManagerFactoryBuilder builder) {
       LocalContainerEntityManagerFactoryBean entityManagerFactory
               = builder
               .dataSource(secondaryDataSource)
               //.packages(classes)
               //设置实体类所在位置
               .packages("com.mm.dmp.t3cc.core.entity.two")
               .persistenceUnit("secondaryPersistenceUnit")
               .properties(properties.determineHibernateProperties(jpaProperties.getProperties(), new
                       HibernateSettings()))
               .build();
       return entityManagerFactory;
   }

@Bean(name = "transactionManagerSecondary")
   public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
       return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());
   }
}

如果你觉得这样比较麻烦,并且还有分库分表的需求,那么可以使用sharding jdbc来操作,移步这一篇文章

来源:https://tianyalei.blog.csdn.net/article/details/96977099

标签:jpa,多数据源,Hibernate,生成表
0
投稿

猜你喜欢

  • C#并查集(union-find)算法详解

    2023-10-27 12:18:54
  • mybatis项目CRUD步骤实例详解

    2023-04-21 13:12:00
  • Java对象级别与类级别的同步锁synchronized语法示例

    2023-06-25 09:11:22
  • 详解Java环境变量配置方法(Windows)

    2022-05-09 02:39:33
  • Android SharePreferences与数据库SQLite存储实现方法介绍

    2023-03-13 11:20:45
  • Java实战之用springboot+netty实现简单的一对一聊天

    2023-12-03 07:28:19
  • Java实现的读取资源文件工具类ResourcesUtil实例【可动态更改值的内容】

    2022-01-15 17:27:12
  • java生成指定范围随机数的多种代码

    2023-04-28 07:51:15
  • 浅谈java 增强型的for循环 for each

    2023-03-30 18:51:05
  • SpringBoot教程_创建第一个SpringBoot项目

    2022-02-19 23:12:54
  • Spring session 获取当前账户登录数的实例代码

    2022-10-17 10:02:05
  • 解析C#中#region与#if的作用

    2021-09-18 16:48:28
  • Java线程池并发执行多个任务方式

    2023-08-14 16:26:03
  • 浅谈Java 三种方式实现接口校验

    2023-01-20 02:57:55
  • mybatis中查询结果为空时不同返回类型对应返回值问题

    2023-02-15 10:50:31
  • Jaxb2实现JavaBean与xml互转的方法详解

    2023-11-25 11:51:38
  • 聊聊@RequestBody和Json之间的关系

    2023-11-27 03:31:45
  • 基于Java实现经典蜘蛛纸牌游戏

    2021-09-06 15:22:57
  • Java 精炼解读数据结构逻辑控制

    2023-09-14 05:35:37
  • Unity3D绘制地形的实现方法

    2022-12-01 01:06:46
  • asp之家 软件编程 m.aspxhome.com