java Eclipse Texo ModelEMFConverter和Hibernate代理
我正试图将EclipseTexto集成到我现有的Hibernate项目中。我已经在ECore中建模了我的域模型,并使用Texo和常规的EMF代码生成从中生成了EMF和POJO代码
获取存储在数据库中的实体(POJO)不会出现问题,现在我想使用Texo的ModelEMFConverter
将Hibernate映射的数据模型转换为相应的EMF模型。但是,由于Hibernate返回的实体被透明地代理,因此此尝试失败。Texo的ModelResolver
无法查找这些代理实体的模型描述符,因为它将实体的类(即代理类)与映射的类进行比较,并在我的示例中出现异常而失败:
Exception in thread "main" java.lang.IllegalStateException: The class class foobar.Entity_$$_jvst4f2_5 is not managed by this ModelResolver at org.eclipse.emf.texo.utils.Check.isNotNull(Check.java:66) at org.eclipse.emf.texo.model.ModelResolver.getModelDescriptor(ModelResolver.java:366) at org.eclipse.emf.texo.model.ModelResolver.getModelObject(ModelResolver.java:298) at org.eclipse.emf.texo.resolver.DefaultObjectResolver.toUri(DefaultObjectResolver.java:188) at org.eclipse.emf.texo.resolver.DefaultObjectResolver.resolveToEObject(DefaultObjectResolver.java:98) at org.eclipse.emf.texo.converter.ModelEMFConverter.createTarget(ModelEMFConverter.java:146) at org.eclipse.emf.texo.converter.ModelEMFConverter.convertSingleEReference(ModelEMFConverter.java:265) at org.eclipse.emf.texo.converter.ModelEMFConverter.convertContent(ModelEMFConverter.java:189) at org.eclipse.emf.texo.converter.ModelEMFConverter.convert(ModelEMFConverter.java:107) [...]
来自ModelResolver
的相关代码位:
public ModelObject<?> getModelObject(final Object target) {
/* ... snip ... */
final ModelDescriptor modelDescriptor = getModelDescriptor(target.getClass(), true);
return modelDescriptor.createAdapter(target);
}
在将代理实体传递给模型转换器之前,我尝试使用以下代码手动展开代理实体:
final List<Object> objects = entities
.stream()
.map(o ->
o instanceof HibernateProxy ?
(Entity) ((HibernateProxy) o).getHibernateLazyInitializer().getImplementation() : o)
.collect(Collectors.toList());
final ModelEMFConverter converter = new ModelEMFConverter();
final Collection<EObject> eObjects = converter.convert(objects);
理论上,这种方法似乎是可行的(我通过单步执行转换代码进行了检查),但是对于我的数据模型中关联引用的实体,它失败了,这些实体不包含在原始的entities
列表中。我希望避免为了摆脱代理而手动遍历整个对象图
有没有办法从Hibernate检索未加密的实体?或者有没有人会建议我如何从不同的角度来处理这个模型转换
提前谢谢你的帮助
# 1 楼答案
您可以编写一个通用替换程序,它将遍历整个图形并替换给定实体实例的所有代理,如下所示:
不要忘记回滚完成此操作的事务(Hibernate可能认为对象是脏的,因为我们手动更改了字段值)。或者将其设置为只读(通过将刷新模式设置为手动)。或者在不刷新会话的情况下显式清除会话,从而使已解除代理的图形分离
如果这对您的需求是一个障碍,那么您可以通过从托管实体实例读取值并将解除代理的值设置到另一个实例来更改此方法。通过这种方式,您可以构建一个新的单独的非托管实体实例,该实例的整个图形都是在没有任何代理的情况下初始化的
或者,您可以只存储有关必要更改的信息,然后将其应用于分离实例上的事务之外,例如: