【问题标题】:Set creation and update time with Hibernate in Xml mappings在 Xml 映射中使用 Hibernate 设置创建和更新时间
【发布时间】:2011-02-07 18:25:42
【问题描述】:

我正在使用带有 Xml 映射的 Hibernate。我有一个实体,它有两个字段 creationDateupdateDate,类型为 timestamp,当实体被持久化和更新时,必须用当前的 UTC 时间填充。 我知道 @PrePersist@PreUpdate 注释的存在,但我不知道如何在我的 Xml 映射中使用它们的等价物。

再次,我想知道 Hibernate 是否以某种方式原生支持更新和创建时间集。

谢谢

【问题讨论】:

    标签: hibernate orm hibernate-mapping hbm


    【解决方案1】:

    我知道 @PrePersist@PreUpdate 注释的存在,但我不知道如何在我的 Xml 映射中使用它们的等价物。

    Hibernate3 event architecture 提供了等效的功能,您可以为PreInsertEventPreUpdateEventSaveOrUpdateEvent 注册侦听器(完整列表请参见org.hibernate.event 包)来设置和更新创建/更新日期。

    另一种方法是使用interceptorSession-scoped 或SessionFactory-scoped,并在onSave(...) 中设置createDateupdateDate,更新@987654340 中的updateDate @。


    更新:我将在下面留下我最初的建议,但我认为正确的方法(应该是我最初的答案)是使用拦截器或事件架构。

    您可以使用 timestampgenerated 属性来获取 creationDate@ 987654344@分别由数据库在插入和插入更新时生成:

    <class name="MyEntity" table="MY_ENTITY">
      <id .../>
      <timestamp name="createDate" generated="insert" ... />
      <timestamp name="updateDate" generated="always" ... />
      ...
    </class>
    

    有关详细信息,请参阅generated properties 部分。

    选项 1

    timestamp 似乎不支持generatead,所以我的建议不起作用。尽管如此,仔细阅读文档后,我的理解是 timestamp 是版本控制的替代方案,我认为它不适合像 createDate 这样的字段strong> 和 updateDate (它可能适用于后者,但这不是 timestamp 的用途)。

    所以我实际上仍然会使用 generated properties butsimple properties 而不是 timestamp

    <class name="MyEntity" table="MY_ENTITY">
      <id .../>
      <property name="createDate" update="false" insert="false" generated="insert" ... />
      <property name="updateDate" update="false" insert="false" generated="always" ... />
      ...
    </class>
    

    在数据库级别,这需要对updateDate 列使用触发器。对于createDate 列,使用current_timestamp 之类的默认值可以很好地工作。但是可能不需要触发器...

    选项 2

    为避免触发 选项 1,一种变体是使用updateDate 进行版本控制(并将其映射为timestamp):

    <class name="MyEntity" table="MY_ENTITY">
      <id .../>
      <timestamp name="updateDate" ... />
      <property name="createDate" update="false" insert="false" generated="insert" ... />
      ...
    </class>
    

    createDate 的方法与选项 1 相同,在数据库级别使用默认值。

    选项 3

    查看此答案的顶部...

    【讨论】:

    • 很好。但是我应该为 createDate 和 updateDate 属性设置哪种类型...您的代码 sn-p 在 type 属性之前结束:)
    • @Marco type 属性是可选的。如果在 Java 级别使用java.util.Date,则无需指定。
    • 谢谢。无论如何,这个解决方案涉及到创建特定的数据库触发器对吗?
    • @Marco 对于 updateDate,确实如此(createDate 可以只使用“默认”值)。我会更新我的答案。
    • @Péter 谢谢。很高兴你发现它也很有用。
    【解决方案2】:

    Hibernate 中的时间戳显然总是在实体更改时自动更新,因此您不能使用 &lt;timestamp&gt; 映射作为创建日期。但是,您可以将其存储为简单的java.util.Date 属性,并使用new Date() 对其进行初始化。

    对于更新时间戳,试试这个:

    public class MyEntity {
      ...
      private Date updateDate;
      ...
    }
    
    <class name="MyEntity" table="MY_ENTITY">
      <id .../>
      <timestamp name="updateDate" access="field" column="UPDATE_DATE"/>
      ...
    </class>
    

    请注意,timestamp 在映射中必须紧跟在 id 之后。

    仅供参考,这里是reference of the timestamp attributes

    【讨论】:

    • 您可以使用generated 属性控制此行为。
    • @Pascal 上面链接的参考指出:“insert:给定的属性值是在插入时生成的,但不会在后续更新时重新生成。[...] 即使 version 和 @ 987654332@属性可以标记为generated,此选项不可用。"
    • 确实,你是对的。我走得太快了。现在我已经仔细阅读了文档,我什至想知道是否应该将timestamp 用于createDateupdateDate 等“常规”字段(我的理解是您应该使用timestamp 来表示@987654338 @ 这解释了为什么 generatedtimestamp 没有意义),这似乎是对 timestamp 的滥用。
    • @Pascal 是的,尽管它很常见(从我在网上找到的示例数量来看)。这是可以理解的,因为您的答案中列出的其他选项都比较复杂,需要触发器/拦截器/事件侦听器......
    • 老实说,我发现generated 上的文档很烂,不清楚且具有误导性。 (顺便说一句,我不是故意用我的评论来骚扰你,我犯了一个很大的错字,我想更正一下,因此删除/重新发布)。
    猜你喜欢
    • 2021-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-24
    • 2014-05-04
    • 2018-05-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多