JPA - 如何使用规范和@EmbeddedId 进行查询?
JPA - How to query using Specification and @EmbeddedId?
我正在使用 JPA 查询,该查询使用规范来检索实体。当我执行查询时,出现错误:
org.springframework.data.mapping.PropertyReferenceException: No property name found for type Task!
我查看了之前在此站点上提出的类似问题的答案,并尝试对我的代码进行建模以遵循推荐的模式,但代码仍然失败。
当我使用调试器单步执行代码时,条件构建器中的扩展路径返回嵌入的 ID class,但是当规范在查询中实际使用时,它看起来像是属性应用于基本实体 class.
我是不是遗漏了什么明显的东西?
这是实体 class:
@Entity
@Table(name = "TASKS")
public class Task implements Serializable {
@EmbeddedId
private TaskId id;
...more attributes, getters and setters
}
这是嵌入的 ID 实体 class:
@Embeddable
public class TaskId implements Serializable {
@Column(name = "NAME", length = 100)
private String name;
...more attributes, getters and setters
}
这是匹配嵌入 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);
};
}
}
查询在存储库上执行如下:
List<Task> results = taskRepository.findAll(HasTaskNameSpec.equals("foo"));
存储库本身非常简单:
public interface TaskRepository extends JpaRepository<Task, TaskId>, JpaSpecificationExecutor<Task> {
List<Task> findByIdName(String name);
Page<Task> findByIdName(String name, Pageable page);
}
** EDIT 按照下面的建议将方法添加到存储库 **
看看这个 link 有类似的查询。
EmbbededId Lookup
最后的答案建议您可以向您的 TaskRepository 添加一个方法。
public interface TaskRepository extends JpaRepository<Task, TaskId>, JpaSpecificationExecutor<Task> {
public List<Task> findByIdName(String name);
}
啊,根本原因完全在我们的代码库中。页面上指定的排序顺序不包含嵌入的 "id" 属性。上面的代码有效。
'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;
......
......
}
在上面的代码片段中,ProjectId 是一个嵌入式 ID。要查询 projectName,我们应该使用以下代码段。
expression = root.get("projectId").get("projectName");
演示应用程序 link。
我正在使用 JPA 查询,该查询使用规范来检索实体。当我执行查询时,出现错误:
org.springframework.data.mapping.PropertyReferenceException: No property name found for type Task!
我查看了之前在此站点上提出的类似问题的答案,并尝试对我的代码进行建模以遵循推荐的模式,但代码仍然失败。
当我使用调试器单步执行代码时,条件构建器中的扩展路径返回嵌入的 ID class,但是当规范在查询中实际使用时,它看起来像是属性应用于基本实体 class.
我是不是遗漏了什么明显的东西?
这是实体 class:
@Entity
@Table(name = "TASKS")
public class Task implements Serializable {
@EmbeddedId
private TaskId id;
...more attributes, getters and setters
}
这是嵌入的 ID 实体 class:
@Embeddable
public class TaskId implements Serializable {
@Column(name = "NAME", length = 100)
private String name;
...more attributes, getters and setters
}
这是匹配嵌入 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);
};
}
}
查询在存储库上执行如下:
List<Task> results = taskRepository.findAll(HasTaskNameSpec.equals("foo"));
存储库本身非常简单:
public interface TaskRepository extends JpaRepository<Task, TaskId>, JpaSpecificationExecutor<Task> {
List<Task> findByIdName(String name);
Page<Task> findByIdName(String name, Pageable page);
}
** EDIT 按照下面的建议将方法添加到存储库 **
看看这个 link 有类似的查询。
EmbbededId Lookup
最后的答案建议您可以向您的 TaskRepository 添加一个方法。
public interface TaskRepository extends JpaRepository<Task, TaskId>, JpaSpecificationExecutor<Task> {
public List<Task> findByIdName(String name);
}
啊,根本原因完全在我们的代码库中。页面上指定的排序顺序不包含嵌入的 "id" 属性。上面的代码有效。
'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;
......
......
}
在上面的代码片段中,ProjectId 是一个嵌入式 ID。要查询 projectName,我们应该使用以下代码段。
expression = root.get("projectId").get("projectName");
演示应用程序 link。