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 #这里配置自己写的类的全路径名称,别照抄!!!

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

相关推荐
青皮桔5 分钟前
Java+OpenCV实现图片切割
java·后端·opencv·计算机视觉
TDengine (老段)7 分钟前
TDengine 数据函数 MOD 用户手册
大数据·数据库·物联网·时序数据库·tdengine·涛思数据
文档搬运工7 分钟前
Oracle 19.29
数据库·oracle
兮动人10 分钟前
Spring中@Configuration注解的proxyBeanMethods属性详解
java·后端·spring
zl97989911 分钟前
SpringBoot-数据访问之Druid
java·spring boot
小小管写大大码20 分钟前
AI重排序API:优化搜索相关性
数据库·人工智能
猫头虎35 分钟前
解决升级IDEA2025.2后,每次打开Maven项目爆红的问题:Windows和Mac解决方案
java·ide·macos·maven·intellij-idea·idea·intellij idea
NFG89C39 分钟前
Adobe Lightroom Classic 2025解锁版 (专业照片管理)
java·adobe·工具
蒙奇D索大1 小时前
【计算机网络】408计算机网络高分指南:物理层编码与调制技术精讲
java·前端·学习·计算机网络
豐儀麟阁贵1 小时前
5.2 类
java·开发语言