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

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

相关推荐
松树戈6 分钟前
PostgreSQL使用LIKE右模糊没有走索引分析&验证
数据库·postgresql
纪元A梦11 分钟前
华为OD机试真题——绘图机器(2025A卷:100分)Java/python/JavaScript/C++/C/GO最佳实现
java·javascript·c++·python·华为od·go·华为od机试题
文牧之13 分钟前
PostgreSQL 常用日志
运维·数据库·postgresql
24k小善25 分钟前
FlinkSql入门与实践
java·大数据·flink·云计算
TE-茶叶蛋37 分钟前
Redis 原子操作
数据库·redis·缓存
CodeCraft Studio38 分钟前
Excel处理控件Spire.XLS系列教程:Java设置Excel活动工作表或活动单元格
java·python·excel
Linux运维老纪40 分钟前
Python文件操作及数据库交互(Python File Manipulation and Database Interaction)
linux·服务器·数据库·python·云计算·运维开发
Bruce_Liuxiaowei1 小时前
MCP Python SDK构建的**SQLite浏览器**的完整操作指南
数据库·python·sqlite
数据与人工智能律师1 小时前
正确应对监管部门的数据安全审查
大数据·网络·数据库·人工智能·区块链
瓯雅爱分享1 小时前
任务管理系统,Java+Vue,含源码与文档,科学规划任务节点,全程督办保障项目落地提效
java·mysql·vue·软件工程·源代码管理