chargement Paresseusement un clob en veille prolongée
Question
Il y a beaucoup on peut trouver sur ce googler un peu, mais je n'ai pas encore trouvé une solution viable à ce problème.
En fait ce que j'ai est un grand CLOB sur une classe particulière que je veux avoir chargé à la demande. La façon naïve de le faire serait:
class MyType {
// ...
@Basic(fetch=FetchType.LAZY)
@Lob
public String getBlob() {
return blob;
}
}
Cela ne fonctionne pas bien, apparemment en raison du fait que je utilise les pilotes d'oracle, à savoir des objets Lob ne sont pas traités comme des poignées simples mais sont toujours chargées. Ou alors j'ai été amené à croire de mes incursions. Il y a une solution qui utilise une instrumentation spéciale pour le chargement de la propriété paresseux, mais comme la mise en veille prolongée docs semblent suggérer qu'ils sont moins intéressés à faire ce travail correctement, donc je préfère ne pas aller dans cette voie. Surtout d'avoir à lancer une passe de compilation supplémentaire et tous.
Alors, la prochaine solution que je l'avais envisagé était séparer cet objet à un autre type et définissant une association. Malheureusement, alors que les documents donnent des informations contradictoires, il est évident pour moi que le chargement paresseux ne fonctionne pas sur les associations ONEtoONE avec clé primaire partagée. Je mis un côté de l'association ManyToOne, mais je ne suis pas tout à fait sûr de savoir comment faire quand il y a une clé primaire partagée.
Alors quelqu'un peut-il proposer la meilleure façon d'aller à ce sujet?
La solution
Selon cette que PostgreSQL implémente Blob comme vraiment paresseux. Donc, la meilleure solution est de déplacer le blob à une autre table. Avez-vous d'utiliser une clé primaire partagée? Pourquoi ne pas vous faire quelque chose comme ceci:
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;
}
}
Autres conseils
Au lieu de faire équilibrisme avec annotations mise en veille prolongée, on peut juste essayer convertir le champ de String
en 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);
}
A travaillé pour moi (le champ a commencé à charger paresseusement, sur Oracle).
Puisque vous semblez utiliser Hibernate Je me demande si votre problème est lié à la fonction Veille prolongée suivant:
Utilisation des propriétés Lazy semblables dans
Hibernate3 supporte le chargement tardif des propriétés individuelles. Cette technique d'optimisation est également connu sous le nom des groupes aller chercher. S'il vous plaît noter que c'est surtout une fonction de marketing; optimisation de la lecture est beaucoup plus importante que l'optimisation de la colonne se lit comme suit. Cependant, seulement le chargement certaines propriétés d'une classe pourrait être utile dans les cas extrêmes. Pour par exemple, lorsque les tables existantes ont des centaines de colonnes et les données modèle ne peut pas être améliorée.
chargement de la propriété Lazy nécessite une instrumentation de bytecode à la compilation . Si vos classes persistantes ne sont pas, Hibernate ignorera paresseux paramètres de propriété et le retour de chargement immédiat.
Voir bytecode Instrumentation pour Hibernate utilisant Maven .
Ancien poste, mais seulement celui qui m'a aidé, grâce à la réponse @TadeuszKopec.
On dirait qu'il est difficile de faire le chargement paresseux de blob avec JPA. J'ai essayé association @OneToOne, mais il complique plus que l'aide. Je viens de déménager les octets à une autre classe, sans association avec MyClass (parent Même table, même 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 .....
}
Rappelez-vous simplement de parent rincer, avant d'enregistrer le blob:
em.persist(parent);
em.flush();
em.merge(new MyBlobWrapper(parent_id,new byte[1000]));
Maintenant, je peux charger le pdf seul:
String query1 = " select PDF from MyBlobWrapper PDF where PDF.id = :id";
Je suis débutant juste avec JPA, espoir qui aide.