Отображение Java-байта [] в двоичный файл MySQL (64) в Hibernate - PullRequest
7 голосов
/ 12 мая 2011

У меня возникли проблемы с отображением байтового массива в базу данных MySQL в Hibernate, и мне было интересно, если я упускаю что-то очевидное. Мой класс выглядит примерно так:

public class Foo {
    private byte[] bar;

    // Getter and setter for 'bar'
}

Таблица определяется следующим образом в MySQL 5.5:

CREATE TABLE foo (
bar BINARY(64) NOT NULL)

И отображение Hibernate 3.6.2 выглядит примерно так:

<hibernate-mapping>
    <class name="example.Foo" table="foo">
        <property name="bar" column="bar" type="binary" />
    </class>
</hibernate-mapping>

Я использую hbm2ddl только для проверки, и она выдает мне эту ошибку при развертывании приложения:

Wrong column type in foo for column bar. Found: binary, expected: tinyblob

Если использование type = "binary" в отображении не заставит Hibernate ожидать, что тип столбца будет двоичным (вместо tinyblob,), я не знаю, что будет. Я потратил некоторое время на поиск в Google, но не смог найти точную ошибку. Решения для подобных ошибок были ...

  1. Укажите «длину» на . Это меняет то, что ожидает Hibernate, но это всегда разновидность большого двоичного объекта, а не двоичный тип, который он находит.
  2. Вместо того, чтобы объявлять «тип» в элементе свойства, вложите элемент столбца и присвойте ему атрибут sql-type. Это работает, но это также сделало бы привязку специфичной для MySQL, поэтому я хотел бы избежать ее, если это возможно.

Что-то выделяется в этой настройке, что может привести к этому несоответствию? Если я укажу type = "binary" вместо "blob", почему Hibernate ожидает двоичный объект вместо двоичного?

Ответы [ 3 ]

4 голосов
/ 14 мая 2011

Я полагаю, что проблема в type="binary".

Этот тип является спящим, универсальным типом.Он не привязан напрямую к конкретным типам движка БД.Они переводятся в разные типы SQL в зависимости от используемого вами драйвера.По-видимому, драйвер MySQL отображает «двоичный» тип гибернации на крошечный шарик.

Полный список типов гибернации доступен здесь .

У вас есть 2 варианта.Вы можете изменить свой скрипт CREATE TABLE, чтобы хранить этот столбец с типом данных tinyblob.Тогда ваша проверка гибернации не провалится, и ваше приложение будет работать.Это было бы предлагаемое решение.

Второй вариант следует использовать, только если вы должны использовать тип данных BINARY в БД.Что вы можете сделать, так это указать sql-тип в отображении hibernate, чтобы использовать hibernate для использования нужного типа.Сопоставление будет выглядеть следующим образом:

<property name="bar">
  <column name="bar" sql-type="binary" />
</property>

Основной недостаток этого способа - потеря независимости от DB-двигателя, поэтому большинство людей в первую очередь используют спящий режим.Этот код будет работать только на механизмах БД, которые имеют тип данных BINARY.

2 голосов
/ 14 мая 2011

В итоге мы решили проблему, подобную этой, - написали наш собственный пользовательский тип пользователя.

UserTypes относительно просты в реализации. Просто создайте класс, который реализует org.hibernate.usertype.UserType и реализует методы @override.

в ваших определениях гибернации использовать тип пользователя довольно просто:

<property name="data" type="com.yourpackage.hibernate.CustomBinaryStreamUserType" column="binary_data" />

Проще говоря, это будет выполнять этот класс для чтения и записи данных из базы данных. В частности, используются методы nullSafeGet и nullSafeSet.

В нашем случае мы использовали это, чтобы сжать двоичные данные gzip перед записью в базу данных и распаковать их при считывании. Это скрывает тот факт, что данные сжимаются из приложения с использованием этих данных.

0 голосов
/ 24 августа 2014

Я думаю, что есть простое решение для отображения двоичных столбцов в hibernate.

Столбцы "BINARY" могут быть легко сопоставлены с "java.util.UUID" в классах сущностей hibernate.

Например, определение столбца будет выглядеть так:

`tokenValue` BINARY(16) NOT NULL

Hibernate Entitiy будет иметь код ниже для поддержки столбца BINARY

private UUID tokenValue;

@Column(columnDefinition = "BINARY(16)", length = 16)
public UUID getTokenValue() {
    return this.tokenValue;
}

public void setTokenValue(UUID sessionTokenValue) {
    this.tokenValue = tokenValue;
}
...