使用Criteria API查询具有自引用的实体

时间:2015-09-06 06:05:29

标签: java hibernate

我有以下实体:

package model.entity;

import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;

@Entity
@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="id")
public class Folder {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column
    private String title;

    @JsonBackReference
    @ManyToOne(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)
    @JoinColumn(name = "parent")
    private Folder parent;

    @JsonManagedReference
    @OneToMany(mappedBy="parent")
    private Set<Folder> children;

    @JsonManagedReference
    @OneToMany(mappedBy="containerFolder")
    private Set<Project> projects;

    @Column
    private Integer orderIndex;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String name) {
        this.title = name;
    }

    public Folder getParent() {
        return parent;
    }

    public void setParent(Folder parent) {
        this.parent = parent;
    }

    public Set<Folder> getChildren() {
        return children;
    }

    public void setChildren(Set<Folder> children) {
        this.children = children;
    }

    public Set<Project> getProjects() {
        return projects;
    }

    public void setProjects(Set<Project> projects) {
        this.projects = projects;
    }

    public Integer getOrderIndex() {
        return orderIndex;
    }

    public void setOrderIndex(Integer orderIndex) {
        this.orderIndex = orderIndex;
    }



}

我使用Criteria API进行查询以查找父级的所有子级。

Session session = (Session) JPA.em().getDelegate();
List rootFolderList = session.createCriteria(Folder.class).add(Restrictions.isNull("parent")).list();

if (rootFolderList.isEmpty()) {
    Folder root = new Folder();
    root.setTitle("root");
    JPA.em().persist(root);
    rootFolder = root;
} else
    rootFolder = (Folder) rootFolderList.get(0);


Criteria criteria = session.createCriteria(Folder.class);
criteria.add(Restrictions.eq("parent", rootFolder.getId()));
List<Folder> folders = criteria.list();

获取根元素的第一个查询不是问题。它找到根元素并且不会给出错误。但是,第二个查询会在 list()方法上抛出异常。

[PropertyAccessException: could not get a field value by reflection getter of model.entity.Folder.id]

除了例外,有几种解决方案,但它们对我不起作用:

  • 将Hibernate版本降级到4.3.5或更低。没用。
  • 保留最新的Hibernate版本但设置为
    hibernate.classloading.use_current_tccl_as_parent false 。也没用。

1 个答案:

答案 0 :(得分:0)

  

获取根元素的第一个查询不是问题

我对此表示怀疑,因为查询试图找到所有没有ID的文件夹(并且显然都有一个:一个实体在没有ID的情况下不存在)。实际应该做的是找到没有父母的实体。这将为您提供根文件夹。

然后你做

criteria.add(Restrictions.eq("parent", rootFolder.getId()));

类型为Folder的父级如何等于类型为Long的rootFolder.getId()?

你想要的是

criteria.add(Restrictions.eq("parent", rootFolder));

criteria.add(Restrictions.eq("parent.id", rootFolder.getId()));