Java Bean Validation (JSR303) vincoli che coinvolgono rapporto tra diverse proprietà del bean
-
19-09-2019 - |
Domanda
Dire che ho il seguente fagiolo java semplice:
class MyBean {
private Date startDate;
private Date endDate;
//setter, getters etc...
}
Esiste un meccanismo in JSR 303 per creare un validatore personalizzato che convalida il vincolo che startDate deve essere prima endDate?
A me sembra essere un caso di uso comune, ma non riesco a trovare alcun esempio di questo tipo di vincolo multipla proprietà relationsship.
Soluzione
Mi vengono in mente un paio di cose da provare.
È possibile creare un Constraint
con un obiettivo di tipo in sé con un validatore appropriato:
@ValidateDateRange(start="startDate", end="endDate")
public class MyBean {
Si potrebbe racchiudere un intervallo di date in un tipo e convalidare che:
public class DateRange {
private long start;
private long end;
public void setStart(Date start) {
this.start = start.getTime();
}
// etc.
Si potrebbe aggiungere una semplice proprietà che esegue il controllo:
public class MyBean {
private Date startDate;
private Date endDate;
@AssertTrue public boolean isValidRange() {
// TODO: null checks
return endDate.compareTo(startDate) >= 0;
}
Altri suggerimenti
Se stai usando Hibernate Validator in versione 4.1 o successiva è possibile utilizzare la @ScriptAssert vincolo insieme un linguaggio di scripting o di espressione per esprimere questo tipo di vincolo. Utilizzando JavaScript tuo esempio sarebbe simile a questa:
@ScriptAssert(lang = "javascript", script = "_this.startDate.before(_this.endDate)")
public class CalendarEvent {
private Date startDate;
private Date endDate;
//...
}
È possibile ottenere una sintassi ancora più compatto da la creazione di un vincolo personalizzato per il linguaggio di script di vostra scelta:
@JexlAssert("_.startDate < _.endDate")
public class CalendarEvent {
private Date startDate;
private Date endDate;
//...
}
La risposta è un validatore livello di classe. È possibile definire vincoli personalizzati che è possibile inserire sulla classe di entità. Al momento la convalida si ottiene passato l'intera istanza nel metodo isValid (). È quindi possibile confrontare i vostri due date uno contro l'altro. Si veda anche la Hibernate Validator documentazione .
Poiché non v'è alcun modo per accedere al bean in una JSR 303 validatore, questo non è possibile.
Una soluzione potrebbe essere quella di fornire il proprio ConstraintValidatorContext
ed estendere con un riferimento al bean che si sta convalidare. Ma non sono sicuro se è possibile modificare / annullare il rispettivo fabbrica.