spring-data-jdbc: JdbcQueryCreator: 无法按嵌套实体查询
spring-data-jdbc: JdbcQueryCreator: Cannot query by nested entity
我正在使用 Spring Boot 创建服务(第一次使用 Spring)。我在数据库中有一个由三元组 (mission, cycle, id)
标识的实体,这在逻辑上是主键。
为了解决 Spring-data-jdbc 具有 @Id Long
主键的要求,我创建了一个 IDENTITY
主键并为这些添加了 UNIQUE
约束列。在我的实验中,我有两个 table 以这种方式键入(第二个在逻辑键中有一个附加列):
CREATE TABLE IF NOT EXISTS submission_counter (
id IDENTITY NOT NULL PRIMARY KEY,
mission VARCHAR(10) NOT NULL,
cycle INTEGER NOT NULL,
proposal_id INTEGER NOT NULL,
count INTEGER NOT NULL DEFAULT 1,
UNIQUE (mission, proposal_id, cycle),
CHECK (count >= 1),
CHECK (proposal_id >= 1)
);
CREATE TABLE IF NOT EXISTS submission (
id IDENTITY NOT NULL PRIMARY KEY,
mission VARCHAR(10) NOT NULL,
cycle INTEGER NOT NULL,
proposal_id INTEGER NOT NULL,
number INTEGER NOT NULL,
CHECK (number >= 1),
CHECK (proposal_id >= 1),
UNIQUE (mission, cycle, proposal_id, number)
);
为了在 Java 代码中打包密钥三元组,我为两个实体 类 创建了一个嵌入式记录。
enum Mission {A, B, C}
public record SubmissionCount(int count){}
public record ProposalId(int id) {}
public record SubmissionNumber(int number) {}
public record SubmissionKey(Mission mission, Cycle cycle, ProposalId proposalId) {}
public record Submission(@Id Long id, SubmissionKey key, SubmissionNumber number) {}
public record SubmissionCounter(@Id Long id, SubmissionKey key, SubmissionCount count) {}
以前,我将所有 SubmissionKey
字段内联在使用它们的记录中,并且一切正常。现在,当尝试为密钥编写查询时,我从 JdbcQueryCreator
得到一个异常
此存储库定义结果“无法按嵌套实体查询”:
public interface SubmissionRepository extends CrudRepository<Submission, Long> {
Streamable<Submission> findByKey(SubmissionKey key);
}
Caused by: java.lang.IllegalArgumentException: Cannot query by nested entity: key
at org.springframework.data.jdbc.repository.query.JdbcQueryCreator.validateProperty(JdbcQueryCreator.java:147)
我试过用多种方式编写存储库查询方法。我最近的尝试是基于一些问题说方法名可以做字段导航。
public interface SubmissionCounterRepository extends CrudRepository<SubmissionCounter, Long> {
Optional<SubmissionCounter> findByKeyMissionAndKeyCycleAndKeyProposalId(SubmissionKey key);
}
这导致
Caused by: java.lang.IllegalStateException: Query method expects at least 2 arguments but only found 1. This leaves an operator of type SIMPLE_PROPERTY for property key.cycle unbound.
at org.springframework.data.relational.repository.query.RelationalQueryCreator.throwExceptionOnArgumentMismatch(RelationalQueryCreator.java:126)
at org.springframework.data.relational.repository.query.RelationalQueryCreator.validate(RelationalQueryCreator.java:110)
at org.springframework.data.jdbc.repository.query.JdbcQueryCreator.validate(JdbcQueryCreator.java:117)
如果我手动滚动所有内容,我会将 (mission, cycle, proposal_id)
三元组仅放在 submission_counter
table 中,并将其与 submission
结合起来进行读取。
Spring有更好的方法吗?我可以使用 @Query
和命名参数进行字段导航吗?
几天后回过头来,问题是 SubmissionKey
元素上缺少 @Embedded
注释。
像这样添加 @Embedded
解决了问题:
public record Submission(@Id Long id, @Embedded(onEmpty = Embedded.OnEmpty.USE_EMPTY) SubmissionKey key, SubmissionNumber number) {}
public record SubmissionCounter(@Id Long id, @Embedded(onEmpty = USE_EMPTY) SubmissionKey key, SubmissionCount count) {}
这让我可以在我的存储库接口上定义 findByKey
方法,并且可以正确派生查询:
public interface SubmissionRepository extends CrudRepository<Submission, Long> {
Streamable<Submission> findByKey(SubmissionKey key);
}
public interface SubmissionCounterRepository extends CrudRepository<SubmissionCounter, Long> {
Optional<SubmissionCounter> findByKey(SubmissionKey key);
}
我认为“无法通过嵌套实体查询”的错误意味着 Spring JDBC 得出的结论是 SubmissionKey
是嵌套在 Submission
实体中的单独实体.事后看来很明显。
我正在使用 Spring Boot 创建服务(第一次使用 Spring)。我在数据库中有一个由三元组 (mission, cycle, id)
标识的实体,这在逻辑上是主键。
为了解决 Spring-data-jdbc 具有 @Id Long
主键的要求,我创建了一个 IDENTITY
主键并为这些添加了 UNIQUE
约束列。在我的实验中,我有两个 table 以这种方式键入(第二个在逻辑键中有一个附加列):
CREATE TABLE IF NOT EXISTS submission_counter (
id IDENTITY NOT NULL PRIMARY KEY,
mission VARCHAR(10) NOT NULL,
cycle INTEGER NOT NULL,
proposal_id INTEGER NOT NULL,
count INTEGER NOT NULL DEFAULT 1,
UNIQUE (mission, proposal_id, cycle),
CHECK (count >= 1),
CHECK (proposal_id >= 1)
);
CREATE TABLE IF NOT EXISTS submission (
id IDENTITY NOT NULL PRIMARY KEY,
mission VARCHAR(10) NOT NULL,
cycle INTEGER NOT NULL,
proposal_id INTEGER NOT NULL,
number INTEGER NOT NULL,
CHECK (number >= 1),
CHECK (proposal_id >= 1),
UNIQUE (mission, cycle, proposal_id, number)
);
为了在 Java 代码中打包密钥三元组,我为两个实体 类 创建了一个嵌入式记录。
enum Mission {A, B, C}
public record SubmissionCount(int count){}
public record ProposalId(int id) {}
public record SubmissionNumber(int number) {}
public record SubmissionKey(Mission mission, Cycle cycle, ProposalId proposalId) {}
public record Submission(@Id Long id, SubmissionKey key, SubmissionNumber number) {}
public record SubmissionCounter(@Id Long id, SubmissionKey key, SubmissionCount count) {}
以前,我将所有 SubmissionKey
字段内联在使用它们的记录中,并且一切正常。现在,当尝试为密钥编写查询时,我从 JdbcQueryCreator
此存储库定义结果“无法按嵌套实体查询”:
public interface SubmissionRepository extends CrudRepository<Submission, Long> {
Streamable<Submission> findByKey(SubmissionKey key);
}
Caused by: java.lang.IllegalArgumentException: Cannot query by nested entity: key
at org.springframework.data.jdbc.repository.query.JdbcQueryCreator.validateProperty(JdbcQueryCreator.java:147)
我试过用多种方式编写存储库查询方法。我最近的尝试是基于一些问题说方法名可以做字段导航。
public interface SubmissionCounterRepository extends CrudRepository<SubmissionCounter, Long> {
Optional<SubmissionCounter> findByKeyMissionAndKeyCycleAndKeyProposalId(SubmissionKey key);
}
这导致
Caused by: java.lang.IllegalStateException: Query method expects at least 2 arguments but only found 1. This leaves an operator of type SIMPLE_PROPERTY for property key.cycle unbound.
at org.springframework.data.relational.repository.query.RelationalQueryCreator.throwExceptionOnArgumentMismatch(RelationalQueryCreator.java:126)
at org.springframework.data.relational.repository.query.RelationalQueryCreator.validate(RelationalQueryCreator.java:110)
at org.springframework.data.jdbc.repository.query.JdbcQueryCreator.validate(JdbcQueryCreator.java:117)
如果我手动滚动所有内容,我会将 (mission, cycle, proposal_id)
三元组仅放在 submission_counter
table 中,并将其与 submission
结合起来进行读取。
Spring有更好的方法吗?我可以使用 @Query
和命名参数进行字段导航吗?
几天后回过头来,问题是 SubmissionKey
元素上缺少 @Embedded
注释。
像这样添加 @Embedded
解决了问题:
public record Submission(@Id Long id, @Embedded(onEmpty = Embedded.OnEmpty.USE_EMPTY) SubmissionKey key, SubmissionNumber number) {}
public record SubmissionCounter(@Id Long id, @Embedded(onEmpty = USE_EMPTY) SubmissionKey key, SubmissionCount count) {}
这让我可以在我的存储库接口上定义 findByKey
方法,并且可以正确派生查询:
public interface SubmissionRepository extends CrudRepository<Submission, Long> {
Streamable<Submission> findByKey(SubmissionKey key);
}
public interface SubmissionCounterRepository extends CrudRepository<SubmissionCounter, Long> {
Optional<SubmissionCounter> findByKey(SubmissionKey key);
}
我认为“无法通过嵌套实体查询”的错误意味着 Spring JDBC 得出的结论是 SubmissionKey
是嵌套在 Submission
实体中的单独实体.事后看来很明显。