微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

当一个 JPA/Hibernate 实体只有一个实体没有 EntityManager/Session时,如何锁定一个 JPA/Hibernate 实体?

如何解决当一个 JPA/Hibernate 实体只有一个实体没有 EntityManager/Session时,如何锁定一个 JPA/Hibernate 实体?

我正在处理一些遗留代码,在某些地方,没有一种干净可靠的方法获取给定实体的 JPA EntityManager(或 Hibernate Session),以便根据需要调用 lock(...) 方法.本质上,我们在实体中有一个方法需要执行以下操作:

@Entity
public class SomeEntity {
    @Column(...)
    @Basic(...)
    private String name; 

    ... 

    public void doSomething(/* arguments irrelevant */) {
         ...
         myCurrentEntityManagerOrSession.lock(...);
         ...
    }

    ...
}

问题是如何做到这一点 - 如何访问该实体管理器或会话?我们编造了两种方法来完成我们需要的事情,尽管这两种方法都有效,但都不理想:

选项 #1 - 令人尴尬的财产触发器

    final String originalName = getName();
    setName("modified " + originalName);
    setName(originalName);

...“欺骗”Hibernate(我们使用字节码增强,顺便说一句)来执行锁定本身,然后撤消更改但保留锁定(我们会在任何“廉价”属性上执行此操作)。

选项 #2:不当滥用 Hibernate 字节码增强及其内部 API 的反射

  private static final Method HIBERNATE_ENTITY_ENTRY_GETTER;
    static {
        Method getter;
        try {
            getter = SomeEntity.class.getmethod("$$_hibernate_getEntityEntry");
        } catch (NoSuchMethodException e) {
            /// Oooh .. not good!
            getter = null;
        }
        HIBERNATE_ENTITY_ENTRY_GETTER = getter;
    }
    public Session getEntitySession()  {
        try {
            final MutableEntityEntry entry = (MutableEntityEntry) HIBERNATE_ENTITY_ENTRY_GETTER.invoke(this);
            return (Session) entry.getPersistenceContext().getSession();
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    public void lock(final LockMode lockMode) {
        getEntitySession().lock(this,lockMode);
    }
    public void lock() {
        lock(LockMode.OPTIMISTIC_FORCE_INCREMENT);
    }

是否有适当、干净的方法获取当前管理/拥有特定实体的 EntityManager/Session?我们知道底层引擎必须已经知道这一点,当然......但似乎这很好地隐藏起来。

附加说明:ThreadLocal 在某些项目中可能是一种解决方案,但在本项目中则不然。别问了。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。