java - JPA ID生成策略

标签 java hibernate jpa

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

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

在某些情况下,我已经有一个实体的 ID,但是当我插入实体时,Id 是使用生成器生成的。

是否可以定义一个生成器,只在不存在的情况下生成一个 Id?

我正在使用 Hibernate 作为 JPA Provider。

谢谢

最佳答案

我找不到在 JPA 中执行此操作的方法,因此我使用了 Hibernate EJB3 事件监听器。我过度使用 saveWithGeneratedId 来使用反射来检查实体是否有 @Id 注释,然后检查该字段的值。如果它有值,那么我会调用 saveWithRequestedId。否则我让它生成 Id。这很有效,因为如果我需要一个 Id,我仍然可以使用为 Hibernate 设置的序列。反射可能会增加开销,所以我可能会稍微改变一下。我正在考虑在所有实体中使用 getId()getPK() 方法,这样我就不必搜索哪个字段是 @Id

在我使用反射之前,我尝试调用 session.getIdentifier(entity) 来检查,但我得到了 TransientObjectException(“实例未与此 session 关联”)。我无法弄清楚如何在不先保存实体的情况下让实体进入 session ,所以我放弃了。下面是我写的监听器代码。

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

关于java - JPA ID生成策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5081947/

相关文章:

java - Android NDK释放内存

java - 如何在家里自己的机器上测试简单的服务器-客户端应用程序?

java - 快速排序3有什么问题

java - 如何从字符串中删除某些特定单词并将其存储在临时变量中并将该变量发送到我的查询

java - 将 swing 组件绘制到图形

java - Hibernate 异常 : java. lang.IllegalArgumentException:枚举类的未知名称值 []

java - QuerySyntaxException 但实体已映射

hibernate - 我们可以使用 JPA2 注释来缓存关联吗?

java - EhCache Hibernate 二级缓存 maxBytesLocalHeap 慢

java - 扩展 JPA 实体以添加属性和逻辑