【发布时间】:2016-01-29 15:35:53
【问题描述】:
我在一个 EAR 包中遇到问题,该包包含一个 EJB 模块中的服务器部署的持久性单元和一个 WAR 模块中的 Web 应用程序
EAR
|--- persistence unit (EJB module)
|--- web app (WAR)
...
一切都编译成功,部署(在 WildFly 10 CR5 下)成功执行。持久化单元已正确部署并创建了模式(在开发期间使用 Hibernate 模式生成)。
但是,当我尝试保持这样的实体之一时
MyEntitiy e = new MyEntitiy();
e.setId(UUID.randomUUID().toString());
e.setName("name");
entityService.save(e);
我得到一个运行时错误,其根本原因是:
Caused by: java.lang.IllegalArgumentException: Can not set java.lang.String field x.y.z.MyEntity.id to x.y.z.MyEntity
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:36)
at java.lang.reflect.Field.get(Field.java:393)
at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:39)
深入调试器,我找到了方法 sun.reflect.UnsafeFieldAccessorImpl.ensureObj,它通过方法 Class.isAssignableFrom 在类之间执行检查
-
Field对象的类 (Field.getDeclaredClass()) - 要持久化的实体的类
此检查返回 false,因为 to 类已经加载了不同的 ClassLoaders(它们在逻辑上是同一个类)。
如何在不改变项目总体布局的情况下克服这个问题(即,将持久性单元保持为 EJB 模块以在各个模块之间共享)?
【问题讨论】:
-
您是否也在 ejb jar 和 war 文件中打包 MyEntity 类(或多个实体)?
-
@MadhusudanaReddySunnapu 是的
-
虽然我没有测试过,但根据 jboss 文档,您可能希望从 war 文件中删除域实体并进行测试。根据文档,默认情况下,ejb jar 中定义的类可用于 war 文件中的类。
-
@MadhusudanaReddySunnapu 嗨!我花了一段时间才能彻底测试您的解决方案(必须重写部分核心代码才能这样做)。它有效:如果您想回答这个问题,我很乐意立即接受。
-
很高兴有帮助。我已将其发布为答案,以便其他人也可以从中受益。
标签: java classloader wildfly