unidades:06_objetos_validaciones:02_validaciones
Diferencias
Muestra las diferencias entre dos versiones de la página.
— | unidades:06_objetos_validaciones:02_validaciones [2023/04/07 21:26] (actual) – creado - editor externo 127.0.0.1 | ||
---|---|---|---|
Línea 1: | Línea 1: | ||
+ | ====== Validaciones ====== | ||
+ | En este tema vamos a ver cómo Hibernate puede validar los datos de nuestros objetos Java antes de que se persistan en la base de datos. | ||
+ | |||
+ | Hace unos años se creó una especificación estándar para validar los valores de los objetos Java mediante anotaciones. Esta especificación se define en el [[http:// | ||
+ | |||
+ | |||
+ | ===== Instalación ===== | ||
+ | Hibernate soporta estas anotaciones aunque el desarrollo del código que las soporta ha sido desarrollado como un subproyecto llamado [[http:// | ||
+ | |||
+ | Desde la URL [[http:// | ||
+ | |||
+ | Deberemos descomprimir el fichero '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | <note tip> | ||
+ | Se deben copiar todos los ficheros excepto los siguientes: | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | </ | ||
+ | |||
+ | <note warning> | ||
+ | **No** bajaros la versión Hibernate Validator 5.0.0.Final. Esta se hizo estable solo 2 semanas antes de empezar el curso.Así que no la usaremos. | ||
+ | </ | ||
+ | ===== Introducción ===== | ||
+ | Empezar a usar las validaciones mediate anotaciones es tan sencillo como añadir dichas anotaciones a las propiedades de las clases Java a validar. | ||
+ | |||
+ | Veamos un sencillo ejemplo con la clase '' | ||
+ | |||
+ | <code java 1> | ||
+ | import java.io.Serializable; | ||
+ | import java.util.Set; | ||
+ | import javax.validation.constraints.NotNull; | ||
+ | import javax.validation.constraints.Size; | ||
+ | |||
+ | |||
+ | public class Profesor implements Serializable | ||
+ | | ||
+ | private int id; | ||
+ | @NotNull | ||
+ | @Size(min = 3, max = 50) | ||
+ | private String nombre; | ||
+ | @NotNull | ||
+ | @Size(min = 3, max = 50) | ||
+ | private String ape1; | ||
+ | @Size(min = 3, max = 50) | ||
+ | private String ape2; | ||
+ | | ||
+ | |||
+ | public Profesor(){ | ||
+ | | ||
+ | } | ||
+ | | ||
+ | public Profesor(String nombre, String ape1, String ape2) { | ||
+ | this.nombre = nombre; | ||
+ | this.ape1 = ape1; | ||
+ | this.ape2 = ape2; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Al código fuente de la clase profesor se han añadido las siguientes nuevas anotaciones '' | ||
+ | * **'' | ||
+ | * **'' | ||
+ | |||
+ | Expliquemos ahora cada una de las validaciones de la clase '' | ||
+ | * La propiedad '' | ||
+ | * La propiedad '' | ||
+ | * La propiedad '' | ||
+ | * La propiedad '' | ||
+ | * La propiedad '' | ||
+ | |||
+ | <note tip> | ||
+ | No se ha validado que '' | ||
+ | </ | ||
+ | |||
+ | Ahora cuando vayamos a persistir la clase '' | ||
+ | |||
+ | Veamos cómo queda el código Java al persistir a '' | ||
+ | |||
+ | <code java 1> | ||
+ | Profesor profesor = new Profesor(" | ||
+ | |||
+ | try { | ||
+ | session.beginTransaction(); | ||
+ | |||
+ | session.save(profesor); | ||
+ | |||
+ | session.getTransaction().commit(); | ||
+ | } catch (ConstraintViolationException cve) { | ||
+ | session.getTransaction().rollback(); | ||
+ | System.out.println(" | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Al ejecutar el código se mostrará al usuario el mensaje //No se ha podido insertar el profesor// ya que la propiedad '' | ||
+ | |||
+ | Destacar que prácticamente no se ha modificado el código Java al persistir la clase '' | ||
+ | ===== Mensajes ===== | ||
+ | En el ejemplo anterior se muestra un simple mensaje al usuario indicando que no ha podido insertarse el profesor pero sin indicar el motivo de ello. Como todos sabemos, se debe mostrar al usuario los motivos por lo que ha fallado dicha inserción (( o actualización , borrado, etc )). | ||
+ | |||
+ | La excepción <javadoc jee6> | ||
+ | |||
+ | La clase <javadoc jee6> | ||
+ | * < | ||
+ | * < | ||
+ | |||
+ | Ahora el código Java debe quedar de la siguiente forma: | ||
+ | <code java 1> | ||
+ | Profesor profesor = new Profesor(" | ||
+ | |||
+ | try { | ||
+ | session.beginTransaction(); | ||
+ | |||
+ | session.save(profesor); | ||
+ | |||
+ | session.getTransaction().commit(); | ||
+ | } catch (ConstraintViolationException cve) { | ||
+ | session.getTransaction().rollback(); | ||
+ | System.out.println(" | ||
+ | for (ConstraintViolation constraintViolation : cve.getConstraintViolations()) { | ||
+ | System.out.println(" | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Como podemos ver, se han añadido las líneas 12, 13, y 14. Estas líneas contienen un bucle para recorrer cada una de las validaciones infringidas y mostrar el mensaje al usuario. | ||
+ | |||
+ | La salida por la consola en este caso será la siguiente: | ||
+ | No se ha podido insertar el profesor debido a los siguientes errores. | ||
+ | En el campo ' | ||
+ | En el campo ' | ||
+ | |||
+ | ==== Mensajes personalizados ==== | ||
+ | En el ejemplo anterior podemos ver cómo el mensaje de la anotación @NotNull es //"no puede ser null"// | ||
+ | |||
+ | Existen dos formas de cambiar los mensajes al usuario: | ||
+ | * [[# | ||
+ | * [[# | ||
+ | |||
+ | === Reemplazo local === | ||
+ | Para cada anotación de validación es posible usar el atributo '' | ||
+ | |||
+ | Veamos cómo queda la clase '' | ||
+ | <code java 1> | ||
+ | import java.io.Serializable; | ||
+ | import java.util.Set; | ||
+ | import javax.validation.constraints.NotNull; | ||
+ | import javax.validation.constraints.Size; | ||
+ | |||
+ | |||
+ | public class Profesor implements Serializable | ||
+ | | ||
+ | private int id; | ||
+ | @NotNull | ||
+ | @Size(min = 3, max = 50) | ||
+ | private String nombre; | ||
+ | @NotNull(message=" | ||
+ | @Size(min = 3, max = 50) | ||
+ | private String ape1; | ||
+ | @Size(min = 3, max = 50) | ||
+ | private String ape2; | ||
+ | | ||
+ | |||
+ | public Profesor(){ | ||
+ | | ||
+ | } | ||
+ | | ||
+ | public Profesor(String nombre, String ape1, String ape2) { | ||
+ | this.nombre = nombre; | ||
+ | this.ape1 = ape1; | ||
+ | this.ape2 = ape2; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Vemos cómo en la línea 13 se ha modificado la anotación '' | ||
+ | |||
+ | Si volvemos a ejecutar el código la salida por consola será ahora: | ||
+ | |||
+ | No se ha podido insertar el profesor debido a los siguientes errores: | ||
+ | En el campo ' | ||
+ | En el campo ' | ||
+ | |||
+ | El problema de esta técnica es el nuevo mensaje.Sólo se aplica a '' | ||
+ | |||
+ | === Reemplazo global === | ||
+ | Por suerte hay una forma de cambiar los mensajes para todas las veces que aparece la validación '' | ||
+ | |||
+ | Debemos crear el fichero '' | ||
+ | |||
+ | Veamos un ejemplo que quedará mucho más claro: | ||
+ | |||
+ | <code java | Fichero ValidationMessages.properties> | ||
+ | javax.validation.constraints.NotNull.message=No puede estar vacio | ||
+ | </ | ||
+ | |||
+ | Ahora con el siguiente código | ||
+ | <code java 1> | ||
+ | Profesor profesor = new Profesor(null, | ||
+ | |||
+ | try { | ||
+ | session.beginTransaction(); | ||
+ | |||
+ | session.save(profesor); | ||
+ | |||
+ | session.getTransaction().commit(); | ||
+ | } catch (ConstraintViolationException cve) { | ||
+ | session.getTransaction().rollback(); | ||
+ | System.out.println(" | ||
+ | for (ConstraintViolation constraintViolation : cve.getConstraintViolations()) { | ||
+ | System.out.println(" | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Como el objeto '' | ||
+ | |||
+ | No se ha podido insertar el profesor debido a los siguientes errores: | ||
+ | En el campo ' | ||
+ | En el campo ' | ||
+ | |||
+ | Es decir que a partir de ahora cualquier uso que hagamos de la anotación '' | ||
+ | |||
+ | <note tip>Y ahora ya podemos quitar el mensaje personalizado de la línea 13 de la clase '' | ||
+ | ===== Validaciones simples ===== | ||
+ | Hasta ahora sólo hemos usado las anotaciones '' | ||
+ | |||
+ | |||
+ | ^ Anotación ^ Tipos (( Tipo de la propiedad a la que se puede aplicar)) ^ Explicación ^ | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | |||
+ | Como podemos ver, las anotaciones son bastante sencillas de usar. | ||
+ | |||
+ | <note tip> | ||
+ | |||
+ | <note important> | ||
+ | Recuerda que la anotación '' | ||
+ | </ | ||
+ | ===== Validaciones complejas ===== | ||
+ | Hasta ahora hemos visto simples validaciones de campos pero , ¿qué ocurre cuando queremos validar más de un campo a la vez?. Hibernate Validator soporta 2 formas de hacerlo. | ||
+ | * [[#La anotación @ScriptAssert]] | ||
+ | * [[#Métodos Java de Validación]] | ||
+ | |||
+ | ==== La anotación @ScriptAssert ==== | ||
+ | La anotación '' | ||
+ | |||
+ | |||
+ | <note important> | ||
+ | Explico la anotación '' | ||
+ | </ | ||
+ | |||
+ | '' | ||
+ | |||
+ | Un ejemplo es el siguiente: | ||
+ | <code java> | ||
+ | @ScriptAssert(lang=" | ||
+ | public class Usuario implements Serializable | ||
+ | | ||
+ | private int idUsuario; | ||
+ | | ||
+ | @NotNull | ||
+ | @Size(min = 3, max = 50) | ||
+ | | ||
+ | @Column(name=" | ||
+ | private String login; | ||
+ | | ||
+ | @NotNull | ||
+ | @Size(min = 3, max = 50) | ||
+ | private String nombre; | ||
+ | | ||
+ | @NotNull | ||
+ | @Size(min = 3, max = 50) | ||
+ | private String ape1; | ||
+ | | ||
+ | @Size(min = 3, max = 50) | ||
+ | private String ape2; | ||
+ | | ||
+ | @NotNull | ||
+ | @Size(min = 7, max = 50) | ||
+ | private String password; | ||
+ | |||
+ | @NotNull | ||
+ | @Size(min = 7, max = 50) | ||
+ | private String confirmPassword; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Vemos en la línea 1 cómo se ha añadido la anotación '' | ||
+ | <code javascript> | ||
+ | (_this.password!=null)? | ||
+ | </ | ||
+ | Se ha utilizado el operador ternario de JavaScript porque sólo es posible escribir una expresión con lo que no podemos usar un '' | ||
+ | |||
+ | <note tip> | ||
+ | Para acceder a los valores nótese que se usa "'' | ||
+ | </ | ||
+ | |||
+ | |||
+ | Si intentamos añadir más validaciones con '' | ||
+ | <code java> | ||
+ | @ScriptAssert.List({ | ||
+ | @ScriptAssert(lang=" | ||
+ | @ScriptAssert(lang=" | ||
+ | }) | ||
+ | </ | ||
+ | ==== Métodos Java de Validación ==== | ||
+ | Podemos añadir también métodos Java que realicen las validaciones, | ||
+ | |||
+ | <note important> | ||
+ | Este truco que vamos a explicar ahora mismo , es de una sencillez pasmosa pero muy util para colocar las validaciones que debamos hacer en código Java | ||
+ | </ | ||
+ | |||
+ | Veamos ahora un ejemplo de código: | ||
+ | |||
+ | <code java> | ||
+ | @AssertTrue(message=" | ||
+ | private boolean isPasswordValido() { | ||
+ | if ((login!=null) && (login.equalsIgnoreCase(password))) { | ||
+ | return false; | ||
+ | } else { | ||
+ | return true; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Deberemos hacer un método Java que realice la validación que deseemos y que retorne '' | ||
+ | Entonces el truco consiste en añadir la anotación '' | ||
+ | |||
+ | <note tip> | ||
+ | El nombre del método deberá empezar por '' | ||
+ | </ | ||
+ | |||
+ | <note important> | ||
+ | El nombre del método no debe llamarse como el de una propiedad. Es decir si está la propiedad '' | ||
+ | </ | ||
+ | |||
+ | Esta forma de validar tiene varias ventajas respecto a '' | ||
+ | * El código fuente de la validación se comprueba en tiempo de compilación en vez de en tiempo de ejecución. | ||
+ | * Es posible usar toda la potencia de Java en vez de sólo expresiones en JavaScript. | ||
+ | * En caso de tener muchas validaciones queda todo mucho más ordenado mediante métodos que con multitud de anotaciones '' | ||
+ | * Al usar la anotación '' | ||
+ | |||
+ | <note tip> | ||
+ | El único problema de esta técnica de validación es que al hacer el método privado y que aparentemente nadie lo llame , si usamos herramientas de chequeo de código como [[http:// | ||
+ | |||
+ | Pero si lo hacemos público cualquiera podría ver las métodos y hacer uso de ellos cuando realmente no queremos que los llamen directamente. | ||
+ | </ | ||