Java 为TypedQuery指定的类型与自身不兼容

Java 为TypedQuery指定的类型与自身不兼容,java,spring,hibernate,spring-boot,Java,Spring,Hibernate,Spring Boot,我对Spring和Hibernate有问题。我有以下几种方法: @Override @Transactional public List<SomeEntityClass> getSomeData(Integer someParam1, Long someParam2) { TypedQuery<SomeEntityClass> query = em.createQuery( "SELECT sec FROM SomeEntityClass

我对Spring和Hibernate有问题。我有以下几种方法:

@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<>();
    }
}
我发现,提供的答案表明类是从不同的类装入器装入的。然而:

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)

似乎,调用的
getSomeData
的实体管理器只是一些
SharedEntityManager
的代理,它们都有不同的类加载器…

这看起来确实像是类加载器问题。要确认这一点,请尝试此代码片段。我只是将其作为答案发布,因为我无法将其放入注释中

for (EntityType e : em.getMetamodel().getEntities()) {
    if (e.getJavaType().getName().equals(SomeEntityClass.class.getName())) {
        assert(e.getJavaType().equals(SomeEntityClass.class));
    }
}

如果断言失败,那么类确实会加载两次。

好的。我发现了问题。删除spring开发工具解决了所有问题:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>

org.springframework.boot

.

您的错误消息表明查询返回类型是class,而不是SomeEntityClass。您能详细说明一下吗?系统中的所有其他查询都是以这种方式生成的。我已经检查了实体中的绑定是否正常。它们是否正常。请参阅与@coladict的讨论中的更多内容日志显示[some.package.[…]和[class some.package.[…]。我真的没有ide为什么会这样。调试器怎么说?你确定实例是一样的吗?有没有办法添加一些代码,使你的示例完全可复制?好吧,断言没有失败。有什么想法吗?没有想过这样检查它。谢谢。好吧,除了打印每个
e.getJavaType之外.getName()
在日志中查看它是否甚至输入了
如果
块,我就没有主意了。其他信息:当我运行相同的查询时(调用相同的方法)在导致在应用程序启动时运行查询的
@Autowired
组件的
@PostConstruct
方法中,此查询工作正常。最好的是。当稍后在失败的同一位置调用时,它也会工作。然而,这会导致相同类型的错误,但会导致不同的方法和不同的查询。它输入IF语句。由于某些原因,断言是正确的。
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>