当前位置:Gxlcms > 数据库问题 > JPA移植到PostgreSQL时关于CLOB, BLOB及JSON类型的处理

JPA移植到PostgreSQL时关于CLOB, BLOB及JSON类型的处理

时间:2021-07-01 10:21:17 帮助过:140人阅读

  • 不修改EJB,重载PostgresDialect类remapSqlTypeDescriptor()方法,将CLOB当longvarchar处理。
  • 经实际测试,三种思路均可达到目的。由于上级领导不赞成修改标注的方式(理由是与Oracle环境的版本不一致),遂采用思路3,顺带着将BLOB按longVarBinary处理。

    因项目中PostgreSQL是9.4版,故选择从PostgreSQL94Dialect继承,一般情况下可选择PostgreSQL9Dialect。代码为:

    package com.xxx.pgdialect;
    
    import java.sql.Types;
    
    import org.hibernate.dialect.PostgreSQL94Dialect;
    import org.hibernate.type.descriptor.sql.LongVarbinaryTypeDescriptor;
    import org.hibernate.type.descriptor.sql.LongVarcharTypeDescriptor;
    import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
    
    public class PgDialect extends PostgreSQL94Dialect
    {
        @Override
        public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor)
        {
            switch (sqlTypeDescriptor.getSqlType())
            {
            case Types.CLOB:
                return LongVarcharTypeDescriptor.INSTANCE;
            case Types.BLOB:
                return LongVarbinaryTypeDescriptor.INSTANCE;
            }
            return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
        }
    }

    然后在persistence.xml中用这个类(com.xxx.pgdialect.PgDialect)替换PostgreSQL94Dialect即可。

     三、JSON的处理

     JSON类型的特殊之处在于:首先Oracle实际上是按特殊的varchar2或clob来对待;其次是Hibernate及JDBC都没有定义json类型。因此,在遇到“column xxx is type of json but expression is type of character varying ...”例外时,不能简单地照搬前述方法。

    经Google,发现一篇很有价值的资料:

    参考资料4:https://stackoverflow.com/questions/15974474/mapping-postgresql-json-column-to-hibernate-value-type

    其中给出了很多种解决思路,现简单总结如下:

    1. 定义PostgreSql表结构时,将JSON改为TEXT,即仿照Oracle的做法;
    2. 扩展Hibernate中的Type,增加关于json的自定义类型,同时增加(或重载)处理JSON的相应方法;
    3. 更换JDBC驱动为pgjdbc-ng,它提供了可以处理JSON与TEXT转换的@Conveter标注;
    4. 在PostgreSql数据库,创建隐式或显式的类型转换方法或函数,使得PostgreSQL接受JSON与TEXT的自动转换。

    思路1需要应用程序保证数据符合json规范,风险较大,被否决。思路2有很多种具体实现方式(有兴趣者自行钻研),但其共同点都是需要修改EJB标注,被领导否决。思路3过于依赖某一产品,且跟2一样也要修改标注,也被否决。只剩下思路4,而事实上它也确实是最简便的方式。

    在psql命令行,简单创建TEXT与JSON、Varchar与JSON互相转换的四个CAST即可:

    CREATE CAST (text AS json)
      WITH INOUT
      AS ASSIGNMENT;
    
    CREATE CAST (json AS text)
      WITH INOUT
      AS ASSIGNMENT;
    
    CREATE CAST (varchar AS json)
      WITH INOUT
      AS ASSIGNMENT;
    
    CREATE CAST (json AS varchar)
      WITH INOUT
      AS ASSIGNMENT;

    执行之后,再无“column xxx is type of json but expression is type of character varying ...”例外。

    进一步猜测,XML类型也可以按类似方法来处理。

    四、总结

    • 定义EJB时一定要规范,可以避免大多数简单的类型不匹配错误;
    • 对于CLOB和BLOB,把它们按LongVarchar和LongVarBinary处理;
    • 对于JSON,增加隐式或显式的类型转换方法。

    JPA移植到PostgreSQL时关于CLOB, BLOB及JSON类型的处理

    标签:get   原因   post   问题   extends   java   rac   针对   sig   

    人气教程排行