Java 我应该如何在JPA中映射这两个简单实体? 我目前拥有的:

Java 我应该如何在JPA中映射这两个简单实体? 我目前拥有的:,java,hibernate,jpa,mapping,jpa-2.0,Java,Hibernate,Jpa,Mapping,Jpa 2.0,付款实体只持有所有部门每年和每月只需支付一次的默认付款。他们之间不需要任何关系,因为所有部门都支付所有款项 我想要达到的目标: 我想区分当前共享的付款和一些其他部门特定的付款。因此,一个部门将能够选择使用所有共享付款(如目前设计的)或定义自己的付款,而不使用任何其他付款 公司的付款方式应该保持不变,我必须确保每个部门的付款方式也是唯一的 在OOP术语中,我认为我需要对以下任何选项进行建模: 也许第一个更合适 注意:我无法更改当前标识任何实体的方式。但是,我可以在任何其他字段上添加唯一性 问题:

付款实体只持有所有部门每年和每月只需支付一次的默认付款。他们之间不需要任何关系,因为所有部门都支付所有款项

我想要达到的目标: 我想区分当前共享的付款和一些其他部门特定的付款。因此,一个部门将能够选择使用所有共享付款(如目前设计的)或定义自己的付款,而不使用任何其他付款

公司的付款方式应该保持不变,我必须确保每个部门的付款方式也是唯一的

在OOP术语中,我认为我需要对以下任何选项进行建模:

也许第一个更合适

注意:我无法更改当前标识任何实体的方式。但是,我可以在任何其他字段上添加唯一性

问题:
  • 在JPA2中,什么是实现这一点的合适方法
  • 支付等级制度是一种方式吗?应如何映射以确保 场不会碰撞吗
  • 有没有办法避免等级制度

  • 我认为这种情况确实需要一种关系:

    @Entity
    public class Payment {
    
        @Id @GeneratedValue
        private long id;
    
        @Column(unique = true)
        private Date period; // Only used for year and month
    
        @ManyToOne
        private Department department;
    }
    

    这将允许为任何部门创建任何类型的付款。至于部门的默认付款,我认为这不属于ORM的责任范围,应该在业务逻辑中处理。

    如果我理解正确,您需要实现每个部门的唯一性。可以使用
    复合id
    。 有几点:

    • 如果你想使用复合键(
      period
      +
      department\u id
      ),你必须同时设置这两个键,并且你的默认付款应该有
      1
      common-fake
      department
      ,所有默认的
      付款都将属于这两个键
      
    • 一般情况下,我会遵循。这很容易,也不容易出错。不管你怎么决定

    @实体
    公共类支付实现了可序列化{
    @嵌入ID
    私人时期;
    }
    @可嵌入
    公共类周期实现可序列化{
    @许多酮
    私人部门,;
    私人约会期间;
    }
    @实体
    公共类部门实现可序列化{
    @Id@GeneratedValue
    私人长id;
    @独身癖
    私有列表付款=新建ArrayList();
    }
    
    我无法在我的支付实体中保留主键,也无法在期间和部门上维护唯一索引。就DB而言,我正在寻找这些:

    付款(ID,期间,FK_部门)

    这个表应该在Period和FK_Department中添加一个唯一的索引,允许FK_Department中为空(正如您所看到的,出于这个原因,复合PK不是一个选项,因为我需要使用相同的PK结构)。在该表中,所有FK_部门值为空的付款将是通用/默认/公司付款,而非空FK_部门的付款将是特定部门分配的付款,因此它将使用这些付款而不是公司付款

    由于我缺乏JPA的知识,我无法复制这个模式。然而,我可以创建一个类似的功能模式。这是迄今为止我想到的最好的:

    由于其明显可怕的期间重复,我可以为每个表创建两个唯一的索引:一个用于CompanyPayment实体的期间,另一个用于DepartmentPayment实体的期间和部门对:

    @Entity
    @Inheritance(strategy = InheritanceType.JOINED)
    public abstract class Payment {
    
        @Id @GeneratedValue
        private long id;
    
        ...
    }
    
    @Entity
    public class CompanyPayment extends Payment {
    
        @Column(unique = true)  
        public Date period;
    
        ...
    }
    
    @Entity
    @Table(uniqueConstraints =
        @UniqueConstraint(columnNames = { "period", "department_id" })
    )
    public class DepartmentPayment extends Payment {
    
        public Date period;
    
        @ManyToOne(optional = false)
        @JoinColumn(name = "department_id")
        private Department department;
    
        ...
    }
    

    我现在将使用此解决方案,但我愿意接受任何其他更好的解决方案。

    我相信建立关系确实是必须的。但这还不够。这不需要处理独特的部门周期对。没有部门的付款被视为默认付款。在DB术语中,您有一个带有FK的付款表,可以为空。如果FK为空,则默认付款。因此,在PaymentId和FKDepartmentID上设置一个复合唯一索引(不是PK!)就可以了。我认为JPA中一定有某种方法可以做到这一点。为了扩展层次结构选项:这将是一个带有鉴别器(C | D)的表,该表将同时包含CompanyPayments和DepartmentPayments,因此唯一性将由鉴别器列和period列这一对决定。我实际上无法更改当前付款的ID。正如我在凯文的回答中提到的,我不能使用复合PK,但我可以使用唯一索引。另外,我不喜欢假部门的想法(这是因为你有一个复合PK,而不仅仅是一个复合唯一索引)。现在,正如我在问题的评论中提到的,为了解决这个问题,层次结构可以与两种类型的部门的鉴别器一起使用,对吗?我是否可以保留目前存在的简单PK,同时保持鉴别器和department_FK配对的唯一性?我将把奖金授予你,作为第二个最佳答案,IMO。
    @Entity
    public class Payment implements Serializable {
    
        @EmbeddedId
        private Period period;
    }
    
    @Embeddable
    public class Period implements Serializable {
        @ManyToOne
        private Department department;
        private Date period;
    }
    
    
    @Entity
    public class Department implements Serializable {
        @Id@GeneratedValue
        private long id;
    
        @OneToMany
        private List<Payment> payments = new ArrayList<Payment>();
    }
    
    @Entity
    @Inheritance(strategy = InheritanceType.JOINED)
    public abstract class Payment {
    
        @Id @GeneratedValue
        private long id;
    
        ...
    }
    
    @Entity
    public class CompanyPayment extends Payment {
    
        @Column(unique = true)  
        public Date period;
    
        ...
    }
    
    @Entity
    @Table(uniqueConstraints =
        @UniqueConstraint(columnNames = { "period", "department_id" })
    )
    public class DepartmentPayment extends Payment {
    
        public Date period;
    
        @ManyToOne(optional = false)
        @JoinColumn(name = "department_id")
        private Department department;
    
        ...
    }