2011-02-22 85 views
2

我定义了一个发电机的JPA类:JPA ID生成策略

<sequence-generator name="MY_SEQ" allocation-size="-1" 
    sequence-name="MY_SEQ" 
    initial-value="100000000" /> 

有,我已经有一个实体的ID的情况,但是当我插入实体被用生成器生成的ID。

是否有可能定义一个生成器,它只会在不存在时生成一个ID?

我使用Hibernate作为JPA Provider。

谢谢

+0

你怎么已有的ID,如果该条目不存在。这是一个坏主意,实施你在说什么。 – 2011-02-22 18:57:54

+0

我有2个数据库。一个在服务器上,另一个在PC上。这个想法是我将数据下载到个人电脑上,这样我就可以'离线'工作,这涉及到将实体放到PC上。在PC上使用我们的软件时,他们可以创建新的实体。我需要序列的新entites,如果它已经有一个ID我想插入实体与该ID。 – Allan 2011-02-23 12:58:33

回答

1

我找不到在JPA中这样做的方法,所以我使用了Hibernate EJB3事件侦听器。我骑着saveWithGeneratedId使用反射来检查@Id注释的实体,然后检查该字段是否有值。如果它有一个值,那么我请拨打saveWithRequestedId。其他方面,我让它生成Id。这很好,因为如果我需要一个Id,我仍然可以使用Hibernate的序列。反射可能会增加开销,所以我可能会稍微改变它。我正考虑在所有实体中使用getId()getPK()方法,因此我不必搜索@Id哪个字段。

在我使用反射之前,我尝试调用session.getIdentifier(实体)来检查,但我得到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"/> 
0

这不是一个好主意,序列用于代理键,在商业意义上毫无意义,但向你保证,不会有重复因此在插入时没有错误。