JPA连接达梦数据库导致auto-ddl失效问题解决

现象:

项目使用了JPA,并且auto-ddl设置的为update,在连接达梦数据库的时候,第一次启动没有问题,但是后面重启就会报错,发现错误为重复建表,也就是说已经建好的表没有检测到,又重新走的建表流程。经过一天的排查,总结了2个解决方案。

问题的根源:

问题产生的原因是因为数据库实例设置了不区分大小写,并且在JPA的注解上的表名及字段名将表名都为小写时,在数据库创建的表名和字段名都为小写。在数据库连接后,会获取所有的表,和模型做匹配映射,没有映射的到的表会走创建表的流程,映射到的会走更新流程。但是在映射的过程中,达梦将映射部分强制设置为大写映射,并且这部分代码被写到了达梦的连接驱动内,很难进行扩展。这个映射部分源码要跟的很深,总的来说就是从数据库拿到的表名都是小写的,但是匹配的时候是将实体类上@Table的name值转为大写后再进行映射,而且这个是在达梦数据库的驱动里面设置的,重写方言的buildIdentifierHelper方法也没用。

而且这个方法的builder是在父类中直接build()的,又没法在父类执行完后扩展,只能在执行前扩展,所以设置的值没用。

解决办法:

1、达梦数据库创建数据库实例的时候使用默认的规则,区分大小写。不要创建不区分大小写的数据库实例,就不会有这个问题。并且记得在数据库连接里要设置参&ignoreCase=false&columnNameUpperCase=false

示例:jdbc:dm://{ip}:{port}/{数据库}?schema={schema}&useUnicode=true&serverTimezone=Asia/Shanghai&useSSL=false&characterEncoding=UTF-8&ignoreCase=false&columnNameUpperCase=false

2、匹配阶段不好解决,就在别的地方想想办法。问题的根源是因为实体类定义的大写表名和数据库中的小写表名匹配不上导致的,那就在建表阶段将表设置为大写就行了。而建表阶段的代码重新方言是可以做到的。

创建自定义的StandardTableExporter

java 复制代码
import org.hibernate.boot.Metadata;
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.dialect.Dialect;
import org.hibernate.mapping.Table;
import org.hibernate.tool.schema.internal.StandardTableExporter;


public class DmStandardTableExporter extends StandardTableExporter {

    public DmStandardTableExporter(Dialect dialect) {
        super(dialect);
    }

    @Override
    public String[] getSqlCreateStrings(Table table, Metadata metadata, SqlStringGenerationContext context) {
        table.setName(table.getName().toUpperCase());
        return super.getSqlCreateStrings(table, metadata, context);
    }
}

重写达梦方言的getTableExporter方法

java 复制代码
import org.hibernate.dialect.DmDialect;


public class ZeusDmDialect extends DmDialect {
    
    //这里是你自定义的StandardTableExporter
    private DmStandardTableExporter tableExporter = new DmStandardTableExporter( this );

    @Override
    public DmStandardTableExporter getTableExporter() {
        return tableExporter;
    }
}

配置使用自己写的写的方言:

java 复制代码
spring:
  jpa:
    properties:
      hibernate:
        dialect: a.b.c.d.e.ZeusDmDialect #这里配置自己写的类的全路径名称,别照抄!!!

把数据库的之前创建的小写的表名的表全删了,多重启几次试试看,应该就解决问题了。

相关推荐
木头没有瓜9 分钟前
idea离线安装插件
java·ide·intellij-idea
llwszx19 分钟前
Spring中DelayQueue深度解析:从原理到实战(附结构图解析)
java·后端·spring·delayqueue·延迟任务
述雾学java34 分钟前
Spring Cloud Feign 整合 Sentinel 实现服务降级与熔断保护
java·spring cloud·sentinel
保持学习ing34 分钟前
苍穹外卖day3--公共字段填充+新增菜品
java·阿里云·实战·springboot·前后端·外卖项目·阿里云文件存储
77qqqiqi1 小时前
正则表达式
java·后端·正则表达式
IT项目管理1 小时前
达梦数据库DMHS介绍及安装部署
linux·数据库
你都会上树?1 小时前
MySQL MVCC 详解
数据库·mysql
厦门德仔1 小时前
【WPF】WPF(样式)
android·java·wpf
大春儿的试验田1 小时前
高并发收藏功能设计:Redis异步同步与定时补偿机制详解
java·数据库·redis·学习·缓存
Gappsong8741 小时前
【Linux学习】Linux安装并配置Redis
java·linux·运维·网络安全