• hibernate跨数据库,columnDefinition不可移植性改造方案


    背景&问题描述

    很多项目选择jpa/hibernate,更多是为了代码的可移植性,不限制数据库的选择。特别是toB的业务系统,不同的客户,要求用不同的数据库。特别近几年,大力倡导软件国产化,国产数据库也在崛起,很多政府、国企、电力、银行在数据库的选择上,纷纷转向国产数据库。也许mybatis+mysql很香,但是代码可移植性却成了toB\toG软件类平台的关键竞争力。
    hibernate,在字段定义,很多人都喜欢用columnDefinition注解去定义表的DDL,可能是曾经留下来的习惯吧。以前的hibernate对数据库字段及数据库移植性支持的比较差,像json、time、blob等一些特殊字段类型,表字段注释等支持的不好,为了方便,大家基本都会用columnDefinition注解直接去定义表,columnDefinition注解属性定义的ddl是不可移植性的,导致了整个项目不能跨数据库自动创建表。
    下文讲解columnDefinition字段的替代方案。

    解决方案

    以mysql为例


    @Colum(columnDefinition="decimal(15,2) comment '产品单价' default 1.5 ")

    • 字段注释
      需要将hibernate升级到5.6版本以上
      字段注释使用注解org.hibernate.annotations.Comment
      @Comment("产品单价")
    • 字段长度、精度
      字段长度使用javax.persistence.Column注解中的length属性,精度使用scale
      @Column(length=15,scale=2)
    • 字段默认值
      字段默认值使用org.hibernate.annotations.ColumnDefault注解
      注意:字符型,需要加单引号
      @ColumnDefault("1.5")
    • 大字段类型
      大字段处理用javax.persistence.Lob,同时加注解@javax.persistence.Basic(fetch = FetchType.LAZY)懒加载,避免加载大数据,导致性能很差
      对应数据库text\blob字段等
        @Column
        @Lob
        @Basic(fetch = FetchType.LAZY)
    
    • 时间类
      时间类型字段使用注解javax.persistence.Temporal
      通过传入注解参数TemporalType类型,可以指定时间类型
      image

    @Temporal(TemporalType.TIMESTAMP) // 时间戳
    @Temporal(TemporalType.DATE) // 日期
    @Temporal(TemporalType.TIME) // 时间

    • json类型
      json数据,如果数据库不支持json类型,hibernate会默认转为varchar类型,并且长度默认为255,对于json数据,通常都是大字段,下期将改造方案。
    @TypeDef(name = "json", typeClass = JsonStringType.class)
    public class Test {
      @Type(type = "json")
      private TestModel testModel;
    }
    

    @Type(type = "json") 其含义是将当前表格列映射成“Hibernate Types”中的 JsonStringType类型。JsonStringType进一步将对应的数据实体映射成VARCHAR类型。

    hibernate支持json字段类型,可参考
    https://github.com/vladmihalcea/hibernate-types

    注意事项

    • 汉字编码长度不同
      不同数据库编码对字符长度的定义不一致,比如,mysql,varchar(20)可以存放20个汉字,而sqlserver相同的字段定义只能存放10个汉字。建议在定义表字段时,取大不取小,考虑汉字占位符;
    • 参数限制
      传参不能超过2100条,条数不能超过1000条,in参数不能超过1000条(SqlServer、oracle都有这个限制)
      对于一些表参数传递,尽可能用关联查询,推荐使用querydsl做关联查询,避免大量参数传递
    • 唯一键名称重复限制
      mysql中,唯一键就是索引,在同一个表,索引名称不能重复,而SqlServer是有唯一键,是整库内,所有唯一键名称不能重复。建议在建唯一键时,不填写索引name,hibernate会自动生产不重复name
      @Table(uniqueConstraints = {@UniqueConstraint(columnNames = {"name", "age"})})
  • 相关阅读:
    [Vue3]Vue3基本概述
    ROS2架构分析总结(一)
    XML配置文件
    在vs中创建linux项目
    【MATLAB第72期】基于MATLAB的LightGbm(LGBM)梯度增强决策树多输入多输出回归预测模型
    Django笔记三十二之session登录验证操作
    Linux系统离线安装Python
    FPGA-结合协议时序实现UART收发器(一):UART协议、架构规划、框图
    让直播和视频通话更精彩的实时换脸神器: 亲妈都未必认识
    【C++】C++11中的智能指针
  • 原文地址:https://www.cnblogs.com/luze/p/17179221.html