hibernate - 在多对一约束上不受支持的 SQL 类型 2005

Posted

技术标签:

【中文标题】hibernate - 在多对一约束上不受支持的 SQL 类型 2005【英文标题】:hibernate - Unsupported SQL type 2005 on many-to-one constraint 【发布时间】:2012-02-12 18:31:03 【问题描述】:

我使用休眠框架能够使用 Oracle 或 Sybase(客户选择)。但是当我们切换到 Sybase 的连接时,我遇到了一些关于多对一约束的问题。首先,Oracle 抱怨在 hibernate_hbm.xml 中定义为“文本”的 clob 字段,我通过在自定义类型中使用二进制 (ClobTypeDescriptor.STREAM_BINDING) 解决了这个问题。对于甲骨文来说,一切正常,运行完美。但是当我将数据库服务器切换到 Sybase 时,尝试在具有外键约束的表上保存记录时出现以下错误。

Caused by: java.sql.SQLException: JZ006: Caught IOException: java.io.IOException: JZ0SL: Unsupported SQL type 2005.
        at com.sybase.jdbc4.jdbc.SybConnection.getAllExceptions(Unknown Source)
        at com.sybase.jdbc4.jdbc.SybStatement.handleSQLE(Unknown Source)
        at com.sybase.jdbc4.jdbc.SybStatement.sendQuery(Unknown Source)
        at com.sybase.jdbc4.jdbc.SybPreparedStatement.sendQuery(Unknown Source)
        at com.sybase.jdbc4.jdbc.SybStatement.executeUpdate(Unknown Source)
        at com.sybase.jdbc4.jdbc.SybPreparedStatement.executeUpdate(Unknown Source)
        at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:94)
        at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:57)
        ... 47 more

这是映射:

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.aykut.test.persistence">

    <class name="classA" table="tableA">
        <id name="tableA_Id" type="long">
            <generator class="native" />
        </id>
        <property name="someDateColumn" type="timestamp" />
        <set name="destinations" table="tableB" cascade="all" lazy="false">
            <key column="tableA_Id" />
            <one-to-many class="classB" />
        </set>
    </class>
    <class name="classB" table="tableB">
        <id name="tableB_Id" type="long">
            <generator class="native" />
        </id>
        <many-to-one name="classA_Data" class="classA" column="tableA_Id" lazy="false" />
        <property name="someInfoColumn" length="64" not-null="true" type="string" />
    </class>
</hibernate-mapping>

我进行了一些测试,如果这两个表之间没有任何关系,则可以正常保存记录。

我觉得有些奇怪,如果我使用 ddl 手动创建表并将 bigint 类型赋予 id 列,并且如果我不使用 hibernate.hbm2ddl.auto=update 属性,一切看起来都很正常。以 bigint 类型创建的列并且工作正常。

如果我使用 hibernate.hbm2ddl.auto=update 属性,则使用 id 列的 numeric(19,0) 字段创建的表。发生这种情况时,我们的映射会抛出错误。

我阅读了一些文章并对其进行了测试,但没有成功。这是我的测试。


将映射添加到 not-null="true" &lt;many-to-one name="classA_Data" class="classA" column="tableA_Id" /&gt; 行。失败

hibernate.max_fetch_depth = 1 添加到属性。失败。

hibernate.jdbc.use_get_generated_keys=true 添加到属性。失败。

这些都发生在 Sybase 方面。

我测试了 jconnect 6.0(jdbc3) 和 7.0 (jdbc4)

我使用的是休眠 3.6.1 最终版本。 使用 Oracle11gR2 和 Sybase 12.0.5 - 15.0.2 - 15.0.3 测试

有什么建议吗?

【问题讨论】:

&lt;many-to-one name="classA_Data" sqltype="bigint"&gt;? 【参考方案1】:

我已经弄清楚了实际问题并解决了它。我们为 oracle 实例的 clob 字段使用自定义类型。(这是 oracle 的另一种解决方案。)但是当我们实现此自定义类型时,sybase 实例开始抛出上述异常。一开始,我认为问题是约束,但根本不是。问题是;尝试为 sybase clob 类型的 clob 字段设置 null。我在自定义类型类上实现了覆盖的 nullSafeSet 方法,就好像自定义类型的值为 null 一样,将类型转换为 varchar。我们还必须为 sybase clob 字段创建新的 texttypedescriptor。然后它工作。这是解决方案:

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;

import org.hibernate.HibernateException;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.type.AbstractStandardBasicType;
import org.hibernate.type.descriptor.java.StringTypeDescriptor;
import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;

public class TextType extends AbstractStandardBasicType<String> 

    public static final TextType INSTANCE = new TextType();

    public TextType() 
        super((myapp.isOracle?ClobTypeDescriptor.STREAM_BINDING:CustomSybaseTextTypeDescriptor.INSTANCE), StringTypeDescriptor.INSTANCE);
    

    public String getName() 
        return "customtext";
    

    @Override
    public void nullSafeSet(PreparedStatement arg0, Object arg1, int arg2,
            boolean[] arg3, SessionImplementor arg4)
            throws HibernateException, SQLException 
        if(arg1 == null)
            arg0.setNull(arg2,Types.VARCHAR);
        else
            super.nullSafeSet(arg0, arg1, arg2, arg4);
    

【讨论】:

以上是关于hibernate - 在多对一约束上不受支持的 SQL 类型 2005的主要内容,如果未能解决你的问题,请参考以下文章

hibernate之多对一单向关联

Hibernate--一对多/多对一

Hibernate映射

Hibernate的关联关系映射

hibernate系列之四

hibernate的一对多和多对一关联