我正在尝试执行一些过滤,但ManyToOne的过滤有一些问题,每次我得到结果集时,我都会得到所有Task对象,而不管它们所链接的项目如何。我有以下实体:
@Entity
public class Project implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "project_seq_gen")
@SequenceGenerator(name = "project_seq_gen", sequenceName = "project_id_seq", allocationSize = 1)
private Long id;
@Column(unique = true)
private String projectId;
//more things
}
和任务类,它通过它的id与项目链接
@Entity
public class Task implements Serializable {
@Id
private String id;
@Column
private String name;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "project_tasks")
private Project project;
@Column
private Enum<TaskType> type;
//more things....
}
在任务表中,它看起来像这样
|id |project_tasks |
|--------|--------------|
| TASK1 | 1 |
| TASK2 | 2 |
|--------|--------------|
我有jparepository来搜索任务:
@Repository
public interface TaskRepository extends JpaRepository<Task, Integer> , JpaSpecificationExecutor {
以及使用由org . hibernate . jpamodelgen . jpametamodelentityprocessor生成的元模型的规范
public class TaskSpecification implements Specification<Task> {
private final TaskFilter taskFilter;
public TaskSpecification(TaskFilter task) {
this.taskFilter = task;
}
@Override
public Predicate toPredicate(Root<Task> task, CriteriaQuery<?> cq, CriteriaBuilder cb) {
Predicate predicate = cb.conjunction();
//project
//approach 1
cb.and(predicate, task.join(Task_.project).get(Project_.id).in(taskFilter.getProject().getId()));
//approach 2
cb.and(predicate, cb.equal(task.get(Task_.project).get(Project_.id), taskFilter.getProject().getId()));
//some other filters to follow
if (StringUtils.isNotBlank(taskFilter.getByState())) {
if (TaskFilter.OPEN.equals(taskFilter.getByState())) {
predicate = cb.and(predicate, task.get(Task_.state).in(TaskState.TO_DO, TaskState.ONGOING, TaskState.COMPLETE, TaskState.BLOCKED));
} else {
predicate = cb.and(predicate, task.get(Task_.state).in(TaskState.valueOf(taskFilter.getByState())));
}
}
return predicate;
}
}
服务呼叫:
public List<Task> findBySpecification(TaskFilter filter) {
return taskRepo.findAll(new TaskSpecification(filter));
}
不幸的是,方法1和方法2的每个查询都返回所有任务,无论项目Id是什么。show_sql,控制台上显示了以下内容
方法 1
Hibernate: select task0_.id as id1_12_, task0_.active as active2_12_, task0_.task_assignee as task_as21_12_, task0_.create_date as create_d3_12_, task0_.description as descript4_12_, task0_.due_date as due_date5_12_, task0_.estimate as estimate6_12_, task0_.estimated as estimate7_12_, task0_.finishDate as finishDa8_12_, task0_.inSprint as inSprint9_12_, task0_.lastUpdate as lastUpd10_12_, task0_.loggedWork as loggedW11_12_, task0_.name as name12_12_, task0_.task_owner as task_ow22_12_, task0_.parent as parent13_12_, task0_.priority as priorit14_12_, task0_.project_tasks as project23_12_, task0_.release_id as release24_12_, task0_.remaining as remaini15_12_, task0_.state as state16_12_, task0_.story_points as story_p17_12_, task0_.subtasks as subtask18_12_, task0_.task_order as task_or19_12_, task0_.type as type20_12_ from Task task0_ inner join Project project1_ on task0_.project_tasks=project1_.id where 1=1 and (task0_.state in (? , ? , ? , ?))
方法 2
Hibernate: select task0_.id as id1_12_, task0_.active as active2_12_, task0_.task_assignee as task_as21_12_, task0_.create_date as create_d3_12_, task0_.description as descript4_12_, task0_.due_date as due_date5_12_, task0_.estimate as estimate6_12_, task0_.estimated as estimate7_12_, task0_.finishDate as finishDa8_12_, task0_.inSprint as inSprint9_12_, task0_.lastUpdate as lastUpd10_12_, task0_.loggedWork as loggedW11_12_, task0_.name as name12_12_, task0_.task_owner as task_ow22_12_, task0_.parent as parent13_12_, task0_.priority as priorit14_12_, task0_.project_tasks as project23_12_, task0_.release_id as release24_12_, task0_.remaining as remaini15_12_, task0_.state as state16_12_, task0_.story_points as story_p17_12_, task0_.subtasks as subtask18_12_, task0_.task_order as task_or19_12_, task0_.type as type20_12_ from Task task0_ where 1=1 and (task0_.state in (? , ? , ? , ?))
我们会很乐意帮忙的问候
您可能无法正确使用cb.and()函数。这个函数将返回一个新的组合谓词,而不是改变当前的谓词。< br >所以不用< br> cb.and(谓词,task.join(Task_。项目)。get(Project_。id)。在(taskFilter.getProject()中。getId()));
应该有< br> 谓词= cb.and(谓词,task.join(Task_。项目)。get(Project_。id)。在(taskFilter.getProject()中。getId()));
PSR 是 PHP Standard Recommendations 的简写,由 PHP FIG 组织制定的 PHP 规范,是 PHP 开发的实践标准。
我有一个父表,它与一个子表有许多关联。 我试图用CriteriaBuilder编写一个查询,以限制从子表返回的结果。 我添加了一个谓词,类似于 如果父节点有一个子节点或子节点和子节点,则返回父节点,同时也返回所有子节点。 Hibernate使用我的谓词启动了第一个查询,但是第二个获取孩子的查询只使用了where子句中的JoinColumn,而没有包含它 思想? 我正在使用SetJoin 澄清:
There are only two hard problems in computer science: cache invalidation, naming things, and off-by-one errors. — Phil Karlton 当你维护代码时会发现,选择适当而有意义的信息为你的模块或类命名是有很大帮助的。 尤其是当其他人需要阅读或基于你编写的配置清单工作时,这种命名方法是
对于来说,肯定有某种方法可以产生这个输出,不是吗?我发现有一些将映射到,所以似乎有一种方法可以让它产生类型,但我没有找到
为什么它更高效,因为像'your_name'这样的c.name扫描只在第一个查询中发生一次。
> 我使用的是Project Lombok,这是一个(虚假的)JSR269实现,提供了一些有用的特性,比如在编译时生成getter和setter,同时保持源代码的清洁: 有没有一种方法可以按照需要的方式管道两个注释处理器?