LazyInitializationException,对于一个 int
LazyInitializationException, for an int
带有整数字段的简单 class:
@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Table(name = "myObject")
public class MyObject
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(columnDefinition = "int default 0")
@Index(name = "refCount")
private int refCount;
public int getRefCount(){ return refCount; }
}
使用简单的 Utility 方法从数据库中获取对象:
Session session = SessionFactoryUtil.getCurrentSession();
Transaction tx = session.beginTransaction();
criteria.setFetchSize(1);
T object = (T) criteria.uniqueResult();
// I tried to add this line, but it made no difference
Hibernate.initialize(object);
tx.commit();
return object;
问题如下:
获取此对象后不久,我将调用 getRefCount
方法。那时我遇到以下异常:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:164)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:285)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
at mypackage.MyObject_$$_javassist_1.getRefCount(MyObject_$$_javassist_1.java)
我的休眠配置文件(即 hibernate.cfg.xml
)包含以下 属性:
<property name="hibernate.current_session_context_class">thread</property>
不明白的地方:
如果这发生在一个集合上,那么我只会添加 fetch = FetchType.LAZY
注释。但是这个简单的 int
字段不是连接。为什么 int
首先会被包裹在 Proxy
中?
我尝试添加 Hibernate.initialize(object);
行,但没有任何区别。
我还尝试了 hibernate.current_session_context_class="managed"
设置。之后我不得不手动启动和停止所有会话。我在每次获取时打开它并在 finally 块中关闭它。但这也没有什么区别。
这是我的第一个 Hibernate 项目之一。我开始怀疑我是否应该在对休眠对象调用 getters 之前打开一个事务。
我没有使用 Spring,只是休眠。
编辑:实际上有第二个对象
其实还有一个父对象(我一开始觉得不重要)。此 Parent
对象包含一个 link 到 MyObject
@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Table(name = "parentObject")
public class ParentObject
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
// link
@ManyToOne(optional = false, fetch = FetchType.LAZY)
@ElementCollection(targetClass = MyObject.class)
@JoinColumn(name = "myObjectId")
private MyObject myObject;
public MyObject getMyObject(){ return myObject; }
}
发生的事情是:
- 一个
Parent
对象被获取
parent.getMyObject()
被调用以获得一个 MyObject
实例
- 这个
MyObject
实例实际上是一个没有任何字段的代理。
- 只要我在这个
MyObject
实例上调用一个方法,我就会得到 LazyInitializationException
当我获取我的对象时,我确保存在一个会话并创建一个事务。但是在获取之后我立即关闭了交易。
我在调用 getMyObject()
或调用 getter 时没有创建事务。我想这就是问题所在。我会测试这是否有所作为。
编辑 2:
事实证明,我确实需要在事务中调用getters。但这本身还不够。
第二个问题是 Parent
对象是在已经提交的事务中获取的。结果,代理对象不再绑定到事件。我想这就是他们所说的“分离对象”。 (哈哈,我边走边学。)
我不得不通过调用 Session#update(proxy)
方法“重新附加”这个对象。现在我终于可以毫无例外地调用 getter。
// uses a transaction internally
Parent parent = MyHibernateUtil.fetch(Parent.class, ...);
MyObject object = parent.getMyObject();
...
// create a new transaction
Session session = SessionFactoryUtil.getCurrentSession();
Transaction tx = session.beginTransaction();
// reattach the object
SessionFactory.getCurrentSession().update(myObject);
int count = myObject.getRefCount();
tx.commit();
但是我从这个问题中学到的是我可能以错误的方式使用事务。我想我应该进行更长的事务,其中包含提取和对 getter 的调用。对吗?
尝试在关闭交易之前调用 getId 函数。不知道会发生什么,只是一个建议。
我想整个对象(在你的例子中是 MyObject)被代理了。您可以调用 getId 而不是 getRefCount() 吗?
带有整数字段的简单 class:
@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Table(name = "myObject")
public class MyObject
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(columnDefinition = "int default 0")
@Index(name = "refCount")
private int refCount;
public int getRefCount(){ return refCount; }
}
使用简单的 Utility 方法从数据库中获取对象:
Session session = SessionFactoryUtil.getCurrentSession();
Transaction tx = session.beginTransaction();
criteria.setFetchSize(1);
T object = (T) criteria.uniqueResult();
// I tried to add this line, but it made no difference
Hibernate.initialize(object);
tx.commit();
return object;
问题如下:
获取此对象后不久,我将调用 getRefCount
方法。那时我遇到以下异常:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:164)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:285)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
at mypackage.MyObject_$$_javassist_1.getRefCount(MyObject_$$_javassist_1.java)
我的休眠配置文件(即 hibernate.cfg.xml
)包含以下 属性:
<property name="hibernate.current_session_context_class">thread</property>
不明白的地方:
如果这发生在一个集合上,那么我只会添加 fetch = FetchType.LAZY
注释。但是这个简单的 int
字段不是连接。为什么 int
首先会被包裹在 Proxy
中?
我尝试添加 Hibernate.initialize(object);
行,但没有任何区别。
我还尝试了 hibernate.current_session_context_class="managed"
设置。之后我不得不手动启动和停止所有会话。我在每次获取时打开它并在 finally 块中关闭它。但这也没有什么区别。
这是我的第一个 Hibernate 项目之一。我开始怀疑我是否应该在对休眠对象调用 getters 之前打开一个事务。
我没有使用 Spring,只是休眠。
编辑:实际上有第二个对象
其实还有一个父对象(我一开始觉得不重要)。此 Parent
对象包含一个 link 到 MyObject
@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Table(name = "parentObject")
public class ParentObject
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
// link
@ManyToOne(optional = false, fetch = FetchType.LAZY)
@ElementCollection(targetClass = MyObject.class)
@JoinColumn(name = "myObjectId")
private MyObject myObject;
public MyObject getMyObject(){ return myObject; }
}
发生的事情是:
- 一个
Parent
对象被获取 parent.getMyObject()
被调用以获得一个MyObject
实例- 这个
MyObject
实例实际上是一个没有任何字段的代理。 - 只要我在这个
MyObject
实例上调用一个方法,我就会得到LazyInitializationException
当我获取我的对象时,我确保存在一个会话并创建一个事务。但是在获取之后我立即关闭了交易。
我在调用 getMyObject()
或调用 getter 时没有创建事务。我想这就是问题所在。我会测试这是否有所作为。
编辑 2:
事实证明,我确实需要在事务中调用getters。但这本身还不够。
第二个问题是 Parent
对象是在已经提交的事务中获取的。结果,代理对象不再绑定到事件。我想这就是他们所说的“分离对象”。 (哈哈,我边走边学。)
我不得不通过调用 Session#update(proxy)
方法“重新附加”这个对象。现在我终于可以毫无例外地调用 getter。
// uses a transaction internally
Parent parent = MyHibernateUtil.fetch(Parent.class, ...);
MyObject object = parent.getMyObject();
...
// create a new transaction
Session session = SessionFactoryUtil.getCurrentSession();
Transaction tx = session.beginTransaction();
// reattach the object
SessionFactory.getCurrentSession().update(myObject);
int count = myObject.getRefCount();
tx.commit();
但是我从这个问题中学到的是我可能以错误的方式使用事务。我想我应该进行更长的事务,其中包含提取和对 getter 的调用。对吗?
尝试在关闭交易之前调用 getId 函数。不知道会发生什么,只是一个建议。
我想整个对象(在你的例子中是 MyObject)被代理了。您可以调用 getId 而不是 getRefCount() 吗?