Java LazyInitializationException,用于int
具有整数字段的简单类:Java LazyInitializationException,用于int,java,hibernate,h2,lazy-initialization,proxy-classes,Java,Hibernate,H2,Lazy Initialization,Proxy Classes,具有整数字段的简单类: @Entity @Cacheable @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE) @Table(name = "myObject") public class MyObject { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id
@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; }
}
使用简单的实用程序方法从数据库中提取对象:
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配置文件(即hibernate.cfg.xml
)包含以下属性:
<property name="hibernate.current_session_context_class">thread</property>
发生的情况是:
parent.getMyObject()
以获取MyObject
实例MyObject
实例实际上是一个没有任何字段的代理MyObject
实例上调用一个方法,我就会得到LazyInitializationException
getMyObject()
或调用getter时,我没有创建事务。我想这就是问题所在。我将测试这是否有区别
编辑2:
事实证明,我确实需要在事务中调用getter。但这本身还不够
第二个问题是在已提交的事务中获取父对象。因此,代理对象不再绑定到事件。我猜这就是他们所谓的“分离物体”。(哈哈,我只是边走边学。)
我必须通过调用会话#更新(代理)
方法来“重新连接”这个对象。现在我终于可以毫无例外地调用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()?在sql级别,refCount是一个索引?代码中的
标准是什么?尝试调用getRefCount
而不是初始化@ShadowRay hibernate为此字段创建了一个索引,这是正确的。这实际上是一个大数据数据库。大约有100万个MyObect对象。每个MyObject
都有多个Parent
对象。实际上,有多个引用计数器(例如,refCount
),用于计算它们拥有多少个具有特定属性的父级。整个想法是为MyObject
(即包含预先计算的数据)创建一个平面记录,这将使以后更容易计算复杂的统计数据。>>但我从这个问题中学到的是,我可能>>以错误的方式使用事务。我想我应该进行更长的>>事务,这些事务包含回迁和对getter的调用正确的?不,通常您可以调用分离对象的getter和setter(不过,对于非延迟加载的字段)。但在您的情况下,由于某种原因,所有文件都是延迟加载的,您无法这样做。请尝试使用此注释参数:@org.hibernate.annotations.Cache(include=“non-lazy”,use=cacheconcurrencysttrategy.READ\u-WRITE);不懒惰的人,没有帮助。你发完后我马上就试了。但与此同时,我做了一次重新测试,发现我不得不调用会话#update(myObject)
// 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();