2013-07-04 16 views
12

Ich habe eine Klasse mit Validierungs Anmerkung des Hibernate auf einigen Feldern (wie @NotNull und @Size(min = 4, max = 50), etc ...)Wie kann ich den gleichen Validator, der auf einer @ RequestMethod-Methode mit einem @ Valid-Parameter in Spring ausgeführt wird, programmgesteuert aufrufen?

public class MyClass { 

    Long id; 

    @NotEmpty 
    @Size(min = 4, max = 50) 
    String machineName; 

    @NotEmpty 
    @Size(min = 4, max = 50) 
    String humanName; 

    // Getters, setters, etc… 
} 

Ich habe auch eine individuelle Steuerung, die als JSON-API fungiert, und einen JSON Deserializer, dass erstellt MyClass-Objekte, wenn API-Methoden aufgerufen werden. In meinem benutzerdefinierten Controller habe ich eine Methode ein neues Objekt dieses Typen zu erstellen:

@RequestMapping(method = RequestMethod.POST) 
public long createMyObject(@RequestBody @Valid MyClass newObj) { 
    // Create the object in the database 
    return newObj.getId(); 
} 

und eine andere Methode, die ein bestehendes Objekt aktualisiert

@RequestMapping(method = RequestMethod.PUT) 
public void updateMyObject(@RequestBody MyClass updatedObj) { 
    MyClass existingObj = // Get existing obj from DB by updatedObj.getId(); 

    // Do some secondary validation, such as making sure that a specific 
    // field remains unchanged compared to the existing instance 
    if (existingObj.getMachineName() != null && 
      !existingObj.getMachineName().equals(updatedObj.getMachineName())) { 
     throw new CannotChangeMachineNameException(); 
    } 
    else { 
     updatedObj.setMachineName(existingObj.getMachineName()); 
    } 

    // [HERE IS WHERE I WANT THE MAGIC TO HAPPEN] 

    // Save updatedObj to the database 
} 

Während ich @Valid in createMyObject verwenden kann, kann ich nicht verwenden es in updateMyObject, da unsere API-Implementierung erfordert, dass machineName unverändert bleibt - Benutzer können die API mit einem JSON-Objekt aufrufen, das entweder machineName vollständig ausschließt oder es mit demselben Wert füllt, der in der Datenbank vorhanden ist. *

Vor dem Speichern des aktualisierten Objekts in der Datenbank möchte ich den gleichen Validator aufrufen, der den Aufruf der Annotation @Valid verursachen würde. Wie kann ich diesen Validator finden und verwenden?

+1

Ich glaube, Sie Validierungsgruppen verwenden können. Wenn alle Validierungen außer dem '@ NotNull' auf' machinename' (oder einem benutzerdefinierten Validierer, der den alten und den neuen Namen vergleicht) in der Standardgruppe sind und sich der verbleibende Validierer in der 'Update'-Gruppe befindet. Verwenden Sie beide Gruppen in der Methode 'updateMyObject'. Siehe http://docs.jboss.org/hibernate/validator/5.0/reference/en-US/html/chapter-groups.html#d0e2595 –

Antwort

6

Nichts besagt, dass Sie @Valid nur in Ihren Controller-Methoden verwenden müssen. Warum nicht eine Validierungsmethode erstellen, die einen Parameter akzeptiert, den Sie als @Valid annotieren, dann geben Sie einfach denselben Parameter zurück.

So:

public Book validateBook(@Valid Book book) { 
    return book; 
} 

Sieht aus wie eine alternative Hibernate Paketüberprüfung zu verwenden wäre. Here's it's documentation.

Grundsätzlich erhalten Sie einen Validator von einem ValidationFactory, und dann den Validator wie folgt verwenden:

@Test 
    public void manufacturerIsNull() { 
     Car car = new Car(null, "DD-AB-123", 4); 

     Set<ConstraintViolation<Car>> constraintViolations = 
      validator.validate(car); 

     assertEquals(1, constraintViolations.size()); 
     assertEquals("may not be null", constraintViolations.iterator().next().getMessage()); 
} 
+1

Danke! Dies führte mich nahe genug an die Antwort - die erste Methode hat nicht funktioniert, ich habe etwas ähnliches wie die zweite Methode: Set > errors = Validierung.buildDefaultValidatorFactory(). GetValidator(). Validate (updatedObj); // Ich kam dazu aus der Dokumentation, auf die Sie hingewiesen haben – daniel