使用Hibernate过滤器与Spring Boot JPA

4

我发现需要通过子类中的属性来限制子集合的大小。

在按照这个指南后,我有以下结果:

@FilterDef(name="dateFilter", parameters=@ParamDef( name="fromDate", type="date" ) )
public class SystemNode implements Serializable {

    @Getter
    @Setter
    @Builder.Default
    // "startTime" is a property in HealthHistory
    @Filter(name = "dateFilter", condition = "startTime >= :fromDate")
    @OneToMany(mappedBy = "system", targetEntity = HealthHistory.class, fetch = FetchType.LAZY)
    private Set<HealthHistory> healthHistory = new HashSet<HealthHistory>();

    public void addHealthHistory(HealthHistory health) {
        this.healthHistory.add(health);
        health.setSystem(this);
    }
}

然而,当使用Spring Data JPA时,我并不真正理解如何切换此过滤器。我像这样获取我的父实体:

public SystemNode getSystem(UUID uuid) {
    return systemRepository.findByUuid(uuid)
        .orElseThrow(() -> new EntityNotFoundException("Could not find system with id " + uuid));
}

然后这个方法会调用被Spring支持的仓库接口:

public interface SystemRepository extends CrudRepository<SystemNode, UUID> {

    Optional<SystemNode> findByUuid(UUID uuid);

}

如何让这个过滤器与Spring良好协作?我希望能够在需要时以编程方式激活它,而不是全局激活。有些情况下,忽略过滤器是可行的。

我正在使用Spring Boot 1.3.5.RELEASE,目前无法更新。


1
我认为您可以启用它进行1次调用,然后立即再次禁用。这里可以找到一个示例:https://www.concretepage.com/hibernate/hibernate-filter-and-filterjointable-annotation-example - XtremeBaumer
@XtremeBaumer 我找到了那个源代码,但这迫使我完全绕过Spring存储库并使用HQL来定义自己的查询。如果可能的话,我想避免这种情况,但我不知道是否可以。 - jokarl
2
不是这样的。在调用存储库方法之前,先获取EntityManager。使用EntityManager.unwrap(Session.class)获取底层的Hibernate Session。调用enableFilter,调用存储库方法,调用disableFilter - M. Deinum
@M.Deinum 谢谢,我会尝试一下! - jokarl
1个回答

6

更新和解决方案

根据上面评论中建议的,我尝试了以下方法。

@Autowired
private EntityManager entityManager;

public SystemNode getSystemWithHistoryFrom(UUID uuid) {
    Session session = entityManager.unwrap(Session.class);

    Filter filter = session.enableFilter("dateFilter");
    filter.setParameter("fromDate", new DateTime().minusHours(4).toDate());

    SystemNode systemNode = systemRepository.findByUuid(uuid)
            .orElseThrow(() -> new EntityNotFoundException("Could not find system with id " + uuid));

    session.disableFilter("dateFilter");

    return systemNode;
}

我在FilterDef注释中使用了错误的类型:

@FilterDef(name="dateFilter", parameters=@ParamDef( name="fromDate", type="timestamp" ) )

我把 date 改成了 timestamp

这样返回的对象数量正确,已通过数据库验证。

谢谢!


1
当在父实体中有OneToMany,然后我想在第三个嵌套实体上添加条件,例如A.fieldB.fieldC.fieldD.id = x时,该怎么办...如何使用Filter在这种情况下实现? - Matley
我不明白为什么你需要在这里使用Hibernate过滤器。你可以使用任何想要的过滤方法。唯一有用的Hibernate过滤器是当你可以同时从几个端点启用它时(例如使用Aspect)。 - Adrien H
@AdrienH 这个回答已经超过四年了,自那时以来可能发生了很多事情。 - jokarl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接