Pergunta

Há muito se pode encontrar sobre isso pesquisando um pouco, mas eu não tenho bastante encontrada uma solução viável para este problema.

Basicamente o que eu tenho é um grande CLOB em uma determinada classe que eu quero ter carregado sob demanda. A maneira ingênua de fazer isso seria:

class MyType {

  // ...

  @Basic(fetch=FetchType.LAZY)
  @Lob
  public String getBlob() {
    return blob;
  }
}

Isso não funciona, porém, aparentemente devido ao fato de que eu estou usando drivers Oracle, ou seja Lob objetos não são tratados como alças simples, mas são sempre carregados. Ou então eu tenho sido levado a acreditar de minhas incursões. Há uma solução que utiliza instrumentos especiais para carregamento propriedade preguiçoso, mas como a documentação do Hibernate parecem sugerir que eles estão a menos de interessados ??em fazer esse trabalho corretamente, então eu prefiro não ir por esse caminho. Especialmente com ter que executar um passe de compilação extra e todos.

Assim, a próxima solução que eu tinha imaginado foi separar esse objeto para outro tipo e definir uma associação. Infelizmente, enquanto os documentos dão informações conflitantes, é evidente para mim que o carregamento lento não funciona em OneToOne associações com chave primária compartilhada. Eu definir um lado da associação como ManyToOne, mas não tenho certeza de como fazer isso quando há uma chave primária compartilhado.

Assim, alguém pode sugerir a melhor maneira de fazer isso?

Foi útil?

Solução

De acordo com a este única PostgreSQL implementos Blob como realmente preguiçoso. Portanto, a melhor solução é mover o blob para outra mesa. Você tem que usar uma chave primária compartilhada? Por que não fazer algo como isto:

public class MyBlobWrapper {
    @Id
    public Long getId() {
       return id;
    }
    @Lob
    public String getBlob() {
        return blob;
    }
    @OneToOne(fetch=FetchType.LAZY,optional=false) 
    public MyClass getParent() {
        return parent;
    }
}

Outras dicas

Em vez de fazer equilibristics com anotações de hibernação, pode apenas tentar converter o campo de String em Clob (ou Blob):

@Lob  
@Basic(fetch=FetchType.LAZY)  
@Column(name = "FIELD_COLUMN")  
public Clob getFieldClob() {  
  return fieldClob;  
}  

public void setFieldClob(Clob fieldClob) {  
  this.fieldClob = fieldClob;  
}  

@Transient  
public String getField()  
{  
  if (this.getFieldClob()==null){  
    return null;  
  }  
  try {  
    return MyOwnUtils.readStream(this.getFieldClob().getCharacterStream());  
  } catch (Exception e) {  
    e.printStackTrace();  
  }  

  return null;  
}  

public void setField(String field)  
{  
  this.fieldClob = Hibernate.createClob(field);  
} 

funcionou para mim (o campo começou a carregar preguiçosamente, no Oracle).

Uma vez que você parece estar usando Hibernate Eu quero saber se o problema está relacionado com o seguinte recurso de hibernação:

Usando preguiçoso Propriedades Buscando

Hibernate3 suporta a busca lazy de propriedades individuais. Esta técnica de optimização é também conhecido como grupos buscar. Por favor note que isto é principalmente um recurso de marketing; otimizar linha lê é muito mais importante do que a otimização da coluna lê. No entanto, apenas o carregamento algumas propriedades de uma classe pode ser útil em casos extremos. Para exemplo, quando tabelas legadas podem ter centenas de colunas e os dados modelo não pode ser melhorado.

preguiçoso propriedade de carga requer Buildtime bytecode instrumentação . E se suas classes persistentes não são reforçadas, Hibernate irá ignorar preguiçoso configurações de propriedade e retorno para buscar imediato.

Bytecode Instrumentação para Hibernate Usando Maven .

post antigo, mas apenas um que me ajudou, graças à resposta @TadeuszKopec.

parece que é difícil de fazer o carregamento lento de blob com JPA. Tentei associação @OneToOne, mas complica mais do que ajuda. Acabei de me mudar os bytes para outra classe, sem associação com MyClass (pai mesma mesa, mesmo id.):

@Entity
@Table(name="MyTable")
public class MyBlobWrapper{

    @Id
    @Column(name = "id") // id of MyTable, same as MyClass
    private Long id;

    @Lob
    private byte[] bytes;   
}

@Entity
@Table(name="MyTable")
public class MyClass{

    @Id
    @Column(name = "id")
    private Long id;
    // other fields  .....
}

Apenas lembre-se de pai flush, antes de salvar o blob:

 em.persist(parent);
 em.flush();
 em.merge(new MyBlobWrapper(parent_id,new byte[1000]));

Agora eu posso carregar o pdf sozinho:

String query1 = " select PDF from MyBlobWrapper PDF where PDF.id = :id";

Eu sou apenas novato com JPA, espero que ajude.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top