简体   繁体   English

JPA - 如何使用规范和@EmbeddedId 进行查询?

[英]JPA - How to query using Specification and @EmbeddedId?

I'm using a JPA query that uses a specification to retrieve entities.我正在使用使用规范来检索实体的 JPA 查询。 When I execute the query, I'm getting the error:当我执行查询时,我收到错误:

org.springframework.data.mapping.PropertyReferenceException: No property name found for type Task! org.springframework.data.mapping.PropertyReferenceException:找不到类型任务的属性名称!

I've looked at the answers to similar questions that have been asked on this site previously & tried to model my code to follow the patterns that were recommended but the code is still failing.我查看了之前在此站点上提出的类似问题的答案,并尝试对我的代码进行建模以遵循推荐的模式,但代码仍然失败。

When I step through the code with a debugger, the expanded path in the criteria builder is returning the embedded ID class, but when the specification is actually used in the query it looks like the attribute is being applied to the base entity class.当我使用调试器单步执行代码时,条件构建器中的扩展路径返回嵌入的 ID 类,但是当在查询中实际使用规范时,看起来该属性正在应用于基本实体类。

Am I missing something obvious?我错过了一些明显的东西吗?

Here is the entity class:这是实体类:

@Entity
@Table(name = "TASKS")
public class Task implements Serializable {

    @EmbeddedId
    private TaskId id;

    ...more attributes, getters and setters
}

Here is the embedded ID entity class:这是嵌入的 ID 实体类:

@Embeddable
public class TaskId implements Serializable {

    @Column(name = "NAME", length = 100)
    private String name;

    ...more attributes, getters and setters
}

Here is the specification builder that matches on the embedded id 'name' attribute:这是与嵌入的 id 'name' 属性匹配的规范构建器:

public class HasTaskNameSpec {

    private HasTaskNameSpec() {
    }

    public static Specification<Task> equals(String name) {
        return (root, query, criteriaBuilder) -> {
            return criteriaBuilder.equal(root.get("id").get("name"), taskName);
        };
    }

}

The query is executed on the repository as follows:查询在存储库上执行如下:

List<Task> results = taskRepository.findAll(HasTaskNameSpec.equals("foo"));

The repository itself is very simple:存储库本身非常简单:

public interface TaskRepository extends JpaRepository<Task, TaskId>, JpaSpecificationExecutor<Task> {
   List<Task> findByIdName(String name);
   Page<Task> findByIdName(String name, Pageable page);    
}

** EDIT added methods to repository as was suggested below ** **编辑向存储库添加的方法,如下所示 **

Ahh, the root cause was totally in our codebase.啊,根本原因完全在我们的代码库中。 There was a sort order being specified on the page that didn't include the embedded "id" attribute.页面上指定的排序顺序不包含嵌入的“id”属性。 The above code works.上面的代码有效。

'root.get({embeddedIdName}).get({subPropertyName})' is used to query on embeddedId using specification. 'root.get({embeddedIdName}).get({subPropertyName})' 用于使用规范查询embeddedId。

@Embeddable
public class ProjectId implements Serializable{

    private static final long serialVersionUID = 1L;

    @Column(name = "PROJECT_NAME")
    private String projectName;

    @Column(name = "ORGANIZATION")
    private String organization;

    ......
    ......

}


@Entity
@Table(name = "projects")
public class Project {

    @EmbeddedId
    private ProjectId projectId;

    @Column(name = "STARTED_TIME")
    private Timestamp startedTime;

    @Column(name = "ACTIVE")
    private String active;

    @Column(name = "DESCRIPTION")
    private String description;

    ......
    ......
}

In the above snippet, ProjectId is an embedded id.在上面的代码片段中,ProjectId 是一个嵌入的 id。 To query on projectName, we should use below snippet.要查询 projectName,我们应该使用以下代码段。

expression = root.get("projectId").get("projectName");

Demo application link .演示应用程序链接

Take a look at this link which has a similar query.看看这个链接,它有一个类似的查询。

EmbbededId Lookup 嵌入式 ID 查找

The final answer suggests that you can add a method to your TaskRepository thus.最终答案表明您可以因此向您的 TaskRepository 添加一个方法。

public interface TaskRepository extends JpaRepository<Task, TaskId>, JpaSpecificationExecutor<Task> {
   public List<Task> findByIdName(String name);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM