[英]JPA ID Generation Strategy
我为JPA类定义了一个生成器:
<sequence-generator name="MY_SEQ" allocation-size="-1"
sequence-name="MY_SEQ"
initial-value="100000000" />
在某些情况下,我已经有一个实体的ID,但是当我插入该实体时,会使用生成器生成ID。
是否可以定义仅在不存在Id时才生成ID的生成器?
我正在使用Hibernate作为JPA提供程序。
谢谢
我找不到在JPA中执行此操作的方法,因此我使用了Hibernate EJB3事件侦听器。 我过度使用saveWithGeneratedId
来使用反射来检查实体的@Id
批注,然后检查该字段的值。 如果它有一个值,那么我改为调用saveWithRequestedId
。 否则,我让它生成ID。 这很好用,因为如果需要Id,我仍然可以使用为Hibernate设置的序列。 反射可能会增加开销,因此我可能会对其进行一些更改。 我当时在考虑在所有实体中使用getId()
或getPK()
方法,因此不必搜索@Id
是哪个字段。
在我使用反射之前,我尝试调用session.getIdentifier(entity)进行检查,但是我遇到了TransientObjectException(“实例未与此会话关联”)。 我无法弄清楚如何在不先保存实体的情况下将其加入会话,所以我放弃了。 以下是我编写的侦听器代码。
public class MergeListener extends org.hibernate.ejb.event.EJB3MergeEventListener
{
@Override
protected Serializable saveWithGeneratedId(Object entity, String entityName, Object anything, EventSource source, boolean requiresImmediateIdAccess) {
Integer id = null;
Field[] declaredFields = entity.getClass().getDeclaredFields();
for (Field field : declaredFields) {
Id annotation = field.getAnnotation(javax.persistence.Id.class);
if(annotation!=null) {
try {
Method method = entity.getClass().getMethod("get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1));
Object invoke = method.invoke(entity);
id = (Integer)invoke;
} catch (Exception ex) {
//something failed (method not found..etc) , keep going anyway
}
break;
}
}
if(id == null ||
id == 0) {
return super.saveWithGeneratedId(entity, entityName, anything, source, requiresImmediateIdAccess);
} else {
return super.saveWithRequestedId(entity, id, entityName, anything, source);
}
}
}
然后,我不得不将侦听器添加到我的persistence.xml中
<property name="hibernate.ejb.event.merge" value="my.package.MergeListener"/>
这不是一个好主意,序列用于代理键,在业务上没有意义,但向您保证,不会重复,因此在插入时不会出错。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.