我有一个数据库表“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可以过滤收藏品?
提前致谢
答案 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(即列出除删除之外的所有级联)和孤儿删除,如果你不需要它们。