contrainte unique avec validation JPA et Bean
-
29-09-2019 - |
Question
J'aimerais avoir une contrainte de @Unique
avec Bean Validation, mais qui ne sont pas fournis par la norme. Si j'utiliser le @UniqueConstraint
de JPA je ne serais pas un mécanisme de validation unique et des rapports d'erreur.
Est-il possible de définir @Unique
comme une contrainte de validation Bean et le combiner avec JPA, de sorte que JPA crée une colonne avec une contrainte unique et contrôles wheter une valeur est unique ou non?
La solution
À moins que vous acquérez un verrou sur une table entière , il est fondamentalement impossible de vérifier l'unicité à l'aide d'une requête SQL (toute transaction concurrente pourrait modifier les données après une vérification manuelle, mais avant la validation de la transaction en cours). En d'autres termes, il est impossible de mettre en œuvre une vérification unique, valable au niveau Java et donc de fournir une implémentation de validation. Le seul moyen fiable pour vérifier l'unicité est tout en engageant la transaction.
du BV les résume comme ceci:
Annexe D. Java Persistence 2.0 intégration
Question: faut-il ajouter que @Unique tracerait à @Column (unique = true)?
@Unique ne peut pas être testé à Java fiable niveau, mais pourrait générer un unique de génération de contrainte de base de données. @Unique ne fait pas partie de la spécification BV aujourd'hui.
Ainsi, alors que je suis d'accord qu'il serait agréable d'avoir unique (et non nulle) violation contrainte enveloppées dans une exception de validation Bean, ce n'est pas le cas actuellement.
Références
- spécification Bean Validation (JSR 303)
- Question sur les contraintes de validation et de la persistance
Autres conseils
Plus d'informations sur la façon de mettre en œuvre un @Unique et la problématique autour d'elle se trouve ici - http: / /community.jboss.org/wiki/AccessingtheHibernateSessionwithinaConstraintValidator
Eh bien, vous pouvez le faire, mais ce n'est pas trivial. Le problème est: le validateur nécessite un accès de base de données pour effectuer des requêtes à vérifier, si la valeur que vous souhaitez insérer est déjà là ou non. Et cela ne peut pas être vraiment fait du validateur, car il n'a pas accès à la sessionFactory / session. Bien sûr, vous pouvez instancier (séance / sessionFactory) à l'intérieur du validateur, mais ce n'est pas une bonne pratique de codage.
Vous pouvez faire un validateur lire les annotations JPA et l'appliquer. Voici un peu d'un exemple en utilisant des validateurs de printemps qui peuvent être utilisés comme une idée à développer.
JPA JSR303 Formulaire printemps Validation
Vous pouvez également injecter (@Inject
ou de @Autowired
de printemps) bean de session dans un validateur personnalisé et le conteneur doit savoir comment il câbler. Je sais que cela comme un exemple de printemps:
import javax.validation.ConstraintValidator;
public class MyConstraintValidator implements ConstraintValidator {
@Autowired //@Inject
private Foo aDependency;
...
}