更新时间:2024-11-12 GMT+08:00
Hibernate框架插入数据开启校验时报错
问题现象
客户从A模式数据库迁移到GaussDB数据库,表结构使用DRS工具进行迁移,迁移后客户原业务代码不可用,Hibernate框架校验表结构报错。
Schema-validation: wrong column type encountered in column [execute_time] in table [abnormal_event]; found [int8 (Types#BIGINT)], but expecting [int4 (Types#INTEGER)]
示例:
- 原A模式数据库中Student表结构为如下格式:
id number(15,0) sid number(15,0) age number(10,0)
- 使用DRS工具进行迁移GaussDB数据库后Student表结构为如下格式:
id bigint sid bigint age Integer
- 当实际数据库中Student实体类信息如下时:
Long id Long sid Long age --Hibernate框架校验表结构报错。
hibernate.cfg.xml配置文件:
<hibernate-configuration> <session-factory> <!--GaussDB连接信息--> <property name="connection.driver_class">com.huawei.gaussdb.jdbc.Driver</property> <property name="connection.url">jdbc:gaussdb://x.x.x.x:xx/postgres?currentSchema=public</property> <property name="connection.username">xxxxxx</property> <property name="connection.password">xxxxxx</property> <!--以下为可选配置--> <!--是否支持方言--> <!--在pgsql兼容模式下,必须有如下配置--> <property name="dialect">org.hibernate.dialect.PostgreSQL92Dialect</property> <!--在A数据库兼容模式下,推荐如下配置--> <!-- <property name="dialect">org.hibernate.dialect.OracleDialect</property>--> <property name="met"></property> <!--执行CURD时是否打印SQL语句 --> <property name="show_sql">true</property> <!--自动建表--> <!-- <property name="hbm2ddl.auto">create</property>--> <!--插入数据时开启校验--> <property name="hbm2ddl.auto">validate</property> <!--关闭校验--> <!-- <property name="hbm2ddl.auto">none</property>--> <!-- 资源注册(实体类映射文件)--> <mapping resource="student.xml"/> </session-factory> </hibernate-configuration>
插入数据的主函数:
// 创建要测试的对象。 Student student = new Student(); student.setId(20L); student.setAge(222L); student.setSid(222L); // 开启事务,基于session得到对象。 Configuration conf = new Configuration().configure(); SessionFactory sessionFactory = conf.buildSessionFactory(); Session session = sessionFactory.openSession(); Transaction transaction = session.beginTransaction(); // 通过session保存数据。 session.save(student); // 提交事务。 transaction.commit(); // 操作完毕,关闭session连接对象。 session.close();
原因分析
- A模式数据库能够插入成功并通过校验:Hibernate框架在校验数据时,通过判断插入数据类型java.lang.long的TypeCode,与表结构的number类型的TypeCode进行对比,结果不一致,随后会把插入数据的long类型的sqlType与表结构的Type作比较,将long类型转成number(19,0)(对应关系由org.hibernate.dialect.OracleDialect进行维护),因为表结构的type是number类型,number(19,0)以number开头,所以校验可以通过。使用A模式数据库时,业务代码涉及整数类型的数据,可以使用Java中的Long类型插入。
- GaussDB数据库校验不同,关闭校验后数据插入成功:Hibernate框架在插入数据做校验时,业务代码是java.lang.long类型,和表数据类型bigint的TypeCode是对应的,因此不报错。但是表数据类型是Integer时无法对应,首先判断业务代码java.lang.long类型的TypeCode,与表数据Integer的TypeCode比较,结果不一致,再根据org.hibernate.dialect.PostgreSQLDialect对应关系,会将Long类型转换为int8,将表数据类型Integer转换为int4,无法对应,所以校验失败。使用GaussDB数据库时,业务代码涉及整数类型的数据,必须使用表类型对应的Java整型。
处理方法
可使用以下方式进行问题处理:
- 关闭校验功能。
- 客户修改业务代码,针对不同的表数据类型,采用对应的Java整型。
父主题: 常见问题处理