7

Hibernate でバイト配列を MySQL データベースにマッピングするのに問題があり、明らかな何かが欠けているのではないかと考えていました。私のクラスはおおよそ次のようになります。

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 ではなく) バイナリであることを期待しない場合、どうなるかわかりません。これをグーグルで検索しましたが、正確なエラーを見つけることができませんでした。同様のエラーの解決策は...

  1. <プロパティ>に「長さ」を指定します。これにより、Hibernate が期待する型が変わりますが、検出される「バイナリ」型ではなく、常に何らかの種類の blob になります。
  2. プロパティ要素で「型」を宣言する代わりに、列要素をネストして、それに sql-type 属性を与えます。それは機能しますが、バインディングが MySQL に固有のものにもなるため、可能であれば避けたいと思います。

この設定で、この不一致の原因となる何か目立ったものはありますか? 「blob」の代わりに type="binary" を指定すると、Hibernate がバイナリではなく blob を期待するのはなぜですか?

4

3 に答える 3

4

私は問題があると信じていますtype="binary"

その型は休止状態のジェネリック型です。DB エンジン固有のタイプに直接マップすることはありません。これらは、使用しているドライバーに基づいてさまざまな SQL タイプに変換されます。どうやら、MySQL ドライバーは、休止状態のタイプ「バイナリ」を tinyblob にマップしているようです。

ハイバネート タイプの完全なリストは、こちらから入手できます。

2 つのオプションがあります。CREATE TABLE スクリプトを変更して、その列を tinyblob データ型で格納できます。その後、休止状態の検証は失敗せず、アプリケーションは機能します。これが推奨される解決策になります。

2 番目のオプションは、DB で BINARY データ型を使用する必要がある場合にのみ使用してください。できることは、hibernate マッピングで sql-type を指定して、必要なタイプを使用するように hibernate を強制することです。マッピングは次のようになります。

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

これの主な欠点は、DB エンジンの独立性が失われることです。これが、ほとんどの人が最初に hibernate を使用する理由です。このコードは、BINARY データ型を持つ DB エンジンでのみ機能します。

于 2011-05-13T20:40:12.440 に答える
2

これに似た問題を解決するために私たちがやったことは、独自のカスタムUserTypeを作成することです。

UserTypesは比較的簡単に実装できます。org.hibernate.usertype.UserTypeを実装するクラスを作成し、@overrideメソッドを実装するだけです。

休止状態の定義では、ユーザータイプの使用は非常に簡単です。

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

簡単に言えば、これが行うことは、データベースからデータを読み書きするためにこのクラスを実行することです。具体的には、メソッドnullSafeGetおよびnullSafeSetが使用されます。

この例では、これを使用して、データベースに書き込む前にバイナリデータをgzip圧縮し、読み取り時に解凍します。これにより、データがこのデータを使用してアプリケーションから圧縮されるという事実が隠されます。

于 2011-05-13T20:37:42.533 に答える