【问题标题】:Hibernate: Mapping ManyToOne only to foreign key entities with particular column valueHibernate:仅将 ManyToOne 映射到具有特定列值的外键实体
【发布时间】:2020-09-08 08:10:16
【问题描述】:

我觉得这有点奇怪,我不确定这是否可能,但我的要求如下:

我有两个实体:DatasetOrganizationDataset 实体具有到Organization 实体的多对一映射。组织有两种类型:CustomerPartner。业务要求是只有Partner 类型的组织才能拥有数据集。那么,有没有办法将Dataset 实体映射到Organization,这样Dataset 中的所有外键都只包含Organization 类型为Partner 的实体的ID?

组织实体定义如下:

@Entity
@Table(name = "organization")
public class Organization {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;    
    private String type;
    private String name;
    private String address;
    private String status;
    private String subtype;
    
    @Column(name = "created_date")
    @Temporal(value =  TemporalType.TIMESTAMP)
    private Date createdDate;

    @OneToMany(fetch = FetchType.LAZY)
    @JoinColumn(name = "organization_id", insertable = false, updatable = false)
    private List<User> users;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumns({ @JoinColumn(name = "subtype", referencedColumnName = "name", insertable = false, updatable = false),
            @JoinColumn(name = "type", referencedColumnName = "organization_type", insertable = false, updatable = false) })
    private OrganizationSubType organizationSubType;

    // Getters and setters
.
.
.

这里,type 列将包含PARTNERCUSTOMER

这是我目前正在设计的数据集实体:

@Entity
@Table(name="datasets")
public class Dataset {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    
    @Column(name="partner_id", nullable = false)
    private long partnerId;
    
    @Column(nullable = false, unique = true)
    private String name;
    
    private String description;
    
    @Column(nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date createdDate;
    
    @Column(nullable = false)
    @Enumerated(EnumType.STRING)
    private DatasetStatus datasetStatus;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="partner_id", referencedColumnName="id", insertable = false, updatable = false)
    private Organization partner;
    
    //Getters and setters

那么,有没有什么方法可以对映射设置约束,这样当一个新的数据集实体被持久化时,组织 ID 总是属于类型为合作伙伴而不是客户的实体?还是我必须将客户和合作伙伴组织分开为单独的实体?

【问题讨论】:

    标签: java hibernate hibernate-mapping


    【解决方案1】:

    有几种方法可以实现它:

    1. 通过在构建新的Dataset 对象之前在业务层添加验证,然后再将其持久化。此类验证将检查给定的Organisation 是否可以与基于组织类型创建的Dataset 实体相关联。

    2. 通过使用 Bean Validation API 和定义自定义约束验证器。实体上的每次更改都会调用此类验证器。

    将 hibernate-validator 添加到类路径

    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>5.3.4.Final</version>
    </dependency>
    

    为新的验证定义注解

    @Constraint(validatedBy = PartnerOrganisationValidator.class)
    @Target(FIELD)
    @Retention(RUNTIME)
    @Documented
    public @interface PartnerOrganisation {
        String message() default "Organisation should be of type PARTNER";
        Class<?>[] groups() default { };
        Class<? extends Payload>[] payload() default { };
    }
    

    定义约束验证器

    public class PartnerOrganisationValidator implements ContraintValidator<PartnerOrganisation, Organisation> {
        @Override
        public boolean isValid(Organisation organisation, ConstraintValidatorContext constraintValidatorContext) {
            return organisation == null || "PARTNER".equals(organisation.type);
        }
    }
    

    通过将验证器的完全限定名称添加到 META-INF/services/javax.validation.ConstraintValidator 文件,在休眠验证器中注册验证器。 最后一步是在您的实体中使用验证器:

        @PartnerOrganisation
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name="partner_id", referencedColumnName="id", insertable = false, updatable = false)
        private Organization partner;
    
    1. 如果您使用的数据库支持,则使用SQL CHECK CONSTRAINT - 就像https://stackoverflow.com/a/55379219/14231619 中的示例一样

    2. 通过将合作伙伴组织和客户组织建模为单独的实体类。

    由于 PARTNER 和 CUSTOMER 的组织结构与选项 4 中的方法相同。对于这种情况似乎过于复杂。我建议使用选项 1。

    【讨论】:

    • 感谢您提供可能的解决方案。我已经在考虑在我的服务层中实现一些自定义逻辑。我只是想看看我是否可以在 Hibernate 本身中设置一些约束。
    猜你喜欢
    • 2014-10-12
    • 1970-01-01
    • 2011-11-15
    • 2011-05-25
    • 1970-01-01
    • 1970-01-01
    • 2016-11-08
    • 2012-04-06
    • 1970-01-01
    相关资源
    最近更新 更多