【问题标题】:Hibernate Versioning - Manage separate field updateHibernate 版本控制 - 管理单独的字段更新
【发布时间】:2012-11-14 09:59:06
【问题描述】:

我有一个后端应用程序,该应用程序没有任何用户界面。这些操作由服务器在 UDP 和 TCP 端口上侦听的传入数据触发。

我们有 Customer 表,该表有 15 个字段。每个字段代表一些关键细节或指向其他信息的指针。例如,

CUSTOMER_TABLE {
 ID,
 NAME,
 DEFAULT_ADDRESS_ID,
 EMAIL_ADDRESS,
 LAST_LOGIN,
 VERSION   <--- trying to introduce
}

除了 ID 之外,这些字段中的每一个都可以由不同的进程一次更新。当两个并发进程覆盖彼此的值时,我遇到了问题。所以,我介绍了 VERSION - hibernate 生成的版本字段。

现在假设服务器 1 在时间 T1 获取带有版本#400 的客户模型 Server2 在 T1 时获取版本#400 的 Customer 模型

Server1 更改 EMAIL_ADDRESS 并更新 CUSTOMER(在 T2),因此新版本号为 401(休眠生成)。

Server2 更改 NAME 并尝试在 T3 更新 CUSTOMER,由于版本号比 DB 中的版本号旧,因此事务将失败。

由于应用程序是非用户界面应用程序,我们不能真正要求用户授权更改...我们必须优雅地处理它,以便更改通过。

我有什么办法来处理这种情况?

该应用具有以下结构

Listening Port Handler -&gt; Service Wrapped in Transaction -&gt; DAO -&gt; DB

对于下一个 - 这是一个免责声明 - 我知道这是一个糟糕的设计......但不幸的是,该应用程序已经从一个非事务性应用程序以一种非常无计划的方式发展为事务性应用程序......我在决定“何时”修复整体设计时没有太多控制权。现在的结构....

Listening Port Handler -> Service invoked to get the model(ModelX) -> DAO -> DB (yes you are right, the model goes out of transaction boundary ... :-( )
                       -> Invoke different independent operations, each operation wrapped in txn -> DAO -> DB
                       -> Modify Model (ModelX)
                       -> Update model(ModelX) as a separate transaction -> DAO -> DB

我在第二个中会遇到问题,我无法刷新我的模型,因为如果我这样做了,我将丢失在模型上更改的所有内容,或者我将不得不再次重复所有步骤,这可能会导致其他成功的操作触发了两次(至少)

我的问题是 - 无论如何

  1. hibernate 可以理解被修改的属性
  2. 检查版本
  3. 如果现有版本过时,请获取新版本并在新版本上应用更改
  4. 保存对象(而不是抛出异常)

【问题讨论】:

  • i) 如果您不想要旧数据,请同步您的方法。 ii) 或者您可以在抛出异常时重试该操作。但是您必须自己编写此逻辑。
  • @TJ - 感谢您的回复 i)如果它是单一服务器环境,同步会有所帮助......但不幸的是,它是一个多服务器环境。 ii)要编写自定义逻辑,我将不得不放置一个事务异常处理程序并依赖于异常和抛出它的位置......呃......我的生命将结束,然后我才能想到完成这个功能更改。所以....您是说休眠无法理解问题(内省修改后的模型)并将更改应用于最新模型?

标签: java hibernate backend spring-transactions application-design


【解决方案1】:

其中一个选项是使用HibernatedynamicInsert/dynamicUpdate 功能。不过,您将不得不摆脱版本控制。这是Hibernate documentation的摘录:

dynamic-update(可选 - 默认为 false):指定 UPDATE SQL 应该在运行时生成,并且只能包含那些列 他们的价值观发生了变化。

可以在here找到此功能的示例。

【讨论】:

  • 听起来像是一个可能的解决方案。我将不得不试一试。根据您提供的链接中的文档optimisticLock(默认为VERSION):确定乐观锁定策略。如果启用动态更新,您将可以选择乐观锁定策略:版本:检查版本/时间戳列全部:检查所有列脏:检查更改的列,允许一些并发更新无:不使用乐观锁。那为什么要说“你必须摆脱版本控制”?
  • 抱歉,我不得不放弃那个解决方案。按照dynamicInsert / dynamicUpdate (defaults to false): specifies that INSERT / UPDATE SQL should be generated at runtime and contain only the columns whose values are not null. 的描述,** not null ** 部分让我望而却步。显然,在我的情况下这不是真的......我模型中的其他字段不会为空......并且不会改变。看起来hibernate改变了dynamicUpdate的实现(基于@ShyJ提供的摘录.....所以仍在寻找解决方案。
  • @javadevg 我认为该描述具有误导性(如果不是简单的谎言),鉴于以下描述,我将其包含在答案中,以及code that uses it
  • 你很可能是对的。我将实施更改并更新此帖子。
猜你喜欢
  • 1970-01-01
  • 2018-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-07
  • 1970-01-01
相关资源
最近更新 更多