2009-08-24 6 views
27

Ce que je veux:Puis-je rendre une entité Hibernate intégrée non nulle?

@Embedded(nullable = false) 
private Direito direito; 

Cependant, comme vous le savez il n'y a pas un tel attribut à @Embeddable.

Existe-t-il une manière correcte de le faire? Je ne veux pas de solutions de contournement.

+0

Voulez-vous dire un élément composite? – Zoidberg

+0

Oui. Pourquoi je ne peux pas répondre avec moins de 15 caractères? –

+0

Je ne suis pas sûr de savoir comment le faire avec des annotations, mais je peux vous montrer le xml – Zoidberg

Répondre

33

Les composants intégrables (ou les éléments composites, peu importe comment vous les appelez) contiennent généralement plus d'une propriété et sont donc mappés sur plusieurs colonnes. Le composant entier étant nul peut donc être traité de différentes manières; La spécification J2EE ne dicte pas d'une manière ou d'une autre. Hibernate considère que le composant est NULL si toutes ses propriétés sont NULL (et vice versa). Vous pouvez donc déclarer une (quelconque) des propriétés non nulle (soit dans @Embeddable ou dans le cadre de @AttributeOverride sur @Embedded) pour obtenir ce que vous voulez.

Alternativement, si vous utilisez Hibernate Validator, vous pouvez annoter votre propriété avec @NotNull, bien que cela n'aboutira qu'à une vérification au niveau de l'application, et non au niveau db.

+0

+1, une bonne réponse – skaffman

+0

Merci! Va ajouter @Nullable à une propriété du composite. –

+0

Ne fonctionne pas pour moi. Est-il possible qu'il y ait un problème si '@ Embeddable' n'a qu'un seul champ, qui est annoté avec' @Access (AccessType.FIELD) '? –

11

Ajouter un champ factice dans la classe marquée @Embeddable.

@Formula("0") 
private int dummy; 

Voir https://issues.jboss.org/browse/HIBERNATE-50.

+0

Cela fonctionne-t-il toujours pour vous? Pour moi ça ne fonctionne pas ... –

+0

Cela fonctionne avec Hibernate 3.5.3-Final. – adam0404

+0

Ne fonctionne pas pour moi avec Hibernate 4.3.7.Final (essayé plusieurs choses similaires, aucune travaillé) – NoUsername

1

Je n'étais pas trop ravi de l'une ou l'autre des suggestions faites précédemment, alors j'ai créé un aspect qui permettrait de gérer cela pour moi.

Ceci n'est pas entièrement testé, et certainement pas testé contre les collections d'objets incorporés, donc attention à l'acheteur. Cependant, semble fonctionner pour moi jusqu'à présent.

Fondamentalement, intercepte le getter au champ @Embedded et s'assure que le champ est rempli.

public aspect NonNullEmbedded { 

    // define a pointcut for any getter method of a field with @Embedded of type Validity with any name in com.ia.domain package 
    pointcut embeddedGetter() : get(@javax.persistence.Embedded * com.company.model..*); 


    /** 
    * Advice to run before any Embedded getter. 
    * Checks if the field is null. If it is, then it automatically instantiates the Embedded object. 
    */ 
    Object around() : embeddedGetter(){ 
     Object value = proceed(); 

     // check if null. If so, then instantiate the object and assign it to the model. 
     // Otherwise just return the value retrieved. 
     if(value == null){ 
      String fieldName = thisJoinPoint.getSignature().getName(); 
      Object obj = thisJoinPoint.getThis(); 

      // check to see if the obj has the field already defined or is null 
      try{ 
       Field field = obj.getClass().getDeclaredField(fieldName); 
       Class clazz = field.getType(); 
       value = clazz.newInstance(); 
       field.setAccessible(true); 
       field.set(obj, value); 
      } 
      catch(NoSuchFieldException | IllegalAccessException | InstantiationException e){ 
       e.printStackTrace(); 
      } 
     } 

     return value; 
    } 
} 
1

Vous pouvez utiliser un getter nullsafe.

public Direito getDireito() { 
    if (direito == null) { 
     direito = new Direito(); 
    } 
    return direito; 
} 
+5

Veuillez noter que votre entité sera marquée comme étant sale à chaque lecture, provoquant l'augmentation de la version d'Hibernate. Cela conduira à des exceptions de verrouillage optimistes. – Arlo

+0

Cette solution déclenche l'instruction de mise à jour SQL vers le serveur de base de données, ce qui entraîne des problèmes tels que la concurrence entre les threads et les problèmes de performances. –

Questions connexes