嵌套 ID class 需要像关系一样命名,即使不是派生标识符?
Nested ID class required to be named like relationship, even though not being a derived identifier?
“Java EE 8 中的 Pro JPA 2”一书的第 10 章,名为“多个映射属性”的部分,其中有使用 @IdClass
的著名部门项目示例,完整https://github.com/Apress/pro-jpa-2-in-java-ee-8/tree/master/examples/Chapter10/08-multipleMappedAttributes/src/model/examples/model.
处的示例代码
下面是短篇小说。
项目实体:
@Entity
@IdClass(ProjectId.class)
public class Project
{
@Id
private String name;
@Id
@ManyToOne
@JoinColumns({
@JoinColumn(name="DEPT_NUM", referencedColumnName="NUM"),
@JoinColumn(name="DEPT_CTRY", referencedColumnName="COUNTRY")
})
private Department dept;
// ...
}
项目 ID class:
public class ProjectId implements Serializable
{
private String name;
private DeptId dept; <-- named dept to conform with derived identifier naming conventions
public ProjectId() {}
public ProjectId(DeptId deptId, String name)
{
this.dept = deptId; <-- naming "mismatch"
this.name = name;
}
// ...
}
部门实体:
@Entity
@IdClass(DeptId.class)
public class Department
{
@Id
@Column(name="NUM")
private int number;
@Id
private String country;
private String name;
// ...
}
部门编号class:
public class DeptId implements Serializable
{
private int number;
private String country;
// ...
}
其实这没什么特别的。注意 ProjectId
class 有一个嵌套的复合 PK class 字段 private DeptId dept;
.
现在回答我的问题...
本书后面的几页,在“使用 EmbeddedId”部分的末尾,有一个更大的注释/子部分,名为“替代派生标识符”和文本(您不一定需要阅读整个模糊来回答这个问题,我 post 这只是为了完整性):
The @MapsId
annotation and the ability to apply @Id
to relationship attributes was introduced in JPA 2.0 to improve the situation that existed in JPA 1.0. At that time, only the one-to-one shared primary key scenario was specified using the @PrimaryKeyJoinColumn
annotation (using the Id
annotation is the preferred and recommended method going forward.
Although there was no specified way to solve the general case of including a foreign key in an identifier, it was generally supported through the practice of adding one or more additional (redundant) fields to the dependent entity. Each added field would hold a foreign key to the related entity, and, because both the added field and the relationship would be mapped to the same join column(s), one or the other of the two would need to marked as read-only (see "Read-Only Mappings" section), or not updatable or insertable. The following example shows how Listing 10-17 [author not: Project
entity above!] would be done using JPA 1.0. The ID class would be the same. Since the deptNumber
and deptCountry
attributes are identifier attributes, and can't be changed in the database, there is no need to set their updatability to false
.
@Entity
@IdClass(ProjectId.class)
public class Project
{
@Id
private String name;
@Id
@Column(name = "DEPT_NUM", insertable = false)
private int deptNumber;
@Id
@Column(name = "DEPT_NUM", insertable = false)
private String deptCountry;
@ManyToOne
@JoinColumns({
@JoinColumn(name="DEPT_NUM", referencedColumnName="NUM"),
@JoinColumn(name="DEPT_CTRY", referencedColumnName="COUNTRY")
})
private Department dept;
// ...
}
所以,这就是“JPA 1.0”方式。根据
The ID class would be the same.
这意味着 ProjectId
ID class 如上所示,但是,JPA 1.0 不 允许嵌套 class还没有。因此,本书作者在这里可能想说的是,向后兼容的非派生标识符映射如下所示。
现在问题:
对于冗余的 @id
字段映射,JPA 2.0 ProjectId
看起来像什么,即 with 嵌套ID class?书中没有展示... ♂️
public class ProjectId implements Serializable
{
private String name;
private DeptId ?; <-- dept or deptId?
public ProjectId() {}
public ProjectId(DeptId deptId, String name)
{
this.? = deptId;
this.name = name;
}
// ...
}
由于关系 private Department dept;
不再使用 @Id
映射为派生标识符,因此是类型为 DeptId
的嵌套 ID class 字段的名称 still 需要命名为 dept
或者它基本上可以命名为任何东西,例如deptId
或 department
?
这很重要。如果名称必须保留关系的名称,那么为派生标识符制定的规则也将适用于使用 JPA 2.x 嵌套 ID classes...[= 的非派生标识符映射44=]
PS:请注意,这是一个 JPA 规范问题,我自己无法回答。使用 EclipseLink 或任何其他 JPA 提供程序尝试此操作也不能保证所描述的行为已正确实现。例如,当 ProjectId
中的 DeptId
字段的名称与实体中的关系名称不同时,Hibernate 会抛出 AnnotationException
。
我添加了 JPA 提供程序标签以吸引合适的人来帮助我解决这个问题。谢谢。
根据与 JPA 有关的任何事情,虽然这本书很好(并且由知识渊博的人撰写,其中一位直接参与了规范的编写),但如果有任何疑问,请转到规范本身为了澄清。派生 ID 包含在第 2.4.1 节中的示例中,可以为您解决这个问题。它需要ProjectId.class
使用相同名称作为实体中的 ID 值,并且使用相同类型作为它引用的 ID - 与您为 DeptId 所做的格式相同。在这种情况下,它需要是:
public class ProjectId implements Serializable
{
private String name;
private DeptId dept;
// ...
}
至于 JPA 1.0 用法 - 关于 ID class 相同的声明可能意味着 ID class 为此需要相同的 3 个 ID 字段(和类型) @ID
注释 - 与现在对此类 class 定义的注释相同。如果您将其标记为 @ID
,它必须在 ID class 中表示。
“Java EE 8 中的 Pro JPA 2”一书的第 10 章,名为“多个映射属性”的部分,其中有使用 @IdClass
的著名部门项目示例,完整https://github.com/Apress/pro-jpa-2-in-java-ee-8/tree/master/examples/Chapter10/08-multipleMappedAttributes/src/model/examples/model.
下面是短篇小说。
项目实体:
@Entity
@IdClass(ProjectId.class)
public class Project
{
@Id
private String name;
@Id
@ManyToOne
@JoinColumns({
@JoinColumn(name="DEPT_NUM", referencedColumnName="NUM"),
@JoinColumn(name="DEPT_CTRY", referencedColumnName="COUNTRY")
})
private Department dept;
// ...
}
项目 ID class:
public class ProjectId implements Serializable
{
private String name;
private DeptId dept; <-- named dept to conform with derived identifier naming conventions
public ProjectId() {}
public ProjectId(DeptId deptId, String name)
{
this.dept = deptId; <-- naming "mismatch"
this.name = name;
}
// ...
}
部门实体:
@Entity
@IdClass(DeptId.class)
public class Department
{
@Id
@Column(name="NUM")
private int number;
@Id
private String country;
private String name;
// ...
}
部门编号class:
public class DeptId implements Serializable
{
private int number;
private String country;
// ...
}
其实这没什么特别的。注意 ProjectId
class 有一个嵌套的复合 PK class 字段 private DeptId dept;
.
现在回答我的问题...
本书后面的几页,在“使用 EmbeddedId”部分的末尾,有一个更大的注释/子部分,名为“替代派生标识符”和文本(您不一定需要阅读整个模糊来回答这个问题,我 post 这只是为了完整性):
The
@MapsId
annotation and the ability to apply@Id
to relationship attributes was introduced in JPA 2.0 to improve the situation that existed in JPA 1.0. At that time, only the one-to-one shared primary key scenario was specified using the@PrimaryKeyJoinColumn
annotation (using theId
annotation is the preferred and recommended method going forward.
Although there was no specified way to solve the general case of including a foreign key in an identifier, it was generally supported through the practice of adding one or more additional (redundant) fields to the dependent entity. Each added field would hold a foreign key to the related entity, and, because both the added field and the relationship would be mapped to the same join column(s), one or the other of the two would need to marked as read-only (see "Read-Only Mappings" section), or not updatable or insertable. The following example shows how Listing 10-17 [author not:
Project
entity above!] would be done using JPA 1.0. The ID class would be the same. Since thedeptNumber
anddeptCountry
attributes are identifier attributes, and can't be changed in the database, there is no need to set their updatability tofalse
.
@Entity
@IdClass(ProjectId.class)
public class Project
{
@Id
private String name;
@Id
@Column(name = "DEPT_NUM", insertable = false)
private int deptNumber;
@Id
@Column(name = "DEPT_NUM", insertable = false)
private String deptCountry;
@ManyToOne
@JoinColumns({
@JoinColumn(name="DEPT_NUM", referencedColumnName="NUM"),
@JoinColumn(name="DEPT_CTRY", referencedColumnName="COUNTRY")
})
private Department dept;
// ...
}
所以,这就是“JPA 1.0”方式。根据
The ID class would be the same.
这意味着 ProjectId
ID class 如上所示,但是,JPA 1.0 不 允许嵌套 class还没有。因此,本书作者在这里可能想说的是,向后兼容的非派生标识符映射如下所示。
现在问题:
对于冗余的 @id
字段映射,JPA 2.0 ProjectId
看起来像什么,即 with 嵌套ID class?书中没有展示... ♂️
public class ProjectId implements Serializable
{
private String name;
private DeptId ?; <-- dept or deptId?
public ProjectId() {}
public ProjectId(DeptId deptId, String name)
{
this.? = deptId;
this.name = name;
}
// ...
}
由于关系 private Department dept;
不再使用 @Id
映射为派生标识符,因此是类型为 DeptId
的嵌套 ID class 字段的名称 still 需要命名为 dept
或者它基本上可以命名为任何东西,例如deptId
或 department
?
这很重要。如果名称必须保留关系的名称,那么为派生标识符制定的规则也将适用于使用 JPA 2.x 嵌套 ID classes...[= 的非派生标识符映射44=]
PS:请注意,这是一个 JPA 规范问题,我自己无法回答。使用 EclipseLink 或任何其他 JPA 提供程序尝试此操作也不能保证所描述的行为已正确实现。例如,当 ProjectId
中的 DeptId
字段的名称与实体中的关系名称不同时,Hibernate 会抛出 AnnotationException
。
我添加了 JPA 提供程序标签以吸引合适的人来帮助我解决这个问题。谢谢。
根据与 JPA 有关的任何事情,虽然这本书很好(并且由知识渊博的人撰写,其中一位直接参与了规范的编写),但如果有任何疑问,请转到规范本身为了澄清。派生 ID 包含在第 2.4.1 节中的示例中,可以为您解决这个问题。它需要ProjectId.class
使用相同名称作为实体中的 ID 值,并且使用相同类型作为它引用的 ID - 与您为 DeptId 所做的格式相同。在这种情况下,它需要是:
public class ProjectId implements Serializable
{
private String name;
private DeptId dept;
// ...
}
至于 JPA 1.0 用法 - 关于 ID class 相同的声明可能意味着 ID class 为此需要相同的 3 个 ID 字段(和类型) @ID
注释 - 与现在对此类 class 定义的注释相同。如果您将其标记为 @ID
,它必须在 ID class 中表示。