hibernate - неподдерживаемый тип SQL 2005 с ограничением многие-к-одному - PullRequest
0 голосов
/ 12 февраля 2012

Я использую Hibernate Framework, чтобы иметь возможность использовать Oracle или Sybase (выбор клиента).Но когда мы переключаем соединение на Sybase, у меня возникают некоторые проблемы с ограничением многие-к-одному.Во-первых, Oracle жаловался на поля clob, которые были определены как «текст» в hibernate_hbm.xml, и я решил эту проблему с помощью двоичного (ClobTypeDescriptor.STREAM_BINDING) пользовательского типа.Для Oracle все нормально и работает отлично.Но когда я переключаю db-сервер на 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, таблицы создаются с числовыми (19,0) полями для столбцов идентификаторов.Когда это происходит, наше отображение оказывается выше ошибки.

Я прочитал какую-то статью и проверил их, но безуспешно.Вот мои тесты.


Добавление сопоставления в строку not-null = "true" <many-to-one name="classA_Data" class="classA" column="tableA_Id" />.FAILED

Добавление hibernate.max_fetch_depth = 1 в свойства.FAILED.

Добавление hibernate.jdbc.use_get_generated_keys=true в свойства.FAILED.

Все это происходит со стороны Sybase.

Я тестировал jconnect 6.0 (jdbc3) и 7.0 (jdbc4)

Я использую Hibernate 3.6.1 final.Протестировано с Oracle11gR2 и Sybase 12.0.5 - 15.0.2 - 15.0.3

Любое предложение, пожалуйста?

1 Ответ

0 голосов
/ 01 марта 2012

Я выяснил, что является актуальной проблемой, и решил ее.Мы используем пользовательский тип для поля clob для экземпляров oracle. (Это было еще одно решение для oracle.), Но когда мы реализовали этот пользовательский тип, экземпляры sybase начали выдавать выше исключения.Сначала я думал, что проблема в ограничениях, но не совсем.Проблема была;пытаясь установить значение null для закрытия полей для типа sybase clob. Я реализовал переопределенный метод nullSafeSet в нашем классе пользовательских типов, как если бы для пользовательского типа было значение null, преобразуйте тип в varchar.Также нам пришлось создать новый texttypedescriptor для полей sybase clob.Тогда это работает.Вот решение:

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);
    }
}
...