自动生成的 ID 不会在 Hibernate 中的子实体中的 EmbeddedId 上级联
Auto generated id not cascading on EmbeddedId in child entity in Hibernate
尝试插入实体时 - A
与 set
另一个实体 B
、B
应该从 [= 获取自动生成的 Id
11=] 但它是 null
.
尝试失败:
@MapsId("taskPKId.storyId.id")
- 同样的错误。
@Embeddable
class StoryId {
@ManyToOne(fetch = FetchType.Lazy)
@JoinColumn(name = "STORY_ID")
Long id;
}
//不可理解的空指针异常
mappedBy("story")
- 同样的错误
- 尝试使用 mappedBy('story') 但重复列时出错,因此必须使用
insertable=false
和 updatable=false
进行映射 [Hibernate 无法识别 insertable=false
@EmbeddedId
]
我得到 STORY_ID = null
,因此 saveAll
在 storyRepository.saveAll(stories)
上失败,其中 storyRepository
是 Spring 数据存储库
@Table(name = "STORY")
@EqualsAndHashCode
class Story {
@Id
@GeneratedValue(stratergy=GenerationType.Auto)
@Column(name="STORY_ID")
Long id;
@Column(name="STORY_NAME")
String name;
//@OneToMany(cascade=ALL, mappedBy="taskPKId.storyId.id", fetch = FetchType.Lazy) // tried this as well
@OneToMany(cascade=ALL, mappedBy="story", fetch = FetchType.Lazy)
Set<Task> task;
}
@Table(name = "TASK_XREF")
@EqualsAndHashCode
Class Task {
@EmbeddedId
TaskPKId taskPKId;
@Column(name = "TASK_NAME")
String name;
@ManyToOne (fetch = FetchType.Lazy, optional = false)
@JoinColumn(name = "STORY_ID", referencedColumnName = "STORY_ID", nullable = false, insertable = false, updatable = false)
Story story;
}
@Embeddable
@EqualsAndHashCode
Class TaskPKId implements Serializable {
TaskId taskId;
TaskTypeId taskTypeId;
StoryId storyId;
}
@Embeddable
@EqualsAndHashCode
class StoryId implements Serializable {
@Column(name = "STORY_ID")
Long id;
}
表格:
- 故事 [
STORY_ID
, STORY_NAME
]
- TASK_XREF[
(TASK_ID(FK), TASK_TYPE_ID(FK), STORY_ID(FK))
PK,TASK_NAME
]
故事被插入(当然在提交之前),但失败了,因为 STORY_ID
被作为 null 发送到 TASK_XREF
以进行下一次插入
我不确定你想要实现什么,但看起来你已经将 @OneToMany
注释与类似 @OneToOne
的实现结合起来(这可能会导致像这样的意外行为)。
可能的解决方案:
如果一个故事拥有多个任务
// Story.java
@OneToMany(cascade=ALL, mappedBy="story", fetch = FetchType.Lazy)
Set<Task> task; // basically Set, List or any other collection type
// Task.java
@ManyToOne (fetch = FetchType.Lazy, optional = false)
@JoinColumn(name = "STORY_ID", referencedColumnName = "STORY_ID")
Story story;
如果一个故事只有一个任务
// Story.java
@OneToOne(cascade=ALL, mappedBy="story", fetch = FetchType.Lazy)
Task task;
// Task.java
@OneToOne (fetch = FetchType.Lazy, optional = false)
@JoinColumn(name = "STORY_ID", referencedColumnName = "STORY_ID")
Story story;
延伸阅读:
@OneToOne
@OneToMany
我不太确定为什么您的配置不起作用。我在我的一个项目中有一个类似的配置,效果很好。但是,通过向任务 class 中的 ManyToOne 添加 @MapsId 注释,我能够找到解决方案。 (有关 MapsId 的解释,请参阅 can someone please explain me @MapsId in hibernate?)我还删除了 insertable=false 和 updatable=false。代码见下方。
我没有让 MapsId 与 StoryId class 一起工作,所以我将 TaskPKID.storyId 的类型从 StoryId 更改为 long。 StoryId class 似乎没有增加太多,所以希望这不是什么大问题。如果您找到解决方案,请在评论中告诉我!
顺便说一句,你的代码有很多问题。有一堆拼写错误,属性 上有一个 OneToMany 映射,它不是 Collection(这是不允许的)这让我更难调试问题。下次请确保 post 在您的问题中使用质量更高的代码。
这是任务 class 我实现它的方式:
@Entity
@Table(name = "TASK_XREF")
class Task {
@EmbeddedId
TaskPKId taskPKId;
@Column(name = "TASK_NAME")
String name;
@MapsId("storyId")
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "STORY_ID")
Story story;
//getters, setters
}
这里是 TaskPKID class:
@Embeddable
class TaskPKId implements Serializable {
long taskId;
long taskTypeId;
@Column(name="STORY_ID")
long storyId;
public long getTaskId() {
return taskId;
}
public void setTaskId(long taskId) {
this.taskId = taskId;
}
public void setTaskTypeId(long taskTypeId) {
this.taskTypeId = taskTypeId;
}
}
尝试插入实体时 - A
与 set
另一个实体 B
、B
应该从 [= 获取自动生成的 Id
11=] 但它是 null
.
尝试失败:
@MapsId("taskPKId.storyId.id")
- 同样的错误。@Embeddable class StoryId { @ManyToOne(fetch = FetchType.Lazy) @JoinColumn(name = "STORY_ID") Long id; }
//不可理解的空指针异常mappedBy("story")
- 同样的错误- 尝试使用 mappedBy('story') 但重复列时出错,因此必须使用
insertable=false
和updatable=false
进行映射 [Hibernate 无法识别insertable=false
@EmbeddedId
]
- 尝试使用 mappedBy('story') 但重复列时出错,因此必须使用
我得到 STORY_ID = null
,因此 saveAll
在 storyRepository.saveAll(stories)
上失败,其中 storyRepository
是 Spring 数据存储库
@Table(name = "STORY")
@EqualsAndHashCode
class Story {
@Id
@GeneratedValue(stratergy=GenerationType.Auto)
@Column(name="STORY_ID")
Long id;
@Column(name="STORY_NAME")
String name;
//@OneToMany(cascade=ALL, mappedBy="taskPKId.storyId.id", fetch = FetchType.Lazy) // tried this as well
@OneToMany(cascade=ALL, mappedBy="story", fetch = FetchType.Lazy)
Set<Task> task;
}
@Table(name = "TASK_XREF")
@EqualsAndHashCode
Class Task {
@EmbeddedId
TaskPKId taskPKId;
@Column(name = "TASK_NAME")
String name;
@ManyToOne (fetch = FetchType.Lazy, optional = false)
@JoinColumn(name = "STORY_ID", referencedColumnName = "STORY_ID", nullable = false, insertable = false, updatable = false)
Story story;
}
@Embeddable
@EqualsAndHashCode
Class TaskPKId implements Serializable {
TaskId taskId;
TaskTypeId taskTypeId;
StoryId storyId;
}
@Embeddable
@EqualsAndHashCode
class StoryId implements Serializable {
@Column(name = "STORY_ID")
Long id;
}
表格:
- 故事 [
STORY_ID
,STORY_NAME
] - TASK_XREF[
(TASK_ID(FK), TASK_TYPE_ID(FK), STORY_ID(FK))
PK,TASK_NAME
]
故事被插入(当然在提交之前),但失败了,因为 STORY_ID
被作为 null 发送到 TASK_XREF
以进行下一次插入
我不确定你想要实现什么,但看起来你已经将 @OneToMany
注释与类似 @OneToOne
的实现结合起来(这可能会导致像这样的意外行为)。
可能的解决方案:
如果一个故事拥有多个任务
// Story.java @OneToMany(cascade=ALL, mappedBy="story", fetch = FetchType.Lazy) Set<Task> task; // basically Set, List or any other collection type // Task.java @ManyToOne (fetch = FetchType.Lazy, optional = false) @JoinColumn(name = "STORY_ID", referencedColumnName = "STORY_ID") Story story;
如果一个故事只有一个任务
// Story.java @OneToOne(cascade=ALL, mappedBy="story", fetch = FetchType.Lazy) Task task; // Task.java @OneToOne (fetch = FetchType.Lazy, optional = false) @JoinColumn(name = "STORY_ID", referencedColumnName = "STORY_ID") Story story;
延伸阅读: @OneToOne @OneToMany
我不太确定为什么您的配置不起作用。我在我的一个项目中有一个类似的配置,效果很好。但是,通过向任务 class 中的 ManyToOne 添加 @MapsId 注释,我能够找到解决方案。 (有关 MapsId 的解释,请参阅 can someone please explain me @MapsId in hibernate?)我还删除了 insertable=false 和 updatable=false。代码见下方。
我没有让 MapsId 与 StoryId class 一起工作,所以我将 TaskPKID.storyId 的类型从 StoryId 更改为 long。 StoryId class 似乎没有增加太多,所以希望这不是什么大问题。如果您找到解决方案,请在评论中告诉我!
顺便说一句,你的代码有很多问题。有一堆拼写错误,属性 上有一个 OneToMany 映射,它不是 Collection(这是不允许的)这让我更难调试问题。下次请确保 post 在您的问题中使用质量更高的代码。
这是任务 class 我实现它的方式:
@Entity
@Table(name = "TASK_XREF")
class Task {
@EmbeddedId
TaskPKId taskPKId;
@Column(name = "TASK_NAME")
String name;
@MapsId("storyId")
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "STORY_ID")
Story story;
//getters, setters
}
这里是 TaskPKID class:
@Embeddable
class TaskPKId implements Serializable {
long taskId;
long taskTypeId;
@Column(name="STORY_ID")
long storyId;
public long getTaskId() {
return taskId;
}
public void setTaskId(long taskId) {
this.taskId = taskId;
}
public void setTaskTypeId(long taskTypeId) {
this.taskTypeId = taskTypeId;
}
}