我刚刚开始使用JPA而且我有一个很愚蠢的问题,但如果是,那就意味着JPA有一些相当基本的东西!如果这是一个愚蠢的问题,请原谅我,但我无法在任何地方找到答案。
我想为我的表的主键自动生成UUID,并且我已经阅读了很多关于如何执行此操作的内容,并且在对象被持久化之前阅读有关ID无法使用的所有警告以及这将如何影响equals和hashCode方法,但我提出了一个我看不到问题的解决方案,但我怀疑是因为我无法在Web上的任何地方找到任何对该方法的引用!
方法很简单:
在我看来,可能是简单化的观点,这似乎可以解决所有问题,但我必须遗漏一些东西,否则肯定会有到处使用这种方法的例子!
答案 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();
}
截至目前,这种方法运行良好并通过了所有单元/集成测试。