JPA 2.0、PostgreSQL 和 Hibernate 3.5 中的混合代理复合键插入

发布于 2024-08-31 03:52:36 字数 1863 浏览 9 评论 0原文

首先,我们使用 JPA 2.0 和 Hibernate 3.5 作为 PostgreSQL 数据库上的持久性提供程序。

我们通过 JPA 2.0 注释成功地使用数据库序列作为单字段代理键的自动生成值,并且一切正常。

现在我们正在实现一个需要混合密钥的双时态数据库方案,如下所示:

Table 1:
id             (pk, integer, auto-generated-sequence)
validTimeBegin (pk, dateTime)
validTimeEnd   (dateTime)
firstName      (varChar)

现在我们遇到了一个问题。您会看到,如果我们 INSERT 一个新元素,则字段 id 会自动生成,这很好。只是,如果我们想要UPDATE此方案中的字段,那么我们必须更改validTimeBegin列而不更改id字段并插入它作为一个新行,如下所示:

在行更新之前:

|---|-------------------------|-------------------------|-------------------|
| id|      validTimeBegin     |       validTimeEnd      |     firstName     |
|---|-------------------------|-------------------------|-------------------|
|  1| 2010-05-01-10:00:00.000 |                    NULL |            Gerald |
|---|-------------------------|-------------------------|-------------------|

在行更新之后恰好发生在 2010-05-01-10:35:01.788 服务器时间:

(we update the person with the id:1 to reflect his new first name...)
|---|-------------------------|-------------------------|-------------------|
| id|      validTimeBegin     |       validTimeEnd      |     firstName     |
|---|-------------------------|-------------------------|-------------------|
|  1| 2010-05-01-10:00:00.000 | 2010-05-01-10:35:01.788 |            Gerald |
|---|-------------------------|-------------------------|-------------------|
|  1| 2010-05-01-10:35:01.788 |                    NULL |             Jerry |
|---|-------------------------|-------------------------|-------------------|

所以我们的问题是,这不起作用完全对字段 id 使用自动生成的序列,因为在插入新行时,id 总是自动生成的,尽管它确实是复合键的一部分,有时表现会有所不同。

所以我的问题是: 有没有办法通过 JPA 告诉 hibernate 停止自动生成 id 字段,如果我想生成同一个人的新品种,并在其他情况下照常进行,或者做我必须用自定义代码接管整个 id 生成?

提前致谢, 杰拉德

First off, we are using JPA 2.0 and Hibernate 3.5 as persistence provider on a PostgreSQL database.

We successfully use the sequence of the database via the JPA 2.0 annotations as an auto-generated value for single-field-surrogate-keys and all works fine.

Now we are implementing a bi-temporal database-scheme that requires a mixed key in the following manner:

Table 1:
id             (pk, integer, auto-generated-sequence)
validTimeBegin (pk, dateTime)
validTimeEnd   (dateTime)
firstName      (varChar)

Now we have a problem. You see, if we INSERT a new element, the field id is auto-generated and that's fine. Only, if we want to UPDATE the field within this scheme, then we have to change the validTimeBegin column WITHOUT changing the id-field and insert it as a new row like so:

BEFORE THE UPDATE OF THE ROW:

|---|-------------------------|-------------------------|-------------------|
| id|      validTimeBegin     |       validTimeEnd      |     firstName     |
|---|-------------------------|-------------------------|-------------------|
|  1| 2010-05-01-10:00:00.000 |                    NULL |            Gerald |
|---|-------------------------|-------------------------|-------------------|

AFTER THE UPDATE OF THE ROW happening at exactly 2010-05-01-10:35:01.788 server-time:

(we update the person with the id:1 to reflect his new first name...)
|---|-------------------------|-------------------------|-------------------|
| id|      validTimeBegin     |       validTimeEnd      |     firstName     |
|---|-------------------------|-------------------------|-------------------|
|  1| 2010-05-01-10:00:00.000 | 2010-05-01-10:35:01.788 |            Gerald |
|---|-------------------------|-------------------------|-------------------|
|  1| 2010-05-01-10:35:01.788 |                    NULL |             Jerry |
|---|-------------------------|-------------------------|-------------------|

So our problem is, that this doesn't work at all using an auto-generated-sequence for the field id because when inserting a new row then the id ALWAYS is auto-generated although it really is part of a composite key which should sometimes behave differently.

So my question is:
Is there a way to tell hibernate via JPA to stop auto-generating the id-field in the case I want to generate a new variety of the same person and go on as usual in every other case or do I have to take over the whole id-generation with custom code?

Thanks in advance,
Gerald

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

错爱 2024-09-07 03:52:36

所以... 一段时间过去了,没有任何评论,现在我很确定没有办法做到这一点。事实上,这就是开发人员开始通过应用程序端自己的 id 生成器为数据库生成自己的唯一密钥的原因之一。
这样数据库就永远不会知道代理键这样的东西;它只是接收它。

顺便一提:
我们通过实现我们自己的方法来更新这些行的任务来解决我们的问题。这些方法现在依赖于 OR-Mapper,并且绝不符合 JPA 2.0,但 JPA 只是不支持此类行为的注释。

So... Some time has passed now without any comments and now I'm pretty sure that there's no way to do that. In fact it's one of the reasons why developers start generating their own unique keys for databases via their own id-generators on the application-side.
This way the database never even knows about such a thing as a surrogate key; It just receives it.

By the way:
We solved our problem by implementing our own methods for the task of updating such rows. These methods now are OR-Mapper dependent and in no way JPA 2.0 compliant but JPA just doesn't support an annotation for such behavior.

野侃 2024-09-07 03:52:36

AFAIK 你的 ID 字段不是 Hibernate 理解的意义上的 ID。如果我可以提出另一种解决方案,考虑到本质上您只想实现数据库修改日志记录:

  • 步骤0:仅在Hibernate中使用ID作为主键。在 Postgres 中使用复合主键。
  • 第 1 步:向 hibernate 添加过滤器,自动过滤设置了 validEndTime 的所有行。
  • 第 2 步:向 hibernate 添加自定义更新语句,这会执行插入操作。
  • 步骤3:在PostgreSQL中添加自动设置结束时间的触发器。
  • 步骤 4:在 postgres 上创建约束索引,以便 hibernate 更快地进行查找。

AFAIK your ID field is not an ID in the sense as Hibernate understands it. If I might propose another solution, given the fact that essentially you just want to realize database modification logging:

  • Step 0: Only use ID as a primary key in Hibernate. Use a compound primary key in Postgres.
  • Step 1: Add filters to hibernate that automatically filter all rows having validEndTime set.
  • Step 2: Add custom update statement to hibernate, that does an insert instead.
  • Step 3: Add trigger in PostgreSQL that sets the end time automatically.
  • Step 4: Create a constrained index on postgres for faster lookups by hibernate.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文