JPA ID生成策略 [英] JPA ID Generation Strategy

查看:118
本文介绍了JPA ID生成策略的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我为JPA类定义了一个生成器:

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

有些情况下,我已经有一个实体的ID,但是当我插入实体时,

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



我使用Hibernate作为JPA Provider。



谢谢

解决方案

我找不到在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 
{



$覆盖
保护可序列化saveWithGeneratedId(Object entity,String entityName,Object any,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 going
}

break;





$ b if(id == null ||
id == 0){
返回super.saveWithGeneratedId(entity,entityName,anything,source,requiresImmediateIdAccess);
} else {

return super.saveWithRequestedId(entity,id,entityName,anything,source);
}
}
}

然后我必须添加监听我的persistence.xml

 < property name =hibernate.ejb.event.mergevalue =my.package .MergeListener/> 


I defined a generator for a JPA class:

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

There are cases where I already have an ID for an entity but when I insert the Entity the Id gets generated using the generator.

Is it possible to define a generator that will only generate an Id when one does not exist?

I am using Hibernate as a JPA Provider.

Thank you

解决方案

I couldn't find a way to do this in JPA so I used Hibernate EJB3 event listeners. I over rode the saveWithGeneratedId to use reflection to check the entity for an @Id annotation and then to check that field for a value. If it has a value then I call saveWithRequestedId instead. Other wise I let it generate the Id. This worked well because I can still use the sequence for Hibernate that is set up if I need an Id. The reflection might add overhead so I might change it a little. I was thinking of having a getId() or getPK() method in all entities so I don't have to search for which field is the @Id.

Before I used reflection I tried calling session.getIdentifier(entity) to check but I was getting TransientObjectException( "The instance was not associated with this session" ). I couldn;t figure out how to get the Entity into the session without saving it first so I gave up. Below is the listener code I wrote.

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);
        }
    }
}

I then had to add the listener to my persistence.xml

 <property name="hibernate.ejb.event.merge" value="my.package.MergeListener"/>

这篇关于JPA ID生成策略的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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