国家名单
现在乐趣开始了。我们将研究实体对象的状态。你必须为所有东西付费,使用 Hibernate 也是如此。你不觉得学习HQL是要付出这样的代价吗?不,生活有点复杂。
如果你有某种可以使用 Hibernate 保存到数据库中的 Entity 对象,那么从 Hibernate 的角度来看,这个对象可以有四种状态:
- 短暂的
- 持久(或托管)
- 分离的
- 删除
为了让您感兴趣,我将在本次讲座中添加这张照片:
短暂的
事实上,一切都比看起来简单得多,尽管并非没有细微差别。例如,您使用 Java 代码显式创建且未使用 Hibernate 从数据库加载的每个实体对象都具有 Transient(透明)状态。
EmployeeEntity employee = new EmployeeEntity();
Transient 状态表示 Hibernate 对这个对象一无所知,对该对象的任何操作都不会影响 Hibernate,Hibernate 对这个对象的工作也不受影响。
此类对象也称为POJO - Plain Old Java Object。该术语通常用于与具有棘手行为的各种对象形成对比。还记得 Mockito 创建的 Moc 对象吗?在这里他们不是 POJO。
如果某些客户端代码与具有 Transient 状态的对象一起工作,那么它们的交互可以用一个超级简单的方案来描述:
持久或托管
下一个最常见的情况是与 Hibernate 引擎相关的对象。它们的状态称为持久性(或托管)。有两种方法可以获取具有此状态的对象:
- 从 Hibernate 加载对象。
- 在 Hibernate 中保存对象。
例子:
Employee employee = session.load(Employee.class, 1);
Employee employee = new Employee ();
session.save(employee);
这样的对象通常对应数据库中的某种记录,它有一个ID之类的。该对象附加到 Hibernate 会话,通常不能由真实对象表示,而是由某种代理表示。
很可能在调用session.load()方法之后,你会得到一些存根对象(代理),所有对数据库的调用都会在调用这个对象的方法之后执行。但是我们稍后会讨论这些细节。
而客户端代码与Managed状态对象的交互可以用下图来描述:
分离的
下一个状态是对象从会话中分离出来的时候。也就是说,一旦对象被附加到 Hibernate 会话中,但是随后会话被关闭或者事务结束,Hibernate 就不再监视这个对象。
例子:
session.close();
session.evict(entity);
在第一个示例中,会话已关闭。在第二种情况下,我们明确指出我们希望使用evict()方法将对象从会话中分离出来。
新的代码对象交互方案将如下所示:
这就是它变得有趣的地方。如果你的对象是从 Hibernate 获得的,那么你很可能得到了一个代理而不是一个真实的对象。而这个代理对象,在与会话断开连接后,调用它的方法时会抛出异常。
这是所有初学者在使用 Hibernate 时最常见的问题。当您使用 Entity 对象时,您需要在任何给定时间准确地知道此类问题的答案:
- 你有一个真实的对象还是只是一个真实对象的代理?
- 您目前是否在交易中?
- 是读写事务还是只读事务?
- 对象是否被LazyLoading机制管理?
- 对象的哪些部分已经加载到内存中,访问时将加载哪些部分?
- 您的对象如何连接到依赖对象?
好消息是大多数时候它是显而易见的。但是您仍然需要了解它在幕后是如何工作的。声明式编程就是这样 - 您可以在 10 分钟内编写代码,理解为什么它不能正常工作 - 在 10 小时内:)
删除
Entity 对象的最后一个状态是 Removed。正如您可能已经从其名称中猜到的那样,这是远程对象的状态。
出现这种状态是因为如果您从数据库中删除某个对象,那么 Java 对象不会立即消失在任何地方。
Employee employee = session.load(Employee.class, 1);
//after loading the object's state is Persisted
session.remove(employee);
//after deletion, the state of the object is Removed
session.save(employee);
//and now Persisted again
session.close();
//and now the Detached state
GO TO FULL VERSION