如何获得懒惰对象的hibernate层次结构 [英] How to get hibernate hierarchy for lazy objects

查看:100
本文介绍了如何获得懒惰对象的hibernate层次结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的代码片段:

  public class Object1 implements Serializable {
@Id
@列(长度= 36)
保护字符串ID;

@Column(length = 36,insertable = false,updatable = false)
保护字符串parentID;

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

public List< Object2> getParents(){
返回父母;


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

@Column(length = 36,insertable = false,updatable = false)
保护字符串object2ID;

@Column(length = 36,insertable = false,updatable = false)
保护字符串parentID;

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

public List< Object2> getParents(){
返回父母;


code $

$ b

和应用程序类:

  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);

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

Object2 object2 = object1.getParents()。get(0);
logger.info(object2.toString()); (!object2.getParents()。isEmpty()){
object2 = object2.getParents()。get(0);


logger.info(object2.toString());
}

session.close();
}

}

我正在按预期得到Object1,但是object2引发异常 org.hibernate.LazyInitializationException:无法初始化代理 - 没有会话



会话未关闭,所以为什么我得到这个错误?



我使用Hibernate核心:4.3.7.Final



解决:



嗨。谢谢大家。我发现解决我的问题。我试图得到OneToMany,但在数据库引用中的实数是ManyToMany类型。我为数据库和模型创建了一个小的改变。



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

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

@Column(长度= 36)
保护字符串parentGUID;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name =parentguid,referencedColumnName =guid)
受保护的AddressObject地址;

public AddressObject getAddress(){
return address;
}

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


$ b $实体
@Table(name =AddressObjects)
public class AddressObject实现Serializable {
@Id
@Column(长度= 36)
保护字符串ID;

@Column(length = 36,unique = true)
保护字符串guid;

@Column(length = 36,nullable = true)
保护字符串parentGUID;

@OneToMany(fetch = FetchType.LAZY,mappedBy =address)
保护列表< 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)
保护AddressObject upHierarchicObject;

公共列表< House> getHouses(){
返回房屋;
}

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

public AddressObject getUpHierarchicObject(){
return upHierarchicObject;
}

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


code $

$ b

和应用程序类:

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

public static void main(String [] args){
ArrayList< Object> objects = new ArrayList<>();
路径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);

会话会话= 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的bug吗?

解决方案

懒惰是当你忘记在查询中进行读取(这里是父母)并且在关闭会话之后尝试检索java对象
在这部分代码中,您如何知道object1中的object2与父类一起提取?
在这里,我们只是测试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();
列出角色= u.getRoles();
tx.commit();
s.close();
String role = roles.get(0); //这行会抛出错误

简单解决方案

在您的Entity类中使用lazy = false。

注意

<这里Session没有关闭。这可以做到这一点



Fetch条件可以在 fetch =join FetchMode.JOIN 中执行实体类中的多对一条件
映射中定义的提取策略影响:

 通过get )

希望这有助于您。


Here is my code snippet:

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;
    }
}

and Application class:

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();
    }

}

I am getting Object1 as expected, but object2 throws the exception org.hibernate.LazyInitializationException: could not initialize proxy - no Session

Session is not closed, so why I am getting this error?

I'm using Hibernate core: 4.3.7.Final

Solve:

Hi. Thanks all. I found solve for my problem. I tries get OneToMany, but on real in db reference is type ManyToMany. I create small change for db and model.

I rename object. Here is new code snippet:

@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 + '\'' +
                '}';
    }
}

and Application class:

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();
    }
}

But, i doesn't why i except LazyInitializationException. This is a bug on hibernate?

解决方案

A Lazy is when you forgot to do a fetch in the query (here for Parents) and you try to retrive the java object after closing the session In this part of the code, how do you know that the object2 comming from the object1 is fetched with the Parents? here we just test null

object1.getParents() != null

but in the case of the lazy, the object is not null but virtual

if you want to use it, you need to have the session opened but at this step the session is already closed because we close the session just after retriving the object from the database

Example :

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.

Note

Here Session is not closed. This could do the trick

Fetch condition can do the trick fetch="join" or FetchMode.JOIN in many-to-one condition in Entity class The fetch strategy defined in the mapping affects:

retrieval via get() 

Hope this helps.

这篇关于如何获得懒惰对象的hibernate层次结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆