Hibernate复杂的唯一约束

时间:2017-08-29 13:52:36

标签: java mysql hibernate

我有一个具有以下唯一约束设置的实体类:

@Table(name = "foo", uniqueConstraints = {
@UniqueConstraint(columnNames = {"service", "system", "priority", "is_default"})})

如果服务和系统是其他实体类的外键,则priority是一个整数,在具有相同服务和系统对象的条目中保存条目的优先级,is_default是一个布尔值,表示默认配置条目。

这个独特的约束几乎完成了我想要做的事情,但我需要的是一个设置,如果is_default是FALSE那么可以有多个条目具有相同的服务和系统密钥只是具有不同的整数优先级,如果is_default是TRUE,那么只有一个条目具有给定的服务和系统密钥,这意味着给定的服务和系统只能有一个默认条目。我怎么能实现这样的约束呢?

1 个答案:

答案 0 :(得分:1)

关键是要创建自己的验证注释,以便根据特定条件验证行数据是否唯一。

让服务iterface扩展UniqueValidated并实现执行验证的方法

public interface UniqueValidated {
     boolean isUnique(Object value, String fieldName) throws UnsupportedOperationException;
}

public interface FooService extends UniqueValidated {
    // add, delete...
}

public class FooServiceImpl implements FooService {

    // add, delete...

    @Override
    public boolean isUnique(Object value, String fieldName) 
        throws UnsupportedOperationException {

        // the logic of validation itself, feel free to use DAO implementations
    }
}

创建放置在映射属性上的注释。

@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE 
})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UniqueValidator.class)
@Documented
public @interface Unique {
    String message() default "{validation.unique}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
    Class<? extends UniqueValidated> service();
    String serviceQualifier() default "";
    String fieldName();
}

最后使用注释创建类处理。

public class UniqueValidator implements ConstraintValidator<Unique, Object> {

    @Autowired
    private ApplicationContext applicationContext;
    private UniqueValidated service;
    private String fieldName;

    @Override
    public void initialize(Unique unique) {
        Class<? extends UniqueValidated> clazz = unique.service();
        this.fieldName = unique.fieldName();
        this.service = this.applicationContext.getBean(clazz);
    }

    @Override
    public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
        if (this.service == null || this.service.isUnique(o, this.fieldName)) {
            constraintValidatorContext.disableDefaultConstraintViolation();
            return true;
        }
        return false;
    }
}

我对JBoss Docs在线提供的教程有所启发。这是一个相当复杂的结构,但它导致结果很好。毫无疑问,您可以对实现UniqueValidated的任何服务进行自定义唯一验证。无论如何,您需要为您的项目定制上面的这些片段。

映射很简单:

@Unique(service = FooService.class, fieldName = "theNameOfThisField"
@Column(name = "...")
private String theNameOfThisField;