我不知道最近openJPA人们使用的多不多,但是我第一次使用的时候感觉还可以。但是在多组合查询的时候感觉还是得写很多HQL语句。不懂在这方面有没有高手能够给我一个提示呢。
openJPA的另外一个不太理解的就是它的延迟加载的问题。我第一次用的时候不太懂,在标间关联的地方设置了
@ManyToOne(cascade = { CascadeType.REFRESH }, fetch = FetchType.LAZY ) @JoinColumn(name = "depart_id") private Depart depart;
其中这是我设置的admin 表与depart表之间的多对一的关联,我希望取出某个admin的信息的时候,也要知道他所在的部门,当我在页面要显示admin.depart.depart_name的时候出现了错误:
could not initialize proxy - the owning Session was closed
当时我不太理解,为什么说我的代理没有初始化,会话已经关闭。然而再去查找一些资料终于明白了他的一些机制。
首先引用一位网上一位朋友的关于lazy方面的见解。我觉得他说的挺全面的。
延迟初始化错误是运用Hibernate开发项目时最常见的错误。如果对一个类或者集合配置了延迟检索策略,那么必须当代理类实例或代理集合处于持久化状态(即处于Session范围内)时,才能初始化它。如果在游离状态时才初始化它,就会产生延迟初始化错误。下面把Customer.hbm.xml文件的<class>元素的lazy属性设为true,表示使用延迟检索策略: <class name="mypack.Customer" table="CUSTOMERS" lazy="true"> 当执行Session的load()方法时,Hibernate不会立即执行查询CUSTOMERS表的select语句,仅仅返回Customer类的代理类的实例,这个代理类具由以下特征:(1) 由Hibernate在运行时动态生成,它扩展了Customer类,因此它继承了Customer类的所有属性和方法,但它的实现对于应用程序是透明的。(2) 当Hibernate创建Customer代理类实例时,仅仅初始化了它的OID属性,其他属性都为null,因此这个代理类实例占用的内存很少。(3)当应用程序第一次访问Customer代理类实例时(例如调用customer.getXXX()或customer.setXXX()方法), Hibernate会初始化代理类实例,在初始化过程中执行select语句,真正从数据库中加载Customer对象的所有数据。但有个例外,那就是当应用程序访问Customer代理类实例的getId()方法时,Hibernate不会初始化代理类实例,因为在创建代理类实例时OID就存在了,不必到数据库中去查询。
也就是说当我执行hql: from Admin a 时,由于设置了could not initialize proxy - the owning Session was closed ,他在load()的时候并不是返回与admin关联的depart的一个实例,我们再取值getXXX()的时候没有得到值,它仅仅是初始化了一个setId,仅仅getId不会为空,其他的均取道的值是空值,是因为我们提供了延迟加载。当我们要getXX()其他属性时,由于它的session关闭了,所以才会抛出异常:could not initialize proxy - the owning Session was closed 解决的办法我是把它的延迟加载could not initialize proxy - the owning Session was closed给去掉了,原因是我每次取出admin表的内容的时候都要知道它在depart表的的位置。但是不懂这样做好不好。还是希望高手给我解释一下。
openJPA的另外一个不太理解的就是它的延迟加载的问题。我第一次用的时候不太懂,在标间关联的地方设置了
@ManyToOne(cascade = { CascadeType.REFRESH }, fetch = FetchType.LAZY ) @JoinColumn(name = "depart_id") private Depart depart;
其中这是我设置的admin 表与depart表之间的多对一的关联,我希望取出某个admin的信息的时候,也要知道他所在的部门,当我在页面要显示admin.depart.depart_name的时候出现了错误:
could not initialize proxy - the owning Session was closed
当时我不太理解,为什么说我的代理没有初始化,会话已经关闭。然而再去查找一些资料终于明白了他的一些机制。
首先引用一位网上一位朋友的关于lazy方面的见解。我觉得他说的挺全面的。
延迟初始化错误是运用Hibernate开发项目时最常见的错误。如果对一个类或者集合配置了延迟检索策略,那么必须当代理类实例或代理集合处于持久化状态(即处于Session范围内)时,才能初始化它。如果在游离状态时才初始化它,就会产生延迟初始化错误。下面把Customer.hbm.xml文件的<class>元素的lazy属性设为true,表示使用延迟检索策略: <class name="mypack.Customer" table="CUSTOMERS" lazy="true"> 当执行Session的load()方法时,Hibernate不会立即执行查询CUSTOMERS表的select语句,仅仅返回Customer类的代理类的实例,这个代理类具由以下特征:(1) 由Hibernate在运行时动态生成,它扩展了Customer类,因此它继承了Customer类的所有属性和方法,但它的实现对于应用程序是透明的。(2) 当Hibernate创建Customer代理类实例时,仅仅初始化了它的OID属性,其他属性都为null,因此这个代理类实例占用的内存很少。(3)当应用程序第一次访问Customer代理类实例时(例如调用customer.getXXX()或customer.setXXX()方法), Hibernate会初始化代理类实例,在初始化过程中执行select语句,真正从数据库中加载Customer对象的所有数据。但有个例外,那就是当应用程序访问Customer代理类实例的getId()方法时,Hibernate不会初始化代理类实例,因为在创建代理类实例时OID就存在了,不必到数据库中去查询。
也就是说当我执行hql: from Admin a 时,由于设置了could not initialize proxy - the owning Session was closed ,他在load()的时候并不是返回与admin关联的depart的一个实例,我们再取值getXXX()的时候没有得到值,它仅仅是初始化了一个setId,仅仅getId不会为空,其他的均取道的值是空值,是因为我们提供了延迟加载。当我们要getXX()其他属性时,由于它的session关闭了,所以才会抛出异常:could not initialize proxy - the owning Session was closed 解决的办法我是把它的延迟加载could not initialize proxy - the owning Session was closed给去掉了,原因是我每次取出admin表的内容的时候都要知道它在depart表的的位置。但是不懂这样做好不好。还是希望高手给我解释一下。