【问题标题】:JPA 2 - Get last element of a list in a @OneToMany relationshipJPA 2 - 获取@OneToMany 关系中列表的最后一个元素
【发布时间】:2014-05-01 05:56:15
【问题描述】:

我有一个实体,其实体名为 Deadline,与名为 DeadlineDate 的实体具有@OneToMany 关系。

截止日期:

@Entity
@Table(name="deadline")
@Cache(alwaysRefresh=true)
public class Deadline implements Serializable { 
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    @Column(name = "id", nullable = false)
    private Long id;


    @OneToMany(mappedBy = "deadline", cascade = PERSIST)
    @OrderBy("id ASC")
    private List<DeadlineDate> datesList = new ArrayList<DeadlineDate>();

    //...
}

DeadlineDate 实体:

@Entity
@Table(name="deadlinedate")
public class DeadlineDate implements Serializable {     
    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id")
    private Long id;

    @Basic
    @Column(name = "date", nullable = false)
    @Temporal(DATE)
    private Date date;

    @ManyToOne
    @JoinColumn(nullable = false, name = "deadline_id")
    private Deadline deadline;
    //...
}

getAllDeadlines 方法:

private List<Deadline> getAllDeadlines(){
        CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
        CriteriaQuery<Deadline> query = criteriaBuilder.createQuery(Deadline.class);
        Root<Deadline> root = query.from(Deadline.class);

        Join<Deadline, DeadlineDate> joinDeadDate = root.join("datesList");

        List<Predicate> predicateList = new ArrayList<Predicate>();             

        Date date = new Date();

        //other unrelated predicates

        //i'm stuck here - begin
        predicateList.add( criteriaBuilder.lessThan(joinDeadDate.<predicateArray>get("date"), date));       
        //i'm stuck here - end

        Predicate[] predicateArray = new Predicate[predicateList.size()];
        predicateList.toArray(predicateArray);
        query.where(predicateArray);        

        TypedQuery<Deadline> typedQuery = em.createQuery(query);
        return typedQuery.getResultList();
    }

我想查询已超过当前系统日期的截止日期。截止日期具有存储用户所做更改的历史记录(到期日期可以向前或向后修改)。当前截止日期被认为是截止日期表中最大的 id。我正在尝试使用 Criteria api,但不知道如何使其仅返回 datesList 的最后一个值,以便在 criteriaBuilder 的 lessThan 方法中使用。使用当前代码,我获得了特定截止日期的所有截止日期记录。

提前致谢!

【问题讨论】:

    标签: java hibernate jpa criteria-api


    【解决方案1】:

    如果您只需要为每个 Deadline 使用具有最大 id 的 DeadlineDate,则需要一个子查询(未测试):

    Subquery<Long> sq = query.subquery(Long.class);
    Root<DeadlineDate> deadlineDate = query.from(DeadlineDate.class);
    Root<DeadlineDate> deadlineDateSQ = sq.from(DeadlineDate.class);
    Path<Deadline> deadline = deadlineDate.get("deadline");
    Path<Deadline> deadlineSQ = deadlineDateSQ.get("deadline");
    sq.select(criteriaBuilder.max(deadlineSQ.<Long>get("id")));
    sq.groupBy(deadlineSQ);
    ... //create the list of other predicates
    sq.where(predicateListSQ);
    query.select(deadline);
    Predicate predicate1 = criteriaBuilder.in(deadlineDate.get("id")).value(sq);
    Predicate predicate2 = criteriaBuilder.lessThan(deadlineDate.<Date>get("date"), date);
    query.where(criteriaBuilder.and(predicate1, predicate2));
    

    另请参阅:

    【讨论】:

    • 另一件事...使用此解决方案,我得到了与当前日期标准匹配的所有截止日期的列表(在结果中获得重复的截止日期),但是我如何才能限制为选择每个截止日期中具有最高 id 的截止日期(获得不同的截止日期)?这是因为我需要通过仅比较列表的最新 DeadlineDate(具有最大 id 的 DeadlineDate)来获取所有截止日期的列表。谢谢。
    • 好的,现在我知道你在找什么了。请注意,如果日期可以编辑,则通过 id 比较它们会导致错误,您确定吗?我会改为按日期比较它们。
    • 是的,我确定。因为用户必须能够将日期更改为更近或更远的日期。但我有阻止设置过去日期的验证。
    【解决方案2】:

    使用setMaxResults 限制返回的记录数。对输出进行排序,以便您想要的记录是第一个。

    typedQuery.setMaxResults(1);
    

    【讨论】:

    • 我尝试了您的解决方案,但仍然获得了所有记录。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-18
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    相关资源
    最近更新 更多