spring-data-jdbc:JdbcQueryCreator:无法按嵌套实体查询

发布于 2025-01-18 10:52:48 字数 3210 浏览 2 评论 0原文

我正在使用Spring Boot(首次使用Spring)创建服务。我有一个由三重(任务,周期,ID)识别的实体,在数据库中,这是逻辑上的主要密钥。
为了符合具有@id long主键的Spring-data-jdbc的要求,我已经创建了Identity primary键并添加unique这些列的约束。在我的实验中,我有两个以这种方式键入的表(第二个在逻辑密钥中具有添加列):

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) {}

以前,我在记录中使用的所有fibermisskey字段>使用它们的记录,这一切都很好。现在,在尝试编写键的查询时,我从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)仅在infim>提交> Counter_counter表中三倍,然后与提交< /代码>用于读取。

有一个更好的方法可以使用春天做到这一点吗?我可以使用@query和名称参数进行现场导航吗?

I'm in the process of creating a service using Spring Boot (first time using Spring). I have an entity that is identified by a triple (mission, cycle, id) in the database, this is logically the primary key.
To work around the requirement of Spring-data-jdbc of having an @Id Long primary key I have created an IDENTITY primary key and added UNIQUE constraints for these columns. In my experiment I have two tables that are keyed this way (the second has an addition column in the logical key):

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)
);

To package the key triple in the Java code I've created an embedded record for the two entity classes.

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) {}

Previously, I had all the SubmissionKey fields inlined in the records where they are used and this all worked fine. Now, when attempting to write a query for the key I get an exception from JdbcQueryCreator

This repository definition results "Cannot query by nested entity":

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)

I've tried writing the repository query method a number of ways. My latest attempt is based on a number of questions stating that the method name can do field navigation.

public interface SubmissionCounterRepository extends CrudRepository<SubmissionCounter, Long> {
    Optional<SubmissionCounter> findByKeyMissionAndKeyCycleAndKeyProposalId(SubmissionKey key);
}

This results in

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)

If I were hand rolling everything I would put the (mission, cycle, proposal_id) triple only in the submission_counter table and join that with the submission for reads.

Is there a better way to do this with Spring? Can I do field navigation using @Query and named parameters?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

独留℉清风醉 2025-01-25 10:52:48

几天后回到这个问题,问题是 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);
}

我认为错误说“Cannot Query by嵌套实体”意味着 Spring JDBC 断定 SubmissionKey 是嵌套在 Submission 实体内的单独实体。事后看来很明显。

Circling back to this after a few days, the issue was the missing @Embedded annotation on the SubmissionKey element.

Added @Embedded like this solved the issues:

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) {}

This allows me to define findByKey methods on my repository interfaces and the queries are correctly derived:

public interface SubmissionRepository extends CrudRepository<Submission, Long> {
    Streamable<Submission> findByKey(SubmissionKey key);
}

public interface SubmissionCounterRepository extends CrudRepository<SubmissionCounter, Long> {
    Optional<SubmissionCounter> findByKey(SubmissionKey key);
}

I think the error saying "Cannot Query by nested entity" meant that Spring JDBC had concluded that SubmissionKey was a separate entity nested inside the Submission entity. Obvious in hindsight.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文