经实际测试,三种思路均可达到目的。由于上级领导不赞成修改标注的方式(理由是与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
其中给出了很多种解决思路,现简单总结如下:
- 定义PostgreSql表结构时,将JSON改为TEXT,即仿照Oracle的做法;
- 扩展Hibernate中的Type,增加关于json的自定义类型,同时增加(或重载)处理JSON的相应方法;
- 更换JDBC驱动为pgjdbc-ng,它提供了可以处理JSON与TEXT转换的@Conveter标注;
- 在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