过滤JPA实体而不从数据库中删除它们

时间:2011-07-27 08:45:04

标签: java hibernate jpa lazy-initialization hibernate-entitymanager

我有一个数据库表“viewmodule”,其自身的FK(parent_id)允许递归结构。

CREATE TABLE viewmodule (
id,
type,
parent_id,
hide);

我的Java应用程序使用JPA / Hibernate映射该表上的实体。我们有固定的实体hirachy,它由@Discriminator注释解决,该注释使用表的“type”列。

public class ViewModule implements Serializable {
   private long id;
   private String type;
   private ViewModule parent;
   private Boolean hide;

   @OneToMany( targetEntity = ViewModule.class, cascade = javax.persistence.CascadeType.ALL, mappedBy = "parent" )
   @Cascade( { org.hibernate.annotations.CascadeType.ALL,
            org.hibernate.annotations.CascadeType.DELETE_ORPHAN } )
   private Set<ViewModules> children;
(...)
}

我的任务是加载此表中的所有元素(深层)但忽略了将“hide”字段设置为true的元素。 它是一个看似简单的过滤机制。我的第一种方法是使用Hibernate Filter注释,它在第一层上运行良好(所有viewmodules都使用parent_id = null)。但过滤器不适用于“子”关系。 (在我的现实生活模型中,我有不同类型的ViewModules的继承结构)

因此,我编写了一个小函数,以递归方式遍历viewModule对象树,并从具有hide = true的子关系中删除viewModule;

但是,由于所有对象仍在观察jpa / hibernate entityManager,因此每次从集合中删除都会在数据库中直接执行为delete。所以我的过滤器功能会从数据库中删除实体,这是一件坏事。

我尝试使用hibernate会话中的“evict”方法在过滤之前分离实体,但这会导致LazyInitialisationException。

所以,为了防止克隆我的所有对象我的问题是如何解决这个问题?有没有办法以初始化所有集合的方式分离对象?或者是否有一个特殊的Kung-Fu Chuck-Norris JPA Annotation可以过滤收藏品?

提前致谢

2 个答案:

答案 0 :(得分:1)

使用原生查询

em.createNativeQuery("select * from viewmodule where hide = false", ViewModule.class).getResultList();

这有效:Filter list contained in entity returned by jpa/hibernate query

答案 1 :(得分:0)

创建一个新集合并仅添加具有hide=false的元素。您将无法将该集合与对象一起分发,因此您必须从单独的方法调用中返回它。例如:dao.getVisibleItems(module)

另一件事 - 你可以删除Cascade.DELETE(即列出除删除之外的所有级联)和孤儿删除,如果你不需要它们。