hibernate独特的密钥验证 [英] hibernate unique key validation
问题描述
我有一个字段,例如 user_name
,它应该在表中是唯一的。
什么是使用Spring / Hibernate验证验证它的最好方法是什么?
可能的解决方案之一是创建自定义 @UniqueKey
约束(和相应的验证器);并查找数据库中的现有记录,将 EntityManager
(或Hibernate Session
)的实例提供给 UniqueKeyValidator
。
EntityManagerAwareValidator
public interface EntityManagerAwareValidator {
void setEntityManager(EntityManager entityManager);
}
ConstraintValidatorFactoryImpl
public class ConstraintValidatorFactoryImpl implements ConstraintValidatorFactory {
private EntityManagerFactory entityManagerFactory;
public ConstraintValidatorFactoryImpl(EntityManagerFactory entityManagerFactory){
this.entityManagerFactory = entityManagerFactory;
}
@Override
public< T extends ConstraintValidator<?,?>> T getInstance(Class< T> key){
T instance = null;
尝试{
instance = key.newInstance();
} catch(Exception e){
//无法实例化类
e.printStackTrace(); (EntityManagerAwareValidator.class.isAssignableFrom(key)){
EntityManagerAwareValidator validator =(EntityManagerAwareValidator)实例;
}
if
validator.setEntityManager(entityManagerFactory.createEntityManager());
}
返回实例;
UniqueKey
@Constraint(validatedBy = {UniqueKeyValidator.class})
@Target({ElementType.TYPE})
@保留(RUNTIME)
public @interface UniqueKey {
String [] columnNames();
字符串消息()默认{UniqueKey.message};
Class<?> [] groups()default {};
类<?扩展了Payload> [] payload()default {};
@Target({ElementType.TYPE})
@Retention(RUNTIME)
@Documented
@interface List {
UniqueKey [] value() ;
UniqueKeyValidator
public class UniqueKeyValidator实现ConstraintValidator< UniqueKey,Serializable>,EntityManagerAwareValidator {
private EntityManager entityManager;
@Override
public void setEntityManager(EntityManager entityManager){
this.entityManager = entityManager;
}
private String [] columnNames;
@Override
public void initialize(UniqueKey constraintAnnotation){
this.columnNames = constraintAnnotation.columnNames();
}
@Override
public boolean isValid(Serializable target,ConstraintValidatorContext context){
Class<?> entityClass = target.getClass();
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery< Object> criteriaQuery = criteriaBuilder.createQuery();
Root<?> root = criteriaQuery.from(entityClass);
列表<谓词> predicates = new ArrayList< Predicate> (columnNames.length);
尝试{
for(int i = 0; i< columnNames.length; i ++){
String propertyName = columnNames [i];
PropertyDescriptor desc = new PropertyDescriptor(propertyName,entityClass);
方法readMethod = desc.getReadMethod();
Object propertyValue = readMethod.invoke(target);
谓词谓词= criteriaBuilder.equal(root.get(propertyName),propertyValue);
predicates.add(谓词);
}
} catch(Exception e){
e.printStackTrace();
}
criteriaQuery.where(predicates.toArray(new Predicate [predicates.size()]));
TypedQuery< Object> typedQuery = entityManager.createQuery(criteriaQuery);
列表< Object> resultSet = typedQuery.getResultList();
返回resultSet.size()== 0;
}
}
用法
@UniqueKey(columnNames = {userName})
// @UniqueKey(columnNames = {userName ,emailId})//复合唯一键
//@UniqueKey.List(value = {@UniqueKey(columnNames = {userName}),@UniqueKey(columnNames = {emailId})} )//多个唯一键
public class User实现Serializable {
private String userName;
私人字符串密码;
private String emailId;
保护用户(){
super();
}
public User(String userName){
this.userName = userName;
}
....
}
Test
public void uniqueKey(){
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory(default) ;
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
ValidatorContext validatorContext = validatorFactory.usingContext();
validatorContext.constraintValidatorFactory(new ConstraintValidatorFactoryImpl(entityManagerFactory));
Validator validator = validatorContext.getValidator();
EntityManager em = entityManagerFactory.createEntityManager();
User se =新用户(abc,poizon);
Set< ConstraintViolation< User>> violation = validator.validate(se);
System.out.println(Size: - + violations.size());
em.getTransaction()。begin();
em.persist(se);
em.getTransaction()。commit();
用户se1 =新用户(abc);
violation = validator.validate(se1);
System.out.println(Size: - + violations.size());
}
I have a field, say, user_name
, that should be unique in a table.
What is the best way for validating it using Spring/Hibernate validation?
解决方案 One of the possible solutions is to create custom @UniqueKey
constraint (and corresponding validator); and to look-up the existing records in database, provide an instance of EntityManager
(or Hibernate Session
)to UniqueKeyValidator
.
EntityManagerAwareValidator
public interface EntityManagerAwareValidator {
void setEntityManager(EntityManager entityManager);
}
ConstraintValidatorFactoryImpl
public class ConstraintValidatorFactoryImpl implements ConstraintValidatorFactory {
private EntityManagerFactory entityManagerFactory;
public ConstraintValidatorFactoryImpl(EntityManagerFactory entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
}
@Override
public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) {
T instance = null;
try {
instance = key.newInstance();
} catch (Exception e) {
// could not instantiate class
e.printStackTrace();
}
if(EntityManagerAwareValidator.class.isAssignableFrom(key)) {
EntityManagerAwareValidator validator = (EntityManagerAwareValidator) instance;
validator.setEntityManager(entityManagerFactory.createEntityManager());
}
return instance;
}
}
UniqueKey
@Constraint(validatedBy={UniqueKeyValidator.class})
@Target({ElementType.TYPE})
@Retention(RUNTIME)
public @interface UniqueKey {
String[] columnNames();
String message() default "{UniqueKey.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
@Target({ ElementType.TYPE })
@Retention(RUNTIME)
@Documented
@interface List {
UniqueKey[] value();
}
}
UniqueKeyValidator
public class UniqueKeyValidator implements ConstraintValidator<UniqueKey, Serializable>, EntityManagerAwareValidator {
private EntityManager entityManager;
@Override
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
private String[] columnNames;
@Override
public void initialize(UniqueKey constraintAnnotation) {
this.columnNames = constraintAnnotation.columnNames();
}
@Override
public boolean isValid(Serializable target, ConstraintValidatorContext context) {
Class<?> entityClass = target.getClass();
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Object> criteriaQuery = criteriaBuilder.createQuery();
Root<?> root = criteriaQuery.from(entityClass);
List<Predicate> predicates = new ArrayList<Predicate> (columnNames.length);
try {
for(int i=0; i<columnNames.length; i++) {
String propertyName = columnNames[i];
PropertyDescriptor desc = new PropertyDescriptor(propertyName, entityClass);
Method readMethod = desc.getReadMethod();
Object propertyValue = readMethod.invoke(target);
Predicate predicate = criteriaBuilder.equal(root.get(propertyName), propertyValue);
predicates.add(predicate);
}
} catch (Exception e) {
e.printStackTrace();
}
criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()]));
TypedQuery<Object> typedQuery = entityManager.createQuery(criteriaQuery);
List<Object> resultSet = typedQuery.getResultList();
return resultSet.size() == 0;
}
}
Usage
@UniqueKey(columnNames={"userName"})
// @UniqueKey(columnNames={"userName", "emailId"}) // composite unique key
//@UniqueKey.List(value = {@UniqueKey(columnNames = { "userName" }), @UniqueKey(columnNames = { "emailId" })}) // more than one unique keys
public class User implements Serializable {
private String userName;
private String password;
private String emailId;
protected User() {
super();
}
public User(String userName) {
this.userName = userName;
}
....
}
Test
public void uniqueKey() {
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("default");
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
ValidatorContext validatorContext = validatorFactory.usingContext();
validatorContext.constraintValidatorFactory(new ConstraintValidatorFactoryImpl(entityManagerFactory));
Validator validator = validatorContext.getValidator();
EntityManager em = entityManagerFactory.createEntityManager();
User se = new User("abc", poizon);
Set<ConstraintViolation<User>> violations = validator.validate(se);
System.out.println("Size:- " + violations.size());
em.getTransaction().begin();
em.persist(se);
em.getTransaction().commit();
User se1 = new User("abc");
violations = validator.validate(se1);
System.out.println("Size:- " + violations.size());
}
这篇关于hibernate独特的密钥验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!