¿Puedo hacer una entidad de hibernación incrustado no anulable?
-
19-09-2019 - |
Pregunta
Lo que quiero:
@Embedded(nullable = false)
private Direito direito;
Sin embargo, como saben que no hay tal atributo a @Embeddable.
¿Hay una manera correcta de hacer esto? No quiero soluciones.
Solución
Los componentes insertable (o elementos compuestos, lo que quieras llamarlos) suelen contener más de una propiedad y por lo tanto se asignan a más de una columna. Por consiguiente, el ser componente de toda nulo puede ser tratada de diferentes maneras; especificación J2EE no dicta una forma u otra.
Hibernate considera componente a NULL si todas sus propiedades son NULL (y viceversa). Por lo tanto, puede declarar una (cualquiera) de las propiedades de ser no nulo (ya sea dentro @Embeddable
o como parte de @AttributeOverride
en @Embedded
) para conseguir lo que quiere.
Por otra parte, si usted está usando Hibernate Validator puede anotar su propiedad con @NotNull
aunque esto sólo resultará en jaque a nivel de aplicación, no db-nivel.
Otros consejos
Es posible usar "hibernate.create_empty_composites.enabled", ya que Hibernate 5.1 para cambiar este comportamiento (ver https://hibernate.atlassian.net/browse/HHH-7610 )
Añadir campo ficticio en la clase que está marcado @Embeddable.
@Formula("0")
private int dummy;
Yo no estaba muy emocionado con cualquiera de las sugerencias hechas anteriormente, así que creé un aspecto que se ocuparía de esto por mí.
Esto no está completamente probado, y definitivamente no probado contra las colecciones de objetos incrustados, por lo que el comprador y el cuidado. Sin embargo, parece que funciona para mí hasta ahora.
Básicamente, intercepta el getter al campo @Embedded
y asegura que el campo se rellena.
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;
}
}
Puede utilizar un captador nullsafe.
public Direito getDireito() {
if (direito == null) {
direito = new Direito();
}
return direito;
}