我正在尝试建立功能位置层次结构,我从 国家/地区 模型/实体开始。下一层是与国家/地区具有 ManyToOne 关系的 省 实体(双向)。现在,我有 City 实体,它是与省(双向)绑定的 ManyToOne ,但是这种关系可以为空。但是现在,如果City-Province关系为空,则需要City-Country关系(也可以为空)。因此,至少需要一个。但是,如果这两个条件之一已经存在,则无法输入其他条件。
因此,基本上,城市中的这两个关系(城市,省/国家/地区)是互斥,但至少需要其中之一。我正在使用 Java 和 JPA(休眠),但我没有发现实现此功能的任何特殊功能。有没有行之有效的方法?
答案 0 :(得分:0)
您不能使用JPA或Hibernate为互斥关联建模。但是您可以为2个独立模型建模并添加BeanValidation约束。 JPA集成了BeanValidation规范,并在持久或更新实体之前自动触发验证。
我在Hibernate Tips之一中对此进行了更详细的说明。这是简写形式。
您可以在City
实体上为2个关联建模。
@Entity
@EitherOr
public class City {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Version
private int version;
@ManyToOne
private Province province;
@ManyToOne
private Country country;
...
}
请注意第2行中的@EitherOr
批注。这是我根据BeanValidation规范实现的自定义约束。 @Constraint
注释指定将在实体生命周期过渡期间触发的ConstraintValidator
。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {EitherOrValidator.class})
public @interface EitherOr {
String message() default "A city can only be linked to a country or a province.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
ConstraintValidator的实现非常简单。您需要实现isValid
方法,并检查province
或country
属性是否不为空。
public class EitherOrValidator implements ConstraintValidator<EitherOr, City>{
@Override
public void initialize(EitherOr arg0) { }
@Override
public boolean isValid(City city, ConstraintValidatorContext ctx) {
return (city.getProvince() == null && city.getCountry() != null)
|| (city.getProvince() != null && city.getCountry() == null);
}
}