【发布时间】:2012-08-13 16:38:54
【问题描述】:
我有一个实体,它有一个主键/id 字段,如下所示:
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
这很好用。我正在使用 EclipseLink 创建 DDL-Schema,并且该列已正确创建,如下所示:
`id` bigint(20) NOT NULL AUTO_INCREMENT
但是,我确实有几个实体想要自己指定 PK(这是一个将数据从旧数据库传输到我们正在构建的新数据库的小应用程序)。如果我为 POJO 指定 ID(使用 setId(Long id))并将其持久化,EclipseLink 不会保存它(即保存记录,但 id 由 eclipseLink 自动生成)。
有没有办法手动指定具有 @GeneratedValue 的列的值?
这里有一些关于这个问题的想法:
我试图通过完全不使用@GeneratedValue 来解决此问题,而只是手动将列定义为AUTO_INCREMENTed。然而,这迫使我手动提供一个 ID,总是,因为 EclipseLink 会验证主键(因此它可能不是 null、零或负数)。异常消息显示我应该指定 eclipselink.id_validation,但这似乎没有任何区别(我注释了 @PrimaryKey(validation = IdValidation.NONE),但仍然收到相同的消息)。
澄清一下:我正在使用 EclipseLink (2.4.0) 作为持久性提供程序,我无法摆脱它(项目的大部分依赖于 eclipselink 特定的查询提示、注释、和类)。
编辑(回应答案):
自定义排序:我尝试实现自己的排序。我尝试继承 DefaultSequence,但 EclipseLink 会告诉我Internal Exception: org.eclipse.persistence.platform.database.MySQLPlatform could not be found。但我检查过:该类在类路径上。
所以我继承了另一个类,NativeSequence:
public class MyNativeSequence extends NativeSequence {
public MyNativeSequence() {
super();
}
public MyNativeSequence(final String name) {
super(name);
}
@Override
public boolean shouldAlwaysOverrideExistingValue() {
return false;
}
@Override
public boolean shouldAlwaysOverrideExistingValue(final String seqName) {
return false;
}
}
但是,我得到的是以下内容:
javax.persistence.RollbackException: Exception [EclipseLink-7197] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Null or zero primary key encountered in unit of work clone [de.dfv.datenbank.domain.Mitarbeiter[ id=null ]], primary key [null]. Set descriptors IdValidation or the "eclipselink.id-validation" property.
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:102)
...
Caused by: Exception [EclipseLink-7197] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Null or zero primary key encountered in unit of work clone [de.dfv.datenbank.domain.Mitarbeiter[ id=null ]], primary key [null]. Set descriptors IdValidation or the "eclipselink.id-validation" property.
at org.eclipse.persistence.exceptions.ValidationException.nullPrimaryKeyInUnitOfWorkClone(ValidationException.java:1451)
...
(为清楚起见缩短了堆栈跟踪)。这与我之前收到的消息相同。我不应该继承 NativeSequence 吗?如果是这样,我不知道为 Sequence 或 StandardSequence 中的抽象方法实现什么。
还可能值得注意的是,简单地继承(不覆盖任何方法)该类可以按预期工作。但是,在 shouldAlwaysOverrideExistingValue(...) 中返回 false 根本不会生成单个值(我单步执行了该程序并且 getGeneratedValue() 没有被调用一次)。
此外,当我在事务中插入某种类型的 8 个实体时,它会在数据库中产生 11 条记录(到底是什么?!)。
编辑(2012-09-01):我仍然没有解决问题的方法,实现我自己的序列并没有解决它。我需要的是一种能够不显式设置 Id(因此它将自动生成)并且能够显式设置 Id(因此它将用于在数据库中创建记录)的方法。
我尝试将列定义为自己的 auto_increment 并省略 @GeneratedValue,但是验证将启动并且不允许我保存这样的实体。如果我指定一个值 != 0 和 != 零,mysql 会抱怨主键重复。
我想尝试的想法和选择已经不多了。任何? (开始赏金)
【问题讨论】:
-
您是否有理由不能通过 SQL 从旧 -> 新进行标准导入?一旦你完成了,你只需要调整序列,这样你就不会覆盖这些值。毕竟,它是一个 ORM,它正在读取数据库。
-
新旧有完全不同的模式,应用程序用于将数据从一个模型转换到另一个模型(例如一个字段用于旧的名字和姓氏,两个字段在新的等等)。当然,转储旧数据库、创建新数据脚本并导入它们是另一种选择;但是,该应用程序几乎已完成。此外,我真的很想知道如何实现这一点。
-
既然你的模式完全不同,为什么只是做一个“干净”的导入会出现问题。又名:建立新的实体和关系并保持它们?我要引导你的地方是,我认为你在吠叫一棵困难的树。但是,您可以删除序列,手动保留所有内容,然后启动序列。
-
@GeneratedValue(strategy = GenerationType.AUTO)在我的情况下成功了。先迁移旧数据,保留现有密钥。
标签: java mysql jpa orm eclipselink