繁体   English   中英

@ManyToOne的JPA规范CriteriaBuilder

[英]JPA specification CriteriaBuilder for @ManyToOne

我正在尝试执行一些过滤,但是在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生成的元模型的Specification

 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是什么。 我还启用了hibernate.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()函数。 此函数将返回一个新的组合谓词,而不是更改当前谓词。
所以代替
cb.and(predicate, task.join(Task_.project).get(Project_.id).in(taskFilter.getProject().getId()));
你应该有
predicate = cb.and(predicate, task.join(Task_.project).get(Project_.id).in(taskFilter.getProject().getId()));

暂无
暂无

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

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