Domanda

Ho qualche problema a mappare un array di byte in un database MySQL in Hibernate e mi chiedevo se mi manca qualcosa di ovvio. La mia classe sembra approssimativamente così:

public class Foo {
    private byte[] bar;

    // Getter and setter for 'bar'
}

La tabella è definita in questo modo in MySQL 5.5:

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

E la mappatura Hibernate 3.6.2 sembra simile a questa:

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

Sto usando HBM2DDL solo per la convalida e mi dà questo errore quando distribuisco l'applicazione:

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

Se usare type = "binario" nella mappatura non causerebbe che Hibernate si aspettasse che il tipo di colonna sia binario (anziché tinyBlob), non so cosa farebbe. Ho trascorso un po 'di tempo a cercare su Google questo ma non sono riuscito a trovare l'errore esatto. Le soluzioni per errori simili erano di ...

  1. Specificare la "lunghezza" suu003Cproperty> . Ciò cambia quale tipo si aspetta Hibernate, ma è sempre una varietà di BLOB invece del tipo "binario" che sta trovando.
  2. Invece di dichiarare un "tipo" sull'elemento della proprietà, nidificare un elemento di colonna e dargli un attributo di tipo SQL. Quel lavoro, ma ciò renderebbe anche il legame specifico per MySQL, quindi vorrei evitarlo se possibile.

Qualcosa si distingue su questa configurazione che causerebbe questa discrepanza? Se specifico type = "binario" anziché "blob", perché Hibernate si aspetta un blob anziché un binario?

È stato utile?

Soluzione

Credo che il problema sia type="binary".

Quel tipo è un tipo in letargo e generico. Non mappa direttamente i tipi specifici per il motore DB. Sono tradotti in diversi tipi SQL in base al driver che stai utilizzando. Apparentemente il driver MySQL mappa il tipo ibernato "binario" a un tinyblob.

L'elenco completo dei tipi di ibernazione è disponibile qui.

Hai 2 opzioni. È possibile modificare il tuo script di Crea tabella per archiviare quella colonna con un tipo di dati TinyBlob. Quindi la convalida in letargo non fallirebbe e la tua applicazione funzionerebbe. Questa sarebbe la soluzione suggerita.

La seconda opzione dovrebbe essere utilizzata solo se è necessario utilizzare il tipo di dati binari nel DB. Quello che puoi fare è specificare un tipo SQL nella mappatura di ibernazione in modo da far rispettare Hibernate di utilizzare il tipo desiderato. La mappatura sarebbe così:

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

Il lato principale di questo è che perdi l'indipendenza del motore DB, motivo per cui la maggior parte delle persone usa Hibernate in primo luogo. Questo codice funzionerà solo sui motori DB con il tipo di dati binari.

Altri suggerimenti

Ciò che abbiamo finito per risolvere un problema simile a questo è scrivere il nostro utente personalizzato.

Itypes sono relativamente facili da implementare. Basta creare una classe che implementa org.hibernate.usertype.usertype e implementare i metodi @Override.

Nelle tue definizioni in letargo, l'utilizzo di un tipo di utente è abbastanza semplice:

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

In poche parole, ciò che farà è eseguire questa classe per leggere e scrivere i dati dal database. In particolare, vengono utilizzati i metodi NullSafeget e NullSafet.

Nel nostro caso, abbiamo usato questo per comprimere GZIP i dati binari prima di scriverli nel database e disprezzarli come lettura. Ciò nasconde il fatto che i dati vengono compressi dall'applicazione utilizzando questi dati.

Penso che ci sia una soluzione facile per mappare colonne binarie in letargo.

Le colonne "binarie" possono essere facilmente mappate su "java.util.uuid" nelle classi di entità Hibernate.

Per EG la definizione della colonna sarà simile

`tokenValue` BINARY(16) NOT NULL

Hibernate Entitiy avrà di seguito il codice per supportare la colonna binaria

private UUID tokenValue;

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

public void setTokenValue(UUID sessionTokenValue) {
    this.tokenValue = tokenValue;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top