Eu tenho um aplicativo que usa anotações Hibernate 3.1 e JPA. Possui alguns objetos com atributos byte [] (1k - 200k de tamanho). Ele usa a anotação JPA @Lob, e o hibernate 3.1 pode lê-los perfeitamente em todos os principais bancos de dados - parece ocultar as peculiaridades do fornecedor do JDBC Blob (como deveria).
@Entity
public class ConfigAttribute {
@Lob
public byte[] getValueBuffer() {
return m_valueBuffer;
}
}
Tivemos que atualizar para 3.5, quando descobrimos que o hibernate 3.5 quebra (e não corrige) essa combinação de anotação no postgresql (sem solução alternativa). Não encontrei uma correção clara até agora, mas notei que se eu apenas remover o @Lob, ele usa o tipo bytea do postgresql (que funciona, mas apenas no 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.
Estou procurando uma maneira de ter uma única classe anotada (com uma propriedade blob) que seja portátil entre os principais bancos de dados.
- Qual é a maneira portátil de anotar uma propriedade byte []?
- Isso foi corrigido em alguma versão recente do hibernate?
Atualização: Depois de ler este blog , finalmente descobri qual era a solução alternativa original para o problema do JIRA: Aparentemente, você deve remover @Lob e anotar a propriedade como:
@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType")
byte[] getValueBuffer() {...
No entanto, isso não funciona para mim - ainda recebo OIDs em vez de bytea; no entanto, funcionou para o autor da edição do JIRA, que parecia querer oid.
Após a resposta de A. Garcia, tentei esta combinação, que na verdade funciona no postgresql, mas não no oracle.
@Type(type="org.hibernate.type.BinaryType")
byte[] getValueBuffer() {...
O que eu realmente preciso fazer é controlar para qual @ org.hibernate.annotations.Type a combinação (@Lob + byte [] é mapeada) (no postgresql).
Aqui está o snippet de 3.5.5.Final de MaterializedBlobType (sql type Blob). De acordo com o blog de Steve, postgresql deseja que você use Streams para bytea (não me pergunte por quê) e o tipo de Blob personalizado do postgresql para oids. Observe também que o uso de setBytes () em JDBC também serve para bytea (por experiência anterior). Portanto, isso explica por que usar-streams não tem efeito, ambos assumem 'bytea'.
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 );
}
}
Isto resulta em:
ERROR: column "signature" is of type oid but expression is of type bytea
Atualizar A próxima pergunta lógica é: "por que não mudar as definições da tabela manualmente para bytea" e manter o (@Lob + byte [])? Isso faz o trabalho, ATÉ tentar armazenar um byte nulo []. Que o driver postgreSQL pensa que é uma expressão de tipo OID e o tipo de coluna é bytea - isso ocorre porque hibernate (corretamente) chama JDBC.setNull () em vez de JDBC.setBytes (null) que o driver PG espera.
ERROR: column "signature" is of type bytea but expression is of type oid
O sistema de tipo no hibernate é atualmente um 'trabalho em andamento' (de acordo com o comentário de depreciação 3.5.5). Na verdade, grande parte do código 3.5.5 está obsoleto, é difícil saber o que olhar ao subclassificar o PostgreSQLDialect).
AFAKT, Types.BLOB / 'oid' no postgresql deve ser mapeado para algum tipo personalizado que usa o acesso JDBC do estilo OID (ou seja, objeto PostgresqlBlobType e NOT MaterializedBlobType). Na verdade, nunca usei o Blobs com o postgresql com sucesso, mas sei que o bytea simplesmente funciona como um / seria de esperar.
No momento, estou olhando para BatchUpdateException - é possível que o driver não ofereça suporte ao envio em lote.
Excelente citação de 2004: "Para resumir minhas divagações, eu diria que devemos esperar que o driver JDBC faça os LOBs corretamente antes de alterar o Hibernate."
Referências:
- 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/