父表和子表之间的映射不正确
Incorrect mapping between Father and Child tables
我正在尝试在 Spring 数据 JDBC(版本 1.1.5.RELEASE)中建立 Father/Children 关系模型。到目前为止,我已经设法使插入操作正常工作,但在读取数据时遇到错误。
实体看起来像这样
@Table("FATHER")
data class FatherDao(
@Id
val id: Long?,
@MappedCollection(idColumn="father_id")
val childrens: Set<ChildrenDao>
)
@Table("CHILDREN")
data class ChildrenDao(
@Id
val id: Long?,
val father: FatherDao?
)
架构如下:
CREATE TABLE father (
id INT GENERATED BY DEFAULT AS IDENTITY(START WITH 1, INCREMENT BY 1)
PRIMARY KEY (id)
);
CREATE TABLE children (
id INT GENERATED BY DEFAULT AS IDENTITY(START WITH 1, INCREMENT BY 1),
father_id INT
PRIMARY KEY (id)
);
现在我已经省略了 character_id
上的外键。
存储库很简单
@Repository
interface FatherRepository : CrudRepository<CharacterDao, Long>
为了保存与父亲关联的子实体,我不调用 ChildrenRepository
而是继续保存父亲实体。
创建很顺利,但是当试图获取创建的实体时,我收到以下异常
user lacks privilege or object not found: FATHER.CHILDREN_DAO in statement [SELECT CHILDREN.id AS id, father.id AS father_id FROM CHILDREN LEFT OUTER JOIN FATHER AS father ON father.children_dao = CHILDREN.id WHERE CHILDREN.father_id = ?]
我的主要问题是我无法理解 FATHER.CHILDREN_DAO
的来源。我相当确定这是由 FatherDao
实体中的错误映射引起的,但即使在 Spring Data JDBC docs 中查看有关集合的信息,我也找不到任何线索。
您似乎试图在 FatherDao
和 ChildrenDao
之间建立双向关系。
Spring 数据 JDBC 不支持此功能。
这两个连接被认为是独立的,Spring 数据 JDBC 尝试加载由 children 引用的父亲,根据映射规则,父亲需要一个 CHILDREN_DAO
。
根据您的域,有两种变体可以解决问题。
重要的问题是:children 是父亲聚合的一部分还是它们自己的聚合?
如果 children 是父亲聚合的一部分,请删除 father
引用或用 @Transient
标记它。
在后一种情况下,您可以在 FatherDao
或 AfterLoadCallback
的构造函数中设置值
如果 children 是他们自己的聚合体,则 childrens
和 father
引用都应该被删除,取而代之的是一个 id(或应使用包含 id 的实体集)。
您可以使用查询方法来加载 child 的父亲,而不是双向关系,反之亦然。
文章 Spring Data JDBC, References, and Aggregates 解释了此设计决策背后的原因,并提供了如何实施的示例。
我正在尝试在 Spring 数据 JDBC(版本 1.1.5.RELEASE)中建立 Father/Children 关系模型。到目前为止,我已经设法使插入操作正常工作,但在读取数据时遇到错误。
实体看起来像这样
@Table("FATHER")
data class FatherDao(
@Id
val id: Long?,
@MappedCollection(idColumn="father_id")
val childrens: Set<ChildrenDao>
)
@Table("CHILDREN")
data class ChildrenDao(
@Id
val id: Long?,
val father: FatherDao?
)
架构如下:
CREATE TABLE father (
id INT GENERATED BY DEFAULT AS IDENTITY(START WITH 1, INCREMENT BY 1)
PRIMARY KEY (id)
);
CREATE TABLE children (
id INT GENERATED BY DEFAULT AS IDENTITY(START WITH 1, INCREMENT BY 1),
father_id INT
PRIMARY KEY (id)
);
现在我已经省略了 character_id
上的外键。
存储库很简单
@Repository
interface FatherRepository : CrudRepository<CharacterDao, Long>
为了保存与父亲关联的子实体,我不调用 ChildrenRepository
而是继续保存父亲实体。
创建很顺利,但是当试图获取创建的实体时,我收到以下异常
user lacks privilege or object not found: FATHER.CHILDREN_DAO in statement [SELECT CHILDREN.id AS id, father.id AS father_id FROM CHILDREN LEFT OUTER JOIN FATHER AS father ON father.children_dao = CHILDREN.id WHERE CHILDREN.father_id = ?]
我的主要问题是我无法理解 FATHER.CHILDREN_DAO
的来源。我相当确定这是由 FatherDao
实体中的错误映射引起的,但即使在 Spring Data JDBC docs 中查看有关集合的信息,我也找不到任何线索。
您似乎试图在 FatherDao
和 ChildrenDao
之间建立双向关系。
Spring 数据 JDBC 不支持此功能。
这两个连接被认为是独立的,Spring 数据 JDBC 尝试加载由 children 引用的父亲,根据映射规则,父亲需要一个 CHILDREN_DAO
。
根据您的域,有两种变体可以解决问题。 重要的问题是:children 是父亲聚合的一部分还是它们自己的聚合?
如果 children 是父亲聚合的一部分,请删除 father
引用或用 @Transient
标记它。
在后一种情况下,您可以在 FatherDao
或 AfterLoadCallback
如果 children 是他们自己的聚合体,则 childrens
和 father
引用都应该被删除,取而代之的是一个 id(或应使用包含 id 的实体集)。
您可以使用查询方法来加载 child 的父亲,而不是双向关系,反之亦然。
文章 Spring Data JDBC, References, and Aggregates 解释了此设计决策背后的原因,并提供了如何实施的示例。