Puis-je faire une entité Hibernate intégrée non annulable?
-
19-09-2019 - |
Question
Ce que je veux:
@Embedded(nullable = false)
private Direito direito;
Cependant, comme vous le savez il n'y a pas un tel attribut à @Embeddable.
Y at-il une bonne façon de le faire? Je ne veux pas des solutions de contournement.
La solution
composants intégrables (ou des éléments composites, tout ce que vous voulez les appeler) contiennent généralement plus d'une propriété et sont ainsi mis en correspondance avec plus d'une colonne. peut donc être la totalité du composant nulle être traité de différentes manières; spécification J2EE ne dicte pas une manière ou d'une autre.
Hibernate considère le composant à NULL si toutes ses propriétés sont NULL (et vice versa). Vous pouvez donc déclarer un (tout) des propriétés ne pas être nulle (soit dans @Embeddable
ou dans le cadre de @AttributeOverride
sur @Embedded
) pour obtenir ce que vous voulez.
Par ailleurs, si vous utilisez Hibernate Validator vous pouvez annoter votre propriété avec @NotNull
bien que cela ne permettra d'obtenir l'enregistrement niveau de l'application, et non au niveau db.
Autres conseils
Il est possible d'utiliser "hibernate.create_empty_composites.enabled" puisqu'Hibernate 5.1 pour modifier ce comportement (voir https://hibernate.atlassian.net/browse/HHH-7610 )
Ajouter un champ factice dans la classe qui est marquée @Embeddable.
@Formula("0")
private int dummy;
Je n'étais pas trop heureux avec l'une des suggestions faites précédemment, je créé un aspect qui traiterait pour moi.
Ce n'est pas complètement testé, et certainement pas testé contre les collections d'objets embarqués, donc acheteur averti. Cependant, semble fonctionner pour moi jusqu'à présent.
Fondamentalement, intercepte le getter dans le champ @Embedded
et veille à ce 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;
}
}
Vous pouvez utiliser un getter nullsafe.
public Direito getDireito() {
if (direito == null) {
direito = new Direito();
}
return direito;
}