【问题标题】:Spring Data JDBC: Required identifier property not found for a MappedCollectionSpring Data JDBC:未找到 MappedCollection 所需的标识符属性
【发布时间】:2020-06-15 03:28:38
【问题描述】:
class Game(
    @MappedCollection(idColumn = "game")         <---- unnecessary
    var rules: List<Rule> = emptyList(),
){
    @Id
    var id: Long? = null
}

data class Rule(
    @MappedCollection(idColumn = "rule", keyColumn = "rule_key")<---- unnecessary
    val ruleValues: List<RuleValue>
) 

data class RuleValue(val value: String)

架构是

create table game
(
    id              serial primary key
);

create table rule
(
    id              serial primary key,
    game            long references game (id),
    game_key        integer
);

create table rule_value
(
    id               serial primary key,
    game             long references game (id),
    game_key         integer,
    rule             long references rule (id),
    rule_key         integer,
    value            varchar(256)
);

简而言之,我有一个 Game 作为根聚合。 game 有一个Rules 的列表(顺序很重要),rule 有一个rule values 的列表(顺序很重要)。 rule value 现在只是一个字符串,但将来可能会扩展。

我有两个问题:

1) 找不到所需的标识符属性:当我尝试保存游戏时,我收到Caused by: java.lang.IllegalStateException: Required identifier property not found for class com...RuleValue! 异常消息。

2) java.sql.SQLSyntaxErrorException:为什么我需要rule_value 表中的gamegame_key 列?如果我不放它们,我会得到Caused by: java.sql.SQLSyntaxErrorException: Unknown column 'game_key' in 'field list'

我使用 Spring Boot 版本 2.2.5.RELEASE 和 org.springframework.boot:spring-boot-starter-data-jdbc 对应于 spring-data-jdbc 版本 1.1.5.RELEASE


SOLUTION-1:在类中添加 ID 字段

正如@chrylis-onstrike- 建议的那样,我在所有数据类中添加了@Id 字段

class Game(
    @MappedCollection(idColumn = "game")
    var rules: List<Rule> = emptyList(),
){
    @Id
    var id: Long? = null
}

data class Rule(
    @MappedCollection(idColumn = "rule", keyColumn = "rule_key")
    val ruleValues: List<RuleValue>
) {
    @Id
    var id: Long? = null <---- this is new
}

data class RuleValue(val value: String) {
    @Id
    var id: Long? = null  <---- this is new
}

并且架构更改为

create table game
(
    id              serial primary key
);

create table rule
(
    id              serial primary key,
    game            long references game (id),
    game_key        integer
);

create table rule_value
(
    id               serial primary key,
#    game             long references game (id), <---- removed this
#    game_key         integer,                   <---- removed this
    rule             long references rule (id),
    rule_key         integer,
    value            varchar(256)
);


SOLUTION-2:在脚本中添加复合主键

class Game(
    @MappedCollection(idColumn = "game")
    var rules: List<Rule> = emptyList(),
){
    @Id
    var id: Long? = null
}

data class Rule(
    @MappedCollection(idColumn = "rule", keyColumn = "rule_key")
    val ruleValues: List<RuleValue>
)

data class RuleValue(val value: String) 

并且架构更改为

create table game
(
    id              serial primary key
);

create table rule
(
#    id      serial primary key, <---- removed 
    game     integer,
    game_key integer,
    primary key (game, game_key) <---- added 
);

create table rule_value
(
#    id      serial primary key, <---- removed 
    game     integer, <---- added 
    game_key integer, <---- added 
    rule_key integer,
    value    varchar(2048),
    primary key (game, game_key, rule_key) <---- added 
);


结论 您需要确定您的对象是value objects 还是实体。值对象在类中可能不应该有 id 字段,因为它的身份是由它携带的值定义的。但是,您需要识别数据库表中的一行并将其与其所有者相关联,因此如果要将它们持久保存在不同的表中,则需要在值对象中创建复合主键。

【问题讨论】:

  • 嗯?您的 RuleValue 类似乎只有一个属性 String value
  • @chrylis-onstrike- A rule value is just a string for now but may extend in the future. 问题不在于它只是一个字符串值。
  • 正是问题:你的类没有主键,这正是 Spring Data 告诉你的。
  • @chrylis-onstrike- 在所有教程中这样的数据类没有Id 但聚合根为什么我需要添加和Id 到数据类?
  • 您的问题现在很长,包含历史、解决方案和另一个问题。看起来更像是一场讨论。

标签: java mysql kotlin spring-data spring-data-jdbc


【解决方案1】:
  1. 找不到所需的标识符属性。

    我同意@chrylis-onstrike - 该错误告诉您添加带有@Id 注释的字段。 但我也同意你的观点:不应该是这样。 我至少需要一个完整的堆栈跟踪来了解发生了什么。 复制器会更好。 随时在https://jira.spring.io/browse/DATAJDBC 上创建问题

    对提供的复制器的进一步调查表明,问题是由 id 列仍然存在于数据库中并且是 identity 列引起的。 因此,在插入之后,JDBC 确实返回了一个值,Spring Data JDBC 尝试将其设置为实体上的 id,然后未能设置该 id,但问题中提到了异常。

  2. 为什么我需要rule_value 表中的游戏和game_key 列?

    只要Rule 没有专用ID,它的主键就是gamegame_key 的组合,因此来自rule_value 的引用由这两个字段组成。

    Rule 有 id 时,它们不应该是必需的。

【讨论】:

  • 大约 2-game_key 和 game 是不必要的,我猜你把它和规则混为一谈了。
  • @hevi 你是对的,我误解了这个问题。更新了我的答案。
  • Id 的问题恐怕是 Kotlin spring-data-jdbc 互操作性问题引起的。
  • 恐怕这可能是正确的。你能用复制器制造问题吗?
  • 用从复制者那里收集的信息更新了答案。
猜你喜欢
  • 1970-01-01
  • 2019-10-10
  • 1970-01-01
  • 1970-01-01
  • 2022-10-07
  • 2021-12-06
  • 2021-06-27
  • 1970-01-01
  • 2015-11-30
相关资源
最近更新 更多