Mam aplikację używającą hibernacji 3.1 i adnotacji JPA. Ma kilka obiektów z atrybutami byte [] (o rozmiarze 1k - 200k). Używa adnotacji JPA @Lob, a hibernacja 3.1 może je dobrze odczytać we wszystkich głównych bazach danych - wydaje się, że ukrywa osobliwości dostawcy JDBC Blob (tak jak powinno).
@Entity
public class ConfigAttribute {
@Lob
public byte[] getValueBuffer() {
return m_valueBuffer;
}
}
Musieliśmy uaktualnić do wersji 3.5, kiedy odkryliśmy, że hibernacja 3.5 przerywa (i nie naprawi) tej kombinacji adnotacji w postgresql (bez obejścia). Jak dotąd nie znalazłem wyraźnej poprawki, ale zauważyłem, że jeśli po prostu usunę @Lob, używa on bajtu typu postgresql (który działa, ale tylko na postgres).
annotation postgres oracle works on
-------------------------------------------------------------
byte[] + @Lob oid blob oracle
byte[] bytea raw(255) postgresql
byte[] + @Type(PBA) oid blob oracle
byte[] + @Type(BT) bytea blob postgresql
once you use @Type, @Lob seems to not be relevant
note: oracle seems to have deprecated the "raw" type since 8i.
Szukam sposobu, aby mieć jedną klasę z adnotacjami (z właściwością blob), która jest przenośna w głównych bazach danych.
- Jaki jest przenośny sposób dodawania adnotacji do właściwości byte []?
- Czy zostało to naprawione w jakiejś najnowszej wersji hibernacji?
Aktualizacja: po przeczytaniu tego bloga w końcu odkryłem, jakie było pierwotne obejście problemu z JIRA: Najwyraźniej powinieneś porzucić @Lob i dodać adnotację do właściwości jako:
@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType")
byte[] getValueBuffer() {...
Jednak to nie działa dla mnie - nadal otrzymuję identyfikatory OID zamiast bajtów; to jednak zadziałało dla autora wydania JIRA, który wydawał się chcieć oid.
Po odpowiedzi od A. Garcii, wypróbowałem następnie tę kombinację, która faktycznie działa na postgresql, ale nie na Oracle.
@Type(type="org.hibernate.type.BinaryType")
byte[] getValueBuffer() {...
To, co naprawdę muszę zrobić, to kontrolować, które @ org.hibernate.annotations.Type kombinację (@Lob + bajt [] zostanie zmapowane) do (na postgresql).
Oto fragment z 3.5.5.Final z MaterializedBlobType (sql type Blob). Według bloga Steve'a, postgresql chce, abyś używał strumieni dla bajtów (nie pytaj mnie dlaczego) i niestandardowego typu Bloba postgresql dla oids. Zauważ również, że użycie setBytes () na JDBC jest również dla bytea (z wcześniejszych doświadczeń). To wyjaśnia, dlaczego strumienie użycia nie mają wpływu, obie przyjmują „bajt”.
public void set(PreparedStatement st, Object value, int index) {
byte[] internalValue = toInternalFormat( value );
if ( Environment.useStreamsForBinary() ) {
// use streams = true
st.setBinaryStream( index,
new ByteArrayInputStream( internalValue ), internalValue.length );
}
else {
// use streams = false
st.setBytes( index, internalValue );
}
}
To skutkuje:
ERROR: column "signature" is of type oid but expression is of type bytea
Aktualizacja Kolejne logiczne pytanie brzmi: „dlaczego po prostu nie zmienić ręcznie definicji tabeli na bajtowe” i zachować (@Lob + bajt [])? To nie praca, DOPÓKI próbie zapisania null byte []. Który sterownik postgreSQL uważa za wyrażenie typu OID, a typ kolumny to bajt - dzieje się tak, ponieważ hibernacja (słusznie) wywołuje JDBC.setNull () zamiast JDBC.setBytes (null), czego oczekuje sterownik PG.
ERROR: column "signature" is of type bytea but expression is of type oid
System typów w hibernacji jest obecnie w toku (zgodnie z komentarzem do wycofania 3.5.5). W rzeczywistości tak duża część kodu 3.5.5 jest przestarzała, że trudno jest wiedzieć, na co zwrócić uwagę podczas tworzenia podklas PostgreSQLDialect).
AFAKT, Types.BLOB / 'oid' w postgresql powinny być odwzorowane na jakiś niestandardowy typ, który wykorzystuje dostęp JDBC w stylu OID (tj. Obiekt PostgresqlBlobType i NOT MaterializedBlobType). Nigdy tak naprawdę nie korzystałem z Blobów z postgresql, ale wiem, że bytea po prostu działa tak, jak się spodziewałem.
Obecnie patrzę na wyjątek BatchUpdateException - możliwe, że sterownik nie obsługuje przetwarzania wsadowego.
Świetny cytat z 2004 roku: „Podsumowując moje wędrówki, powiedziałbym, że powinniśmy poczekać, aż sterownik JDBC poprawnie wykona LOB przed zmianą Hibernate”.
Bibliografia:
- https://forum.hibernate.org/viewtopic.php?p=2393203
- https://forum.hibernate.org/viewtopic.php?p=2435174
- http://hibernate.atlassian.net/browse/HHH-4617
- http://postgresql.1045698.n5.nabble.com/Migration-to-Hibernate-3-5-final-td2175339.html
- https://jira.springframework.org/browse/SPR-2318
- https://forums.hibernate.org/viewtopic.php?p=2203382&sid=b526a17d9cf60a80f13d40cf8082aafd
- http://virgo47.wordpress.com/2008/06/13/jpa-postgresql-and-bytea-vs-oid-type/