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

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自动生成表,和命名方式并没有生效。

原因我们可以看一下。

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

来看一下HibernateProperties

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

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

也就是在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/98057916

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏爱写Bug

Leetcode 14:Longest Common Prefix 最长公共前缀

Write a function to find the longest common prefix string amongst an array of st...

7330
来自专栏爱写Bug

LeetCode 485:连续最大1的个数 Max Consecutive Ones

Given a binary array, find the maximum number of consecutive 1s in this array.

8840
来自专栏爱写Bug

LeetCode 209:最小长度的子数组 Minimum Size Subarray Sum

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组。如果不存在符合条件的连续子数组,返回 0。

9550
来自专栏爱写Bug

LeetCode 142:环形链表 II Linked List Cycle II

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。

9040
来自专栏keinYe

Python 生成器

列表生成式是 python 内置的非常强大的可以用来生成列表的生成式。在学习生成器之前先来了解一下列表生成式,者有利于我们队生成器的理解。

11520
来自专栏Java技术分享圈

杨校老师课堂基于SSM整合之用户登录案例【Eclipse - Maven版】

Eclipse:2019.06 + Jdk:8u211 + Tomcat:9.0.14 + Maven:3

11720
来自专栏爱写Bug

Leetcode # 118:Pascal's Triangle 杨辉三角

Given a non-negative integer numRows, generate the first numRows of Pascal's tri...

9540
来自专栏爱写Bug

LeetCode 151:给定一个字符串,逐个翻转字符串中的每个单词 Reverse Words in a String

Given an input string, reverse the string word by word.

9650
来自专栏爱写Bug

Leetcode 67:Add Binary(二进制求和)

Given two binary strings, return their sum (also a binary string).

5450
来自专栏WD学习记录

MoreObjects

T firstNonNull(@Nullable T first, @Nullable T second)。找出first和second中第一个不为空的对象,并...

7530

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励