0

我有一个后端应用程序,该应用程序没有任何用户界面。这些操作由服务器在 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 的客户模型 服务器 2 在时间 T1 选择了版本#400 的客户模型

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

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

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

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

该应用程序具有以下结构

Listening Port Handler -> Service Wrapped in Transaction -> DAO -> 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. 保存对象(而不是抛出异常)
4

1 回答 1

0

一种选择是使用HibernatedynamicInsert/dynamicUpdate的功能。不过,您将不得不摆脱版本控制。这是Hibernate 文档的摘录:

动态更新(可选 - 默认为 false):指定 UPDATE SQL 应在运行时生成,并且只能包含值已更改的那些列。

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

于 2012-11-26T22:46:03.240 回答