hibernate - 使用现有 @TableGenerator 进行 Hibernate 4 到 5 迁移
问题描述
我们从 Hibernate 4 迁移到 5,一个主要问题是新的生成器,它为表行生成 ID。我们的旧生成器都是基于表的,比如
@TableGenerator(name = TABLE_NAME + "_generator", table = ...)
@GeneratedValue(strategy = GenerationType.TABLE)
private Long id;
Hibernate 5 中的新默认生成器不正确地尊重这一点,并看似“从头开始”生成新的 id,因此在插入新行时会出现“Already existing ID”异常。
我发现的所有干净解决方案都是基于 Hibernate 4 以前在 AUTO-Mode ( @GeneratedValue(strategy = GenerationType.AUTO)
) 中使用的想法,但我们始终使用GenerationType.TABLE
.
“肮脏”的解决方案:添加<property name="hibernate.id.new_generator_mappings" value="false"/>
到 Hibernates persistence.xml
。结果:我们现有的数据库可以毫无问题地使用,除了:来自 Hibernate 的持续警告
HHH90000015: Found use of deprecated [org.hibernate.id.MultipleHiLoPerTableGenerator] table-based id generator; use org.hibernate.id.enhanced.TableGenerator instead. See Hibernate Domain Model Mapping Guide for details.]]
我的问题是:我们如何才能保留原始数据库,停止使用已弃用的代码,并正确创建具有新 ID 的新行,而不与现有 ID 冲突?
特别是因为据说 Hibernates 5 池标识符生成器比表更好: https ://vladmihalcea.com/hibernate-hidden-gem-the-pooled-lo-optimizer/
解决方案
假设您有以下映射:
@Entity
@Table(name = "TST_PATIENT_ENT")
public class Patient
{
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "table-generator")
@TableGenerator(
name = "table-generator",
table = "TST_TABLE_IDENTIFIER",
pkColumnName = "table_name",
valueColumnName = "product_id",
allocationSize = 3
)
@Column(name = "pat_id")
private Long id;
// ...
}
现在让我们看看基于旧样式表的 ID 生成 ( org.hibernate.id.MultipleHiLoPerTableGenerator
) 和新样式 ( org.hibernate.id.enhanced.TableGenerator
with pooled-lo
, pooled
) 之间的区别:
MultipleHiLoPerTableGenerator
(maxLo = allocationSize - 1)
Inserted IDs | Last seq val | Count of inserted rows
-----------------------------------------------------------
1 | 1 | 1
3, 4 | 2 | 2
6 .. 8 | 3 | 3
9 .. 12 | 5 | 4
15 .. 19 | 7 | 5
org.hibernate.id.enhanced.TableGenerator
(汇集-lo)
Inserted IDs | Last seq val | Count of inserted rows
-----------------------------------------------------------
1 | 3 | 1
4, 5 | 6 | 2
7 .. 9 | 9 | 3
10 .. 13 | 15 | 4
16 .. 20 | 21 | 5
org.hibernate.id.enhanced.TableGenerator
(汇集)
Inserted IDs | Last seq val | Count of inserted rows
-----------------------------------------------------------
1 | 6 | 1
5, 6 | 9 | 2
8.. 10 | 12 | 3
11 .. 14 | 18 | 4
17 .. 21 | 24 | 5
价值在哪里Last seq val
:
select product_id from TST_TABLE_IDENTIFIER where table_name = 'TST_PATIENT_ENT';
在每行插入之后。
因此,如果您决定使用以下配置:
<property name="hibernate.id.new_generator_mappings">true</property>
<property name="hibernate.id.optimizer.pooled.preferred">pooled-lo</property>
您应该查看 中提到的所有表,并将字段的@TableGenerator.table
值手动更新为. 例如,就我而言,我应该运行以下 sql:@TableGenerator.valueColumnName
max(id) + 1
update TST_TABLE_IDENTIFIER
set product_id = (select max(pat_id) + 1 from TST_PATIENT_ENT)
where table_name = 'TST_PATIENT_ENT';
PS 也许这篇Steve Ebersole 的文章也会很有用。
推荐阅读
- android - LocationListener 在服务类中无法在 android 设备上重新启动
- database - 在我们重新保存产品之前,Magento2 自定义产品属性值不会显示在前端
- swift - 如何使用 RxSwift 订阅数组更改?
- git - 如何签出到另一个分支并强制覆盖更改
- php - 使用 JQuery blueimp 上传多个文件
- python - 从 Dataframe 时间序列中提取每月日期
- ios - UITableViewWrapperView 在 tvOS 上具有超级视图的前导和尾随边距
- angular - Angular 6 的 Karma-Jasmine 上的“TypeError:无法读取属性‘routeConfig’ of null”
- c# - 将json字符串反序列化为变体的变体数组时如何控制变体类型
- codeblocks - 尝试调试 [C++] [Code::Blocks] 时出现“未知选项‘全名’”