在JPA @GeneratedValue列中手动指定主键的值 [英] Manually specify the value of a primary key in JPA @GeneratedValue column

查看:2323
本文介绍了在JPA @GeneratedValue列中手动指定主键的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的实体有一个主键/ 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会告诉我内部异常:找不到org.eclipse.persistence.platform.database.MySQLPlatform 。但是我已经检查过:类在类路径上。



所以我将另一个类子类化,NativeSequence:

 公共类MyNativeSequence扩展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 
异常说明:工作单元中遇到空或零主键[de.dfv.datenbank.domain.Mitarbeiter [id = null]],主键[null ]。设置描述符IdValidation或eclipselink.id-validation属性。
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:102)
...
引起:Exception [EclipseLink-7197](Eclipse Persistence服务 - 2.4.0.v20120608-r11652):org.eclipse.persistence.exceptions.ValidationException
异常描述:在工作单元克隆中遇到空或零主键[de.dfv.datenbank.domain.Mitarbeiter [id = null]],主键[null]。设置描述符IdValidation或eclipselink.id-validation属性。
at org.eclipse.persistence.exceptions.ValidationException.nullPrimaryKeyInUnitOfWorkClone(ValidationException.java:1451)
...

(为清晰起见,缩短了堆栈跟踪)。这是我之前收到的相同信息。我不应该继承NativeSequence的子类吗?如果是这样,我不知道在Sequence或StandardSequence中为抽象方法实现什么。



值得注意的是,这只是子类化(不覆盖任何方法) )该课程按预期工作。但是,在中保留false并且isAlwaysOverrideExistingValue(...)根本不会生成单个值(我逐步执行程序并且 getGeneratedValue()不会被调用一次。)



此外,当我在一个事务中插入类似8种实体时,它会在数据库中产生11条记录(怎么回事?!)。



编辑(2012-09-01):我仍然没有问题的解决方案,实施我自己的序列没有解决它。我需要的是一种能够不显式设置Id(因此它将自动生成)并能够显式设置Id的方法(因此它将用于在数据库中创建记录)。 / p>

我尝试将列定义为auto_increment,并省略@GeneratedValue,但验证将启动并且不允许我保存这样的实体。如果我指定一个值!= 0和!=零,mysql会抱怨重复的主键。



我的想法和选项都用完了。任何? (开始赏金)

解决方案

这适用于eclipselink。它将为序列创建一个单独的表,但这不应该造成问题。

  @Id 
@ GeneratedValue(strategy = GenerationType.AUTO)
@Column(name =id,insertable = true,updatable = true,unique = true,nullable = false)
private Long id;

GenerationType.AUTO将选择理想的生成策略。由于该字段被指定为可插入和可更新,因此将使用TABLE生成策略。这意味着eclipselink将生成另一个包含当前序列值的表并生成序列本身,而不是将其委托给数据库。由于列声明为可插入,如果持久化时id为null,则eclipselink将生成id。否则将使用现有ID。


I'm having an Entity which has a primary key / id field like the following:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

This works well. I'm using EclipseLink to create the DDL-Schema, and the column is correctly created like so:

`id` bigint(20) NOT NULL AUTO_INCREMENT

However, I've got several entities for which I do want to specify the PK myself (it's a little application that transfers data from an old database to the new one we're building). If I specify the ID for the POJO (using setId(Long id)) and persist it, EclipseLink does not save it (i.e. the record is saved, but the id is auto generated by eclipseLink).

Is there a way to manually specify the value of a column which has a @GeneratedValue ?

Here some thoughts on the issue:

I tried to work around the problem by not using @GeneratedValue at all, but simply manually define the column to be AUTO_INCREMENTed. However this forces me to manually provide an IDs always, since EclipseLink validates the primary key (so it may not be null, zero, or a negative number). The exception message reads that I should specify eclipselink.id_validation, however this does not seem to make any difference (I annotated @PrimaryKey(validation = IdValidation.NONE) but still got the same message).

To clarify: I'm using EclipseLink (2.4.0) as persistence provider and I can't switch away from it (large portions of the project depend on eclipselink specific query hints, annotations, and classes).


EDIT (In Response to the answers):

Custom Sequencing: I tried to implement my own sequencing. I tried subclassing DefaultSequence, but EclipseLink will tell me Internal Exception: org.eclipse.persistence.platform.database.MySQLPlatform could not be found. But I've checked: The class is on the classpath.

So I subclassed another class, 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;
    }

}

However, what I get is the following:

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)
    ...

(stack trace shortened for clarity). This is the same message which I got before. Shouldn't I subclass NativeSequence? If so, I don't know what to implement for the abstract methods in Sequence or StandardSequence.

It may also be worth noting, that simply subclassing (without overriding any methods) the class works as expected. However, returing false in shouldAlwaysOverrideExistingValue(...) will not generate a single value at all (I stepped through the program and getGeneratedValue() is not called once).

Also, when I insert like 8 entities of a certain kind within a transaction it resulted in 11 records in the database (what the hell?!).

EDIT (2012-09-01): I still do not have a Solution for the problem, Implementing my own sequence did not solve it. What I need is a way to be able to not set an Id explicitly (so it will be auto generated) and to be able to set an Id explicitly (so it will be used for the creation of the record in the database).

I tried to define the column as auto_increment myself and ommit @GeneratedValue, however Validation will kick in and not allow me to save such an entity. If I specify a value != 0 and != zero, mysql will complain for a duplicate primary key.

I'm running out of ideas and options to try. Any? (starting a bounty)

解决方案

This works with eclipselink. It will create a seperate table for the sequence, but that shouldn't pose a problem.

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="id", insertable=true, updatable=true, unique=true, nullable=false)
private Long id;

GenerationType.AUTO will choose the ideal generation strategy. Since the field is specified as insertable and updateable, a TABLE generation strategy will be used. This means eclipselink will generate another table holding the current sequence value and generate the sequence itself instead of delegating it to the database. Since the column is declared insertable, if id is null when persisting, eclipselink will generate the id. Otherwise the existing id will be used.

这篇关于在JPA @GeneratedValue列中手动指定主键的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆