如何为惰性对象获取hibernate层次结构

时间:2014-11-24 10:21:31

标签: java hibernate lazy-loading

这是我的代码段:

public class Object1 implements Serializable {
    @Id
    @Column(length = 36)
    protected String id;

    @Column(length = 36, insertable = false, updatable = false)
    protected String parentID;

    @OneToMany(fetch = FetchType.LAZY)
    @JoinColumn(name = "object2ID", referencedColumnName = "parentID")
    protected List<Object2> parents = new ArrayList<>();

    public List<Object2> getParents() {
        return parents;
    }
}

public class Object2 implements Serializable {
    @Id
    @Column(length = 36)
    protected String id;

    @Column(length = 36, insertable = false, updatable = false)
    protected String object2ID;

    @Column(length = 36, insertable = false, updatable = false)
    protected String parentID;

    @OneToMany(fetch = FetchType.LAZY)
    @JoinColumn(name = "object2ID", referencedColumnName = "parentID")
    protected List<Object2> parents = new ArrayList<>();

    public List<Object2> getParents() {
        return parents;
    }
}

和应用程序类:

public class Application {
    public static Logger logger = LoggerFactory.getLogger(Application.class);

    public static void main(String[] args) {
        Path HIBERNATE_CONFIGURATION = Paths.get("");
        Configuration configuration = new Configuration().configure(HIBERNATE_CONFIGURATION.toFile());
        ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
                configuration.getProperties()).build();
        SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);

        Session session = sessionFactory.openSession();
        Object1 object1 = (Object1) session.get(Object1.class, "1");
        logger.info(object1.toString());

        Object2 object2 = object1.getParents().get(0);
        logger.info(object2.toString());

        while (!object2.getParents().isEmpty()) {
            object2 = object2.getParents().get(0);
            logger.info(object2.toString());
        }

        session.close();
    }

}

我按预期获得了Object1,但是object2抛出异常org.hibernate.LazyInitializationException: could not initialize proxy - no Session

会话未关闭,为什么我收到此错误?

我使用的是Hibernate核心:4.3.7.Final

解决:

您好。谢谢大家。我发现解决了我的问题。我尝试获取OneToMany,但在db引用中实际是类型ManyToMany。我为db和model创建了一些小改动。

我重命名对象。 这是新的代码段:

@Entity
@Table(name = "Houses")
public class House implements Serializable {
    @Id
    @Column(length = 36)
    protected String id;

    @Column(length = 36)
    protected String parentGUID;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parentguid", referencedColumnName = "guid")
    protected AddressObject address;

    public AddressObject getAddress() {
        return address;
    }

    @Override
    public String toString() {
        return "Object1{" +
                "id='" + id + '\'' +
                ", parentGUID='" + parentGUID + '\'' +
                '}';
    }
}

@Entity
@Table(name = "AddressObjects")
public class AddressObject implements Serializable {
    @Id
    @Column(length = 36)
    protected String id;

    @Column(length = 36, unique = true)
    protected String guid;

    @Column(length = 36, nullable = true)
    protected String parentGUID;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "address")
    protected List<House> houses = new ArrayList<>();

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "upHierarchicObject")
    protected List<AddressObject> downHierarchicObject = new ArrayList<>();

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parentguid", referencedColumnName = "guid")
    protected AddressObject upHierarchicObject;

    public List<House> getHouses() {
        return houses;
    }

    public List<AddressObject> getDownHierarchicObject() {
        return downHierarchicObject;
    }

    public AddressObject getUpHierarchicObject() {
        return upHierarchicObject;
    }

    @Override
    public String toString() {
        return "Object2{" +
                "id='" + id + '\'' +
                ", guid='" + guid + '\'' +
                ", parentGUID='" + parentGUID + '\'' +
                '}';
    }
}

和应用程序类:

public class Application {
    public static Logger logger = LoggerFactory.getLogger(Application.class);

    public static void main(String[] args) {
        ArrayList<Object> objects = new ArrayList<>();
        Path HIBERNATE_CONFIGURATION = Paths.get("config/hibernate.test.cfg.xml");
        Configuration configuration = new Configuration().configure(HIBERNATE_CONFIGURATION.toFile());
        ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
                configuration.getProperties()).build();
        SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);

        Session session = sessionFactory.openSession();
        House house = (House) session.get(House.class, "1");
        objects.add(house);

        AddressObject addressObject = house.getAddress();
        objects.add(addressObject);

        while (addressObject.getUpHierarchicObject() != null) {
            addressObject = addressObject.getUpHierarchicObject();
            objects.add(addressObject);
        }

        for (Object obj : objects) {
           logger.info("Object: {}", obj);
        }
        session.close();
    }
}

但是,除了LazyInitializationException,我不知道为什么。这是hibernate的一个错误吗?

2 个答案:

答案 0 :(得分:0)

懒惰就是你忘了在查询中进行提取(这里是为了父母),你试图在关闭会话后检索java对象 在代码的这一部分中,您如何知道来自object1的object2是通过Parents获取的? 这里我们只测试null

object1.getParents() != null

但是在惰性的情况下,对象不是null而是虚拟

如果要使用它,则需要打开会话 但在此步骤中会话已经关闭 因为我们在从数据库中重新获取对象后立即关闭会话

示例:

Session s = sessions.openSession();
Transaction tx = s.beginTransaction();

Employee e = (Employee) s.createQuery("from Employee e where e.name=:empName").setString("empName", eName).uniqueResult();
List roles = u.getRoles();
tx.commit();
s.close();
String role = roles.get(0); //  This line will throw error

 Easy Solution

 Use lazy=false in your Entity class.

注意

此处会话未关闭。这可以做到这一点

获取条件可以在Entity类的多对一条件中执行 fetch =&#34; join&#34; FetchMode.JOIN 的技巧 映射中定义的获取策略会影响:

retrieval via get() 

希望这有帮助。

答案 1 :(得分:-1)

您必须提供虚拟循环才能首先获取所有对象。

例如

 for (Object2 obj:object1.getParents()) {
          obj.getName();
 }