带整数字段的简单类:
@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配置文件(即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项目之一。我开始怀疑在调用hibernate对象上的getter之前是否应该打开一个事务。
我没有使用Spring,只是使用Hibernate。
实际上有一个父对象(我最初认为它并不重要)。此Parent
对象包含指向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时,我没有创建事务。我猜这就是问题所在。我会测试是否有所作为。
事实证明我确实需要在事务中调用getter。但这本身还不够。
第二个问题是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的调用。对吗?
答案 0 :(得分:1)
在关闭事务之前尝试调用getId函数。不知道会发生什么,只是一个建议。
答案 1 :(得分:1)
我认为整个对象(在你的情况下是MyObject)是代理的。你可以调用getId而不是getRefCount()吗?