Как управлять XmlType в базе данных H2 - PullRequest
1 голос
/ 14 апреля 2011

Я использую базу данных H2 для своих модульных тестов.В моем приложении у меня есть объект Entity с именем FooXml, определенный следующим образом:

@Entity
@Table(name = "T_FOOXML")
@SequenceGenerator(allocationSize = 1, name = "S_FOOXML", sequenceName = "S_FOOXML")
@NamedQueries( ... )
@Cache(usage = CacheConcurrencyStrategy.NONE)
public class FooXml implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "S_FOOXML")
    @Column(name = "FOOXML_ID")
    private Integer id;

    @Type(type = "my.app.common.HibernateXMLType")
    @Column(name = "FOOXML_CONTENT")
    @Basic(fetch = FetchType.LAZY)
    private String xmlContent;

    ...

}

Поэтому для чтения / записи содержимого XML из базы данных я создал собственный XMLType, my.app.common.HibernateXMLType, который реализует org.hibernate.usertype.UserType.Здесь определены методы nullSafeSet и nullSafeGet.

Теперь я хочу использовать базу данных H2 в памяти для своих тестов, и некоторые тесты используют этот класс FooXml.Поскольку H2 не поддерживает Oracle XmlType, я должен настроить свой my.app.common.HibernateXMLType.Например, я добавил эту часть:

public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
    ...
    // Case where H2 Database is used as the dataSource...
    if (st.getConnection() instanceof org.h2.jdbc.JdbcConnection) {
        // Set the XML as a String...
        st.setObject(index, (String) value);
    } else {
        // Case of "normal" behavior (outside tests context)
        ...
    }
}

У меня есть несколько проблем с этим подходом:

  • Я добавляю код, который напрямую связан с целью тестирования в производственном кодеapplication (т. е. , а не в тестовом коде);
  • Поскольку этот класс зависит от org.h2.jdbc.JdbcConnection, я должен добавить зависимость h2-database в моем пакете WAR.

Вопросы :

  • Это лучший подход для решения моей проблемы или есть лучший способ сделать это?
  • Есть лиспособ сказать Hibernate использовать другой тип (my.app.common.HibernateXMLTypeForH2 вместо my.app.common.HibernateXMLType) для целей тестирования?

ps: скрипт для создания моей таблицы в базе данных H2 выглядит следующим образом:

create table T_FOO_XML (
    FOOXML_ID NUMBER(9, 0) not null,
    FOOXML_CONTENT CLOB(400000)
);

Технические подробности : База данных H2 v1.3.153, JUnit 4.8.1, Java 1.6,Hibernate 3.2.2, Oracle 10g используется в средах без тестирования .

Ответы [ 2 ]

2 голосов
/ 28 апреля 2011

Я добавляю код, который напрямую связан с Испытание цели в производстве код ...

В некотором смысле, да, потому что вы используете H2 для тестирования. Однако можно утверждать, что вы делаете свое приложение более независимым от базы данных, и использование H2 только для тестирования - это лишь совпадение. Позже вы можете использовать H2 в качестве базы данных, поставляемой с пробной версией вашего продукта. Или вы могли бы поддерживать другие базы данных в дополнение к Oracle и H2 позже.

h2-база данных

Чтобы избежать зависимости времени компиляции от H2, вы можете использовать:

String url = st.getConnection().getMetaData().getURL();
boolean isH2 = url.startsWith("jdbc:h2:");
if (isH2) {
    ...
}

Есть и другие способы, например, getMetaData().getDatabaseProductName().equals("H2") - в основном сравнивать с String вместо объектов Class. Конечно, это не так безопасно во время компиляции, с другой стороны, H2 может вернуть другой класс соединения в будущем, поэтому JdbcConnection также нестабилен.

0 голосов
/ 04 мая 2018
public class Oracle10gDialectWithXMLType extends Oracle10gDialect {
    public Oracle10gDialectWithXMLType() {
        registerHibernateType(XMLType._SQL_TYPECODE, "XMLTYPE");
        registerColumnType(XMLType._SQL_TYPECODE, "XMLTYPE");
    }
}

и добавьте его как свой диалект в свойствах.

...