为什么Hibernate Eager Fetch不起作用?

时间:2013-09-03 18:37:13

标签: hibernate fetch eager

我试图编写一个简单的测试程序来模拟项目中的两个对象并遇到麻烦。基本上我有两个简单的对象,父和子有一对多的关系。以下是两个对象:

import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.fhp.ems.common.data.dao.HibernateInitializer;


@Entity
@Table(name = "Parent")
public class Parent {

  private Integer id;
  private String data;
  private List<Child> child;

  public Parent() {}


  @Id
  @Column(name = "ID", nullable = false)
  public Integer getId() {
    return this.id;
  }

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


  @Column(name = "DATA", length = 128)
  public String getData() {
    return this.data;
  }


  public void setData(String data) {
    this.data = data;
  }


  @OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER, orphanRemoval = true)
  @JoinColumn(name = "PID")
  //@Fetch(value=FetchMode.SELECT)
  public List<Child> getChild() {
    return child;
  }


  public void setChild(List<Child> child) {
    this.child = child;
    if(child != null && child.size() > 0) {
      for(Child c : child) {
        this.data = c.getValue();
      }
    }
  }



  public static void main(String[] args) {
    Session session = null;
    Transaction tx = null;
    try {
      HibernateInitializer.initLocal();
      session = HibernateInitializer.getSession(null);
      int id = 101;
      tx = session.beginTransaction();
      Parent p = (Parent)session.get(Parent.class, 101);
      //Parent p = new Parent();
      //p.setId(id);
      //Child c = new Child();
      //c.setPid(id);
      //c.setId(1);
      //c.setValue("child");
      //Child c1 = new Child();
      //c1.setPid(id);
      //c1.setId(2);
      //c1.setValue("child1");
      //List<Child> childs = new ArrayList<Child>();
      //childs.add(c);
      //childs.add(c1);
      //p.setChild(childs);
      //session.saveOrUpdate(p);

      tx.commit();
    }
    catch(Exception exc) {
      exc.printStackTrace();
    }
    finally {
      HibernateInitializer.closeSession(session, null);
    }

  }

}


import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;


//CREATE TABLE `Child` (
//  `ID` int(11) NOT NULL,
//  `PID` int(11) NOT NULL,     
//  `VALUE` varchar(128) default NULL,
//  PRIMARY KEY  (`ID`)
//)


@Entity
@Table(name = "Child")
public class Child {

  private Integer id;
  private Integer pid;
  private String value;

  public Child() {}

  @Id
  @Column(name = "ID", unique = true, nullable = false)
  public Integer getId() {
    return this.id;
  }


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


  @Column(name = "PID", nullable = false)
  public Integer getPid() {
    return this.pid;
  }


  public void setPid(Integer pid) {
    this.pid = pid;
  }


  @Column(name = "VALUE", length = 128)
  public String getValue() {
    return this.value;
  }


  public void setValue(String value) {
    this.value = value;
  }


}

当我运行程序时,出现以下错误:

Hibernate: 
    select
        parent0_.ID as ID81_1_,
        parent0_.DATA as DATA81_1_,
        child1_.PID as PID81_3_,
        child1_.ID as ID3_,
        child1_.ID as ID82_0_,
        child1_.PID as PID82_0_,
        child1_.VALUE as VALUE82_0_ 
    from
        Parent parent0_ 
    left outer join
        Child child1_ 
            on parent0_.ID=child1_.PID 
    where
        parent0_.ID=? 

org.hibernate.PropertyAccessException: Exception occurred inside setter 
  of com.fhp.ems.common.data.dao.test.Parent.child
  at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:89)
  at org.hibernate.tuple.entity.AbstractEntityTuplizer.setPropertyValues(AbstractEntityTuplizer.java:583)
  at org.hibernate.tuple.entity.PojoEntityTuplizer.setPropertyValues(PojoEntityTuplizer.java:229)
  at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:3822)
  at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:152)
  at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:982)
  at org.hibernate.loader.Loader.doQuery(Loader.java:857)
  at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
  at org.hibernate.loader.Loader.loadEntity(Loader.java:2037)
  at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:86)
  at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:76)
  at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3268)
  at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:496)
  at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:477)
  at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:227)
  at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:285)
  at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:152)
  at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:1090)
  at org.hibernate.impl.SessionImpl.get(SessionImpl.java:1005)
  at org.hibernate.impl.SessionImpl.get(SessionImpl.java:998)
  at com.fhp.ems.common.data.dao.test.Parent.main(Parent.java:98)
Caused by: java.lang.reflect.InvocationTargetException
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  at java.lang.reflect.Method.invoke(Method.java:597)
  at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:66)
  ... 20 more
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection, no session or session was closed
  at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
  at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
  at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:122)
  at org.hibernate.collection.PersistentBag.size(PersistentBag.java:248)
  at com.fhp.ems.common.data.dao.test.Parent.setChild(Parent.java:71)

如果我将earger fetch更改为lazy fetch,它可以正常工作。如果我使用@Fetch(value = FetchMode.SELECT),它也可以正常工作。我的问题是:为什么急切的提取不起作用?

1 个答案:

答案 0 :(得分:0)

如果您在子表中没有@OneToMany,怎么能有ParentId? 您缺少一个与单亲相关的多个孩子的钥匙;将ParentId添加到表Child并在@JoinColumn(name = "ParentId")

中使用该列

编辑:

  • 使用Parent.child
  • 初始化private List<Child> child = new ArrayList<Child>();
  • 使用private Integer pid;更改private Parent pid;(并添加到@OneToMane mappedBy =“parent”)
  • 尝试注释字段而不是设置器
  • 让您的Parent.setChild()只是一项作业

那是 - 通常 - 是亲子关系的最佳实践