Java JPA ID生成策略

Java JPA ID生成策略,java,hibernate,jpa,Java,Hibernate,Jpa,我为JPA类定义了一个生成器: <sequence-generator name="MY_SEQ" allocation-size="-1" sequence-name="MY_SEQ" initial-value="100000000" /> 在某些情况下,我已经有了实体的ID,但是当我插入实体时,ID是使用生成器生成的 是否可以定义一个仅在不存在Id时生成Id的生成器 我使用Hibernate作为JPA提供者 谢谢这不是一个好主意,序列用于代理键,在业务意义

我为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"/>


如果条目不存在,您如何拥有ID。实现你所说的是个坏主意。我有两个数据库。一个在服务器上,另一个在PC上。我的想法是将数据下载到PC上,以便“脱机”工作。这包括将实体下载到PC上。在PC上使用我们的软件时,它们可以创建新的实体。我需要新实体的序列,如果它已经有一个ID,我想插入具有该ID的实体。我有这样做的理由(见我上面的评论)。我已经找到了避免PK重复的方法。我想知道是否有可能编写一个生成器,在没有PK的情况下使用序列,而在已经有PK的情况下不使用序列。