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