Hibernate 休眠对象生命周期

Hibernate 休眠对象生命周期,hibernate,Hibernate,为什么在使用@Transactional注释返回的方法之后,我无法获取idsession.load(product.class,1)加载的实体对象product.getName()的值?当我以这种方式获取产品对象时,session.createQuery(“从产品作为产品,其中product.id=1)一切正常 编辑 道方法 public Product getProduct(Long id) { return (Product) currentSession().load(Product.cl

为什么在使用
@Transactional
注释返回的方法之后,我无法获取id
session.load(product.class,1)
加载的实体对象
product.getName()
的值?当我以这种方式获取产品对象时,
session.createQuery(“从产品作为产品,其中product.id=1)
一切正常

编辑

道方法

public Product getProduct(Long id) {
return (Product) currentSession().load(Product.class, id);
}
服务方式

    @Transactional
public Product getProduct(Long id) {
    return productDao.getProduct(id);
}
控制器方法-本应发送JSON,但它在
product.getName()
上中断,出现错误
org.hibernate.LazyInitializationException:无法初始化代理-无会话

    @RequestMapping(value = "/product",headers="Accept=application/json")
public @ResponseBody Product getProduct() {
    Product product = productService.getProduct(new Long(1));
    System.out.println(product.getName());
    return product;
}

当我们在
Java代码中创建实例时,该实例被认为是一个瞬态实例
,这意味着没有适当的机制来管理该实例的持久状态。 但是,一旦<代码>我们将一个临时实例传递给Hibernate会话的保存、更新或SaveOrror方法,我们认为瞬态实例已经转换为持久实例,因为Hibernate将开始管理该实例的持久状态。

与Hibernate会话关联的任何实例都被称为持久实例。

保存或更新JavaBean并不是获得持久实例的唯一方法。 通过get或load方法调用,甚至是HQL或criteria查询加载到Hibernate会话中的javabean被视为持久实例,因此,对这些实例状态的任何更改或更新也将由Hibernate会话持久化到数据库中

如果确实有一个实例要从Hibernate的控制下释放,则始终可以调用Hibernate会话的execute方法,传入要从Hibernate的控制下释放的实例的名称。当一个实例的状态不再由Hibernate会话管理时,我们称之为分离实例,因为它在数据库中有一个表示,Hibernate没有做任何事情来保持实例与底层持久性存储同步。实际上,实例与数据库中相应的表示分离

当然,当我们使用Hibernate时,我们与数据库的所有交互都必须发生在事务的范围内。默认情况下,当我们调用save或update等方法时,我们永远无法完全确定数据库中的相应记录何时被更新-我们所知道的是,一旦事务被提交,所有的c与Hibernate会话关联的任何持久实例的更改都将保存到数据库中。当然,由于某种原因,将所有数据保存到数据库的操作始终可能会失败,如果发生这种情况,Hibernate将引发运行时异常

在这一点上,除了回滚当前事务并关闭Hibernate会话之外,您真的没什么可做的了。在这一点上,以前受Hibernate会话控制的所有实例都成为分离对象,很可能不再与数据库同步。在这种情况下,您可以ys启动一个新事务,并尝试通过save或update调用将分离的实例与Hibernate会话重新关联,从而将它们转换回持久实例,但最终,您最好只向客户端应用程序发送一条友好的错误消息,从头开始任何请求-响应周期。
当我们谈论瞬态、持久性和分离对象时,简单描述我们的意思。

如果在会话范围之外访问未初始化的集合或代理,即当拥有集合或具有代理引用的实体被删除时,Hibernate将引发
LazyInitializationException
处于分离状态

有时,在关闭会话之前需要初始化代理或集合。您可以通过调用
product.getName()
或(例如)强制初始化。但是,这可能会使代码读者感到困惑,并且对一般代码不方便

静态方法
Hibernate.initialize()
Hibernate.isInitialized()
,为应用程序提供了一种方便的方式来处理延迟初始化的集合或代理。
Hibernate.initialize(产品)
将强制初始化代理,
产品
,只要其会话仍处于打开状态

您还可以将某些字段声明为


您还需要讲一点。通过
session.load(product.class,1)加载产品后,调用
product.getName()
时会发生什么情况
?您的
product
对象是否可能是product类的缓存实例?能否发布代码的相关部分?可能我没有指定要执行的操作。我想从数据库加载产品并将其属性发送到浏览器。正确的方法是什么?一种方法是将行
Hibernate.initi在返回
产品之前,将(产品)
初始化到DAO中。或者在产品实体中简单地写入
@org.hibernate.annotations.Proxy(lazy=false)
,这将完全禁用产品实体所有属性的延迟加载。
@Entity 
public class Product  {

   @Id 
   @GeneratedValue
   private long id;


   @Basic(fetch=EAGER)
   private String name;


}