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

目录
  • application.yml如下
  • 下面是DataSource的配置
  • 下面是第一个数据源的配置
  • 下面是第二个数据源的配置

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来操作,移步这一篇文章

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • spring+Jpa多数据源配置的方法示例

    今天临下班时遇到了一个需求,我的管理平台需要从不同的数据库中获取数据信息,这就需要进行Spring的多数据源配置,对于这种配置,第一次永远都是痛苦的,不过经历了这次的折磨,今后肯定会对这种配置印象深刻.我们这里简单回顾一下流程. 我们配置了两个数据库,一个是公司的数据库,另一个是我本地的一个数据库.首先是application.yml的配置(其中对于公司的数据库我们采取了假的地址,而本机的数据库是真是存在对应的表和库的) 数据库信息: 数据表信息: 1.application.yml datas

  • 解决Spring Data Jpa 实体类自动创建数据库表失败问题

    目录 Spring Data Jpa 实体类自动创建数据库表失败 找了半天发现是一个配置的问题 可能导致JPA 无法自动建表的问题汇总 1.没加@Entity或引错Entity所在包 2.jpa配置中ddl-auto未设置update 3.实体类的包不是启动程序所在包的子包 4.mysql配置问题 5.依赖不全 6.实体类间关系错误 7.启动类注解问题 8.其他问题 Spring Data Jpa 实体类自动创建数据库表失败 先说一下我遇到的这个问题,首先我是通过maven创建了一个spring

  • Spring Boot+Jpa多数据源配置的完整步骤

    关于 有时候,随着业务的发展,项目关联的数据来源会变得越来越复杂,使用的数据库会比较分散,这个时候就会采用多数据源的方式来获取数据.另外,多数据源也有其他好处,例如分布式数据库的读写分离,集成多种数据库等等. 下面分享我在实际项目中配置多数据源的案例.话不多说了,来一起看看详细的介绍吧 步骤 1.application.yml文件中,配置数据库源.这里primary是主库,secondary是从库. server: port: 8089 # 多数据源配置 #primary spring: pri

  • 详解hibernate自动创建表的配置

    详解hibernate自动创建表的配置 配置自动创建表: <prop key="hibernate.hbm2ddl.auto">update</prop>//首次创建项目时用,项目稳定后一般注释这里有4个值: update:表示自动根据model对象来更新表结构,启动hibernate时会自动检查数据库,如果缺少表,则自动建表:如果表里缺少列,则自动添加列. 还有其他的参数: create:启动hibernate时,自动删除原来的表,新建所有的表,所以每次启动后

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

    目录 application.yml如下 下面是DataSource的配置 下面是第一个数据源的配置 下面是第二个数据源的配置 jpa配置多数据源教程很多,在Springboot2之后有一些变化,来看一下. application.yml如下 spring: application: name: t3cc datasource: primary: jdbc-url: jdbc:mysql://${MYSQL_HOST:localhost}:${MYSQL_PORT:3306}/${DB_NAME

  • Springboot引入hibernate配置自动建表并进行增删改查操作

    目录 前言 一.引入依赖 二.配置yml 三.写代码 四.测试结果 前言 有些业务比较复杂,比如我们需要新建10张表,每张表有10个字段,如果用手工来操作,肯定非常浪费时间,而且随着代码中对实体类的修改,还要同时修改数据库表,有时候写着写着就忘了,代码改了,数据库没改,这种问题使用 hibernate 的自动建表就好啦. 一.引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifac

  • Spring Data Jpa 自动生成表结构的方法示例

    想在部署的时候随应用的启动而初始化数据脚本,这不就是Spring Data Jpa中的自动生成表结构,听起来特别简单,不就是配置Hibernate的ddl-auto嘛,有什么好说的,是个人都知道.当初我也是这样认为,实际操作了一把,虽然表是创建成功了,但是字段注释,字符集以及数据库引擎都不对,没想到在这些细节上翻车了. 毕竟开翻的车还要自己扶起来,于是在这记录一下. 注:本文中使用的Spring Data Jpa版本为2.1.4.RELEASE 以MySQL为例,我这边举个例子: import

  • C#实现保存文件时重名自动生成新文件的方法

    本文实例讲述了C#实现保存文件时重名自动生成新文件的方法.分享给大家供大家参考.具体如下: 将一个文档保存为 a.txt 时,发现此文件已经存在,则自动保存为 a(1).txt /// <summary> /// Generates a new path for duplicate filenames. /// </summary> /// <param name="path">The path.</param> /// <retu

  • Vue2 Element Schema Form 配置式生成表单的实现

    目录 前置知识点 Component $attrs $listeners 表单的结构是什么样的 配置数组数据结构 结语 前置知识点 为了实现一个Schema Form配置式表单的生成,需要了解一部分前置知识点. Component vue 提供了一个内置组件 Component,用来动态渲染组件,举个例子,本篇文章以Element UI 为例,假设我们全局注册了Element UI的组件,那么下面一段代码 <Component is="el-input"></Comp

  • JSP实现用于自动生成表单标签html代码的自定义表单标签

    本文实例讲述了JSP实现用于自动生成表单标签html代码的自定义表单标签.分享给大家供大家参考.具体如下: 这个是自己写的一个简单的JSP表单标签,用于自动生成checkbox,select,radio等标签,传入菜单集合生成html代码,自动选中指定值,用于java web项目的jsp页面. 1. Servlet部分代码: Map<String, String> map = new HashMap<String, String>(); map.put("2",

  • PHP自动生成表单代码分享

    Form.php <?php //Form.php class form { var $layout=true;//是否使用表格布局 var $action;//表单要提交到的URL var $method; var $enctype=""; var $name=""; var $id=""; var $class=""; function form($action,$method="POST"){

  • SpringBoot+jpa配置如何根据实体类自动创建表

    目录 jpa配置根据实体类自动创建表 1.配置文件application.properties 2.pom.xml引入包 3.编写实体类 4.运行项目 5.针对项目启动以后数据库并未生成数据库表问题 jpa根据Entry自动生成表 1.加入依赖 2.配置 application.yml 3. 创建Entity jpa配置根据实体类自动创建表 1.配置文件application.properties spring.datasource.url=jdbc:mysql://localhost:3306

  • springboot+mybatis通过实体类自动生成数据库表的方法

    前言 本章介绍使用mybatis结合mysql数据库自动根据实体类生成相关的数据库表. 首先引入相关的pom包我这里使用的是springboot2.1.8.RELEASE的版本 <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.0</ve

随机推荐