Posso fazer uma entidade Hibernate incorporado não-nulo?
-
19-09-2019 - |
Pergunta
O que eu quero:
@Embedded(nullable = false)
private Direito direito;
No entanto, como você sabe que não há tal atributo para @Embeddable.
Existe uma maneira correta de fazer isso? Eu não quero soluções alternativas.
Solução
componentes embutidos (ou elementos compostos, o que você quiser chamá-los) geralmente contêm mais de uma propriedade e, portanto, são mapeados para mais de uma coluna. Todo o ser nulo componente pode, portanto, ser tratado de maneiras diferentes; J2EE especificação faz uma maneira não ditar ou de outra.
hibernação considera componente a ser NULL se todas as suas propriedades são NULL (e vice-versa). Portanto, você pode declarar um (qualquer) das propriedades a ser não nula (ou dentro @Embeddable
ou como parte de @AttributeOverride
em @Embedded
) para conseguir o que deseja.
Como alternativa, se você estiver usando Hibernate Validator você pode anotar o seu imóvel com @NotNull
embora isso só vai resultar em seleção de nível aplicativo, não db-nível.
Outras dicas
É possível usar "hibernate.create_empty_composites.enabled" desde Hibernate 5.1 para alterar esse comportamento (veja https://hibernate.atlassian.net/browse/HHH-7610 )
Adicionar manequim campo na classe que está marcado @Embeddable.
@Formula("0")
private int dummy;
Eu não estava muito emocionado com qualquer uma das sugestões feitas anteriormente, então eu criei um aspecto que iria lidar com isso para mim.
Isto não é totalmente testado, e definitivamente não é testado contra coleções de objetos incorporados, assim que o comprador-cuidado. No entanto, parece funcionar para mim até agora.
Basicamente, intercepta o getter para o campo @Embedded
e garante que o campo é preenchido.
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;
}
}
Você pode usar um getter nullsafe.
public Direito getDireito() {
if (direito == null) {
direito = new Direito();
}
return direito;
}