Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Hibernate/持久化有哪些常见问题?_Java_Hibernate_Testing_Persistence - Fatal编程技术网

Java Hibernate/持久化有哪些常见问题?

Java Hibernate/持久化有哪些常见问题?,java,hibernate,testing,persistence,Java,Hibernate,Testing,Persistence,我有一个应用程序,我想测试与Hibernate和/或持久性相关的可能问题 还有什么问题?我如何复制它们(字面上)?你是如何从中恢复过来的? 明确地说:我说的是多线程集群环境(最复杂的一个) 我的一个: org.hibernate.StaleObjectStateException:行被另一个事务更新或删除(或未保存的值映射不正确) 复制: 加载对象 使用HQL更新 尝试更新(保存)加载的对象 句柄:不确定…您观察到的问题是并发修改数据。Hibernate有足够的时间来处理这个问题 本质上,问

我有一个应用程序,我想测试与Hibernate和/或持久性相关的可能问题

还有什么问题?我如何复制它们(字面上)?你是如何从中恢复过来的?

明确地说:我说的是多线程集群环境(最复杂的一个)

我的一个:

org.hibernate.StaleObjectStateException:行被另一个事务更新或删除(或未保存的值映射不正确)

复制:

  • 加载对象
  • 使用HQL更新
  • 尝试更新(保存)加载的对象

句柄:不确定…

您观察到的问题是并发修改数据。Hibernate有足够的时间来处理这个问题

本质上,问题在于两个线程(或集群中的两台机器)同时作用于同一数据段。考虑这个例子:

machine 1: reads the data and returns it for editing somewhere else
machine 2: also reads the data for modification
machine 1: updates the data and commits.
machine 2: tries to do an update and commit.
当第二台机器尝试提交其更改时会发生什么?Hibernate将在计算机2处理数据时看到数据已更改。也就是说,机器2的更新在陈旧数据上。Hibernate不能总是合并这两个更改(也不是总是期望的行为),因此它通过抛出
org.Hibernate.StaleObjectStateException


正如我前面提到的,Hibernate为您提供了许多解决此问题的选项。也许最简单的方法是在数据对象上使用
@version
添加一个版本字段。Hibernate将自动维护数据的“版本”。无论何时更新,Hibernate都会自动更改版本。您的工作是检查在读取数据和更新数据之间版本是否没有更改。如果它们不匹配,您可以采取措施处理问题(即告诉用户)。有一些更复杂的技术可以防止并发更新,但这是最简单的。

延迟加载是您将遇到的一个大问题,特别是如果您遵循标准DAO模式。您最终将得到延迟加载的集合,但是当从DAO层出来时,spring(或者其他一些东西,如果您不使用spring)可能会关闭会话

public class MyDaoImpl implements MyDao {
   @Override
   @Transactional
   public void save(MyObject object) { ... }
}
在这种情况下,当“save”调用完成时,如果您不在另一个事务中,spring将关闭您的会话。因此,对延迟加载对象的任何调用都将抛出LazyInitializationException

处理此问题的典型方法是将会话绑定到当前线程。在webapps中,您可以使用OpenSessionInViewFilter轻松实现这一点。对于命令行,您可能需要编写一个实用程序方法来创建会话,绑定到当前线程,然后在完成后解除绑定。你可以在网上找到这样的例子


关于集合,如果您使用“更新”方法(这也是您通常使用标准DAO模式所做的),您必须小心不要替换集合实例,而是应该操作已经存在的集合。否则,hibernate将很难找出需要添加/删除/更新的内容。

获取太多数据可能是您使用ORM工具时可能遇到的最大问题,因为这样可以很容易地加载超过必要数量的数据。如果测试数据量非常小,并且一旦数据开始在生产中累积,数据访问层就会以指数级的速度变慢,那么这个问题在开发/测试场景中不会重现

可能会出现许多问题:

  • 缺少批更新
  • 缺少语句缓存
  • 锁得太多
  • 数据库往返次数过多
  • 生成低效SQL语句的奇异关联

我了解奥列斯基,但目前还没有具体的计划来解决这个问题。顺便说一下,我使用版本控制。将不得不研究它,因为你提供的链接没有提供一个明确的解决方案。谢谢你!你能说出一两个“防止并发更新的复杂技术”吗?我真的很感兴趣,当然。我在上面提出的链接讨论了三种技术:应用程序版本检查(您目前正在进行)、扩展会话和自动版本控制、分离对象和自动版本控制。除此之外,您还可以使用悲观锁定,这使您能够更明确地控制您的数据。谢谢:)