JPA UUID Generation

时间:2013-11-05 09:55:01

标签: java-ee jpa

我刚刚开始使用JPA而且我有一个很愚蠢的问题,但如果是,那就意味着JPA有一些相当基本的东西!如果这是一个愚蠢的问题,请原谅我,但我无法在任何地方找到答案。

我想为我的表的主键自动生成UUID,并且我已经阅读了很多关于如何执行此操作的内容,并且在对象被持久化之前阅读有关ID无法使用的所有警告以及这将如何影响equals和hashCode方法,但我提出了一个我看不到问题的解决方案,但我怀疑是因为我无法在Web上的任何地方找到任何对该方法的引用!

方法很简单:

  1. 实现一个@PrePersist方法,如果它为null,则设置ID字段。
  2. 在返回值之前,为调用@PrePersist方法的ID实现一个getter。
  3. 实现hashCode和equals,以便他们使用getter获取ID,而不是直接访问该字段。
  4. 在我看来,可能是简单化的观点,这似乎可以解决所有问题,但我必须遗漏一些东西,否则肯定会有到处使用这种方法的例子!

3 个答案:

答案 0 :(得分:0)

此解决方案存在一些问题:

  • 如果你的getter会调用@PrePersist回调,则ID会在意外时间设置,没有人注意到。更改吸气剂中的物体是您应该避免的副作用的一个很好的例子。

  • 如果您的应用程序负责在持久化之前分配ID,您将遇到激活@PrePersist回调的情况,但实体不会保留(例如,不利的TX回滚)。

  • 这些问题会使您无法可靠地区分持久对象和未持久对象。

答案 1 :(得分:0)

我认为您更容易使用单独的静态方法(在单独的类中),它将为您执行实体的id的初始化。

只需使用UUID.random()为您的POJO / Entity提供唯一的字符串,然后将其与PersistenceContext合并,以便ID反映在数据库中。

答案 2 :(得分:0)

一些事情:

1)Artem是正确的,首先要做的是让自己成为一个静态的UUID生成器。我个人使用JUG如下:

private static TimeBasedGenerator uuidGen = Generators.timeBasedGenerator(EthernetAddress.fromInterface());

public static String next() {
    String uuid = uuidGen.generate().toString();
    return uuid;
}

2)当你创建一个新对象并通过Web服务(例如REST / SOAP)对其进行序列化时,你的@PrePersist方法将会失败,因为你会在事务完成之前对它进行序列化(否则会让你感到害怕) Hibernate懒惰初始化错误)。因此,您经常需要在保存之前设置Id。我为此使用了getter副作用。

3)将副作用放在你的getter中就好了,因为你把JPA注释放在字段而不是属性访问器上。

4)你的哈希代码不能依赖于Id,因为有时候Hibernate会反序列化你的对象并在初始化之前将它添加到HashMap中。这是罕见的,但今晚发生在我身上的是我发现你的问题。所以我的哈希码现在是:

final public int hashCode() {
    return id == null ? getClass().hashCode() : id.hashCode();
}

截至目前,这种方法运行良好并通过了所有单元/集成测试。