oracle 在 jpa 中保存对象之前如何知道 id
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12742826/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I know the id before saving an object in jpa
提问by mstzn
I have a new object. I want to know id before saving it. Is it possible? Or there is another way for this? I am using jpa as orm and oracle as database.
我有一个新对象。我想在保存之前知道 id。是否可以?或者有另一种方法吗?我使用 jpa 作为 orm 和 oracle 作为数据库。
@Id
@Basic(optional = false)
@Column(name = "ID", nullable = false)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "woTypeSeq")
private Long id;
I have a code field in my entity. If the user doesn't enter a value for the code
field, I want to set code as entity's id. If I persist entity, of course i can get id and set code value as id, but this is extra query database.
我的实体中有一个代码字段。如果用户没有为该code
字段输入值,我想将代码设置为实体的 id。如果我持久化实体,当然我可以获得 id 并将代码值设置为 id,但这是额外的查询数据库。
I want to do something like that
我想做这样的事情
if(entity.getCode()==null) {
entity.setCode(entity.getId);
jpaDao.saveOrUpdate(entity);
}
采纳答案by mstzn
After long researching about this, finally I found a solution.
经过长时间的研究,我终于找到了解决方案。
In fact, if you use sequence generatorin jpa, certainly you cannot obtain entity's id before saving it in database, because next id will be assigned by database sequence.
事实上,如果你在jpa中使用sequence generator,在将实体的id存入数据库之前肯定无法获取实体的id,因为下一个id将由数据库sequence分配。
There is one way to obtain the id if you use a custom generator, you can get the id before saving. Here is simple implementation:
如果您使用自定义生成器,则有一种获取 id 的方法,您可以在保存之前获取 id。下面是简单的实现:
public class CustomGenerator extends IdentityGenerator implements Configurable {
private IdentifierGenerator defaultGenerator;
public Serializable generate(SessionImplementor session, Object object) throws HibernateException {
Long idValue = (Long)defaultGenerator.generate(session, object);
//idValue will be assigned your entity id
return idValue;
}
@Override
public void configure(Type type, Properties params, Dialect d) throws MappingException {
DefaultIdentifierGeneratorFactory dd = new DefaultIdentifierGeneratorFactory();
dd.setDialect(d);
defaultGenerator = dd.createIdentifierGenerator("sequence", type, params);
}
}
Using CustomGenerator for id field:
对 id 字段使用 CustomGenerator:
@Id
@Basic(optional = false)
@Column(name = "ID", nullable = false)
@GenericGenerator(name = "seq_id", strategy = "com.yoncabt.abys.core.listener.CustomGenerator", parameters = { @Parameter(name = "sequence", value = "II_FIRM_DOC_PRM_SEQ") })
@GeneratedValue(generator = "seq_id")
private Long id;
回答by Shivan Dragon
With a @GeneratedValue type id you can't know that value in advance (before actually writing it). However once you persist your Bean, the id field will be populated in that bean instance and you can obtain it without needing to do an extra query for it. In other words:
使用 @GeneratedValue 类型 ID,您无法提前知道该值(在实际写入之前)。然而,一旦你持久化你的 Bean,id 字段将被填充到那个 bean 实例中,你可以获取它而无需对其进行额外的查询。换句话说:
MyEntiry myEnt = new MyEntity(); //the id field is null now
entityManager.persist(myEnt);//the id field is populated in myEnt now
Long id = myEnt.getId();
Also, depending on how your EntityManager
is configured, you might need to also first commit the transaction (manually) before you can get that id.
此外,根据您EntityManager
的配置方式,您可能还需要首先提交事务(手动),然后才能获得该 ID。
Update as per comment
根据评论更新
If you want to intercept and do something to the entity before it is saved and/or updated, you can use JPA LifeCycle Listeners (if you're using JPA version 2): Handling JPA lifecycle event using listeners and callbacks.
如果您想在保存和/或更新实体之前拦截并对其执行某些操作,您可以使用 JPA LifeCycle Listeners(如果您使用的是 JPA 版本 2):Handling JPA lifecycle event using listeners and callbacks。
Basically you can make a validate()
method in your bean, annotate it with @PrePersist
and @PreUpdate
and do the validation in it (if code is empty set it to id's value)
基本上你可以validate()
在你的 bean 中创建一个方法,用@PrePersist
和对其进行注释 @PreUpdate
并在其中进行验证(如果代码为空,则将其设置为 id 的值)
Update per 2nd comment
每 2 条评论更新
Yes, I honestly just thought of that just now: that if the id is auto generated, it might get populated AFTER the pre-persist event, such that when your pre-persist code is executed you still don't know what the id is (you may notice also that in the example you link to the id is NOT autogenerated but set manually).
What you can do in this case is add a boolean field to your entity (annotated with @Transient
so it won't get persisted) called isCodeEmpty
(which is false by default if not specifically initialized). Then in your @PrePersist
annotated method you check if the value for code field is empty and if so, set the boolean to true. Then you refactor your setId(...)
method such that (aside from setting the id field) it will check this boolean, and if true set the value of the code field to that of the id field:
是的,老实说,我刚刚才想到:如果 id 是自动生成的,它可能会在 pre-persist 事件之后填充,这样当你的 pre-persist 代码被执行时,你仍然不知道 id 是什么(您可能还会注意到,在示例中,您链接到的 id 不是自动生成的,而是手动设置的)。在这种情况下,您可以做的是向您的实体添加一个布尔字段(使用注释,@Transient
以便它不会被持久化)调用isCodeEmpty
(如果没有特别初始化,默认情况下为 false)。然后在您的@PrePersist
注释方法中检查代码字段的值是否为空,如果是,则将布尔值设置为 true。然后你重构你的setId(...)
方法,这样(除了设置 id 字段)它会检查这个布尔值,如果为真,则将代码字段的值设置为 id 字段的值:
public class YourEntity {
@Transient
private boolean isCodeEmpty;
public void setId(Whatever id) {
this.id = id;
if(isCodeEmpty) {
this.code = id;
//if necessary:
//this.isCodeEmpty = false;
}
}
@PrePersist
public void validate() {
if(code == null || code.isEmpty()) {
isCodeEmpty = true;
}
}
}
回答by suri
Just follow these steps then you will get the id before you complete the transaction 1st step adds an entity listener at your entity level by using the annotation called "@EntityListeners".
只需按照以下步骤操作,您将在完成事务之前获得 ID 第 1 步使用名为“@EntityListeners”的注释在您的实体级别添加一个实体侦听器。
@Id
@Basic(optional = false)
@Column(name = "ID", nullable = false)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "woTypeSeq")
@EntityListeners(SomeLinstener.class)
private Long id;
2nd step
第二步
public class SomeLinstener{
@PostPersist
public void userPostPersist(YourEntity obj) {
try {
obj.getId();
}catch(Exception e) {
}
}
this will you an id which has been generated by your generator and you can reuse where ever it is required this will give in a single transaction.
这将为您提供一个由您的生成器生成的 ID,您可以在任何需要的地方重复使用,这将在单个事务中提供。
hope this will help for somebody else
希望这对其他人有帮助