问题描述
我正在处理一些遗留代码,在某些地方,没有一种干净可靠的方法来获取给定实体的 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 (将#修改为@)