2012-02-12 35 views
0

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

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属性,使用数字(19,0)字段为id列创建表。发生这种情况时,我们的映射会被抛出错误。

我读了一些文章,我测试了它们,但没有成功。这是我的测试。


将映射添加到not-null =“true”<many-to-one name="classA_Data" class="classA" column="tableA_Id" />行。 FAILED

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

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

这些都发生在Sybase方面。

我测试了jConnect的6.0(JDBC3)和7.0(jdbc4)

我使用Hibernate 3.6.1决赛。 使用Oracle11gR2和Sybase测试12.0.5 - 15.0.2 - 15.0.3

有什么建议吗?

+0

'<多对一名=“classA_Data”sqltype =“bigint”>'? – Firo 2012-02-14 12:45:51

回答

0

我已经想出了什么是实际问题并解决了它。我们对oracle实例使用clob字段的自定义类型(这是oracle的另一个解决方案),但是当我们实现这个自定义类型时,sybase实例开始抛出异常。一开始,我认为问题是制约因素,但根本不是。问题是;试图设置null为clob字段为sybase clob类型。我在我们的自定义类型类上实现了overrided nullSafeSet方法,就好像对于自定义类型的值为空,将类型转换为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); 
    } 
}