我对Spring&有问题休眠。我有以下方式的方法:
@Override
@Transactional
public List<SomeEntityClass> getSomeData(Integer someParam1, Long someParam2) {
TypedQuery<SomeEntityClass> query = em.createQuery(
"SELECT sec FROM SomeEntityClass sec " +
"WHERE sec.someField1 = :param1 " +
"AND sec.someField2 = :param2 ", SomeEntityClass.class);
query.setParameter("param1", someParam1);
query.setParameter("param2", someParam2);
try {
return query.getResultList();
} catch (Exception e) {
return new LinkedList<>();
}
}
此方法是Web套接字处理程序的一部分,在收到消息时调用。但是,当它发生时,我得到以下错误:
org.springframework.dao.InvalidDataAccessApiUsageException:
Type specified for TypedQuery [some.package.subpackage.SomeEntityClass] is incompatible
with query return type [class some.package.subpackage.SomeEntityClass]
我找到了similar question,并且提供的答案表明正在从不同的类加载器加载类。但是:
ClassLoader a = UserMicroscopeLensLight.class.getClassLoader();
ClassLoader b = em.getClass().getClassLoader();
a.equals(b)
收益率
true
编辑:2018-02-08 14:05 CET
所以我通过代码调试并从字节代码反编译AbstractEntityManagerImpl.class
并得到以下行:
if (!resultClass.isAssignableFrom(hqlQuery.getReturnTypes()[0].getReturnedClass())) {
throw new IllegalArgumentException("Type specified for TypedQuery [" + resultClass.getName() + "] is incompatible with query return type [" + hqlQuery.getReturnTypes()[0].getReturnedClass() + "]");
}
resultClass.getClassLoader()
给出了:
RestartClassLoader@9995
而hqlQuery.getReturnTypes()[0].getReturnedClass().getClassLoader()
(以及this.getClass().getClassLoader()
导致:
Launcher$AppClassLoader@10034
有趣的是,在查询方法中调用em.getClass().getClassLoader()
会导致:
RestartClassLoader@9995
所以我问...... WTF?!看看痕迹:
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.resultClassChecking(AbstractEntityManagerImpl.java:387)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:344)
at sun.reflect.GeneratedMethodAccessor109.invoke(Unknown Source:-1)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:298)
at com.sun.proxy.$Proxy109.createQuery(Unknown Source:-1)
at some.package.name.SomeDaoImpl.getSomeData(SomeDaoImpl.java:21)
Iit似乎,getSomeData
中调用的实体管理器只是某些SharedEntityManager
的代理,它们都有不同的类加载器......
答案 0 :(得分:1)
这绝对看起来像是一个类加载器问题。要确认它,请尝试此代码片段。我只是将其作为答案发布,因为我无法将其纳入评论中。
for (EntityType e : em.getMetamodel().getEntities()) {
if (e.getJavaType().getName().equals(SomeEntityClass.class.getName())) {
assert(e.getJavaType().equals(SomeEntityClass.class));
}
}
如果断言失败,那么该类确实加载了两次。
答案 1 :(得分:0)
确定。我发现了这个问题。删除spring dev工具解决了所有问题:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>