java – JOIN … WITH子句中不存在限制的替代解决方案

我需要对以下场景进行建模:实体具有值,可以随时间变化,我需要保留所有历史值.例如,我有实体文章,有标题.如果文章是在2015年1月1日创建的,它将获得标题“标题1”,然后,在2015年2月1日,某人将标题更改为“标题2”,并且在3月1日,标题更改为“标题3”.我想问一下“2015年2月20日这篇文章的标题是什么?”

为此,我创建了具有标题列表的Article实体:

@Entity
public class Article {
    @Id
    private Long id;
    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
    private List<ArticleTitle> title = new LinkedList<>();

    //Setters and getters are here
}

标题看起来像这样:

@Entity
public class Title extends DateDependentEntity<Title> {
    @NotNull
    private String title;
}

和DateDependentEntity看起来像这样(我有很多)

@MappedSuperclass
public abstract class DateDependentEntity<PARENT> {
    @Id
    private Long id;
    @Column(nullable = false)
    private LocalDate validFrom;
    @ManyToOne
    private PARENT parent;
}

一切正常,我已经创建了保存和阅读这些实体的方法(比如“给我一篇文章,其中id = 1,其值有效于20.2.2015”).

但我有问题找出依赖于日期的HQL过滤器查询,例如“给我所有在’20.2.2015”上标题包含’dog’的文章.”

首先,我会使用这样的东西:

SELECT DISTINCT a FROM Article a JOIN a.title at WITH (at.validFrom <= :date)  WHERE at.title LIKE :title

但这并不总是能够带来预期的结果 – 如果标题是1月份的“我们爱狗”和“我们喜欢猫”自2月以来我过滤了3月份的狗的价值,它仍会找到这篇文章.据我所知,我不能在WITH子句中使用某种限制,我是对的吗?

所以我虽然我会使用子查询,但那些不支持HQL中的LIMIT,所以问题与上面的JOIN相同.

是否有一些HQL查询来解决我的问题,或者我的模型是否完全错误?

最佳答案 整整一天摆弄HQL(并且在意识到IntelliJ将我的查询标记为具有不正确的语法,尽管查询有效),我想出了这个:

SELECT at.parent FROM ArticleTitle at 
WHERE at.title LIKE :title AND (at.validFrom, at.parent) IN (
    SELECT max(at2.validFrom), at2.parent FROM ArticleTitle at2 
    WHERE at2.validFrom <= :date GROUP BY at2.parent
);

现在这样做,虽然只有一种字段的查询大小让我感到害怕,但我认为给定的模型不会变得简单得多.时间将证明这是否可以在实践中使用.

点赞