冬眠中的魔法npe

use*_*679 3 java hibernate hql

当我写作

Session session = sessionFactory.getCurrentSession();
List<Candidate> candidates = (List<Candidate>) session.createQuery(
        "select Candidate from Candidate as candidate  left outer join"
        + " candidate.skills as skill    where skill.id =" + 1).list();
Run Code Online (Sandbox Code Playgroud)

我已经在第二线了

如果我写

Session session = sessionFactory.getCurrentSession();
List<Candidate> candidates = (List<Candidate>) session.createSQLQuery(
        "select candidate.* from candidate inner join candidate_skill"
        + " on candidate.id = candidate_skill.candidate_id"
        + " inner join skill on candidate_skill.skill_id = skill.id"
        + " where skill.id = 1").list();
Run Code Online (Sandbox Code Playgroud)

我有好结果

为什么我在第一个例子中有NPE?

严重:Servlet [appServlet]的Servlet.service()在路径[/ ui]的上下文中引发异常[请求处理失败; 嵌套异常是java.lang.NullPointerException],原因是org.hibernate.dialect.function.SQLFunctionRegistry.findSQLFunction(SQLFunctionRegistry.java:41)中的根本原因java.lang.NullPointerException

在此输入图像描述

Luc*_*cci 9

删除select Candidate从第一个查询(你有一个字段CandidateCandidate实体)?完整实体选择的HQL语法是from <mapped entity>....


关于你的问题:

魔法NPE如何发生:( ...经过一些调试或HQL解析器之后)
HQL解析器 - 在AST构建期间 - 查找被调用的属性引用Candidate但找不到它所以尝试解析为ClassName或函数(看起来在org.hibernate.hql.internal.ast.util.LiteralProcessor.processConstant()功能); 候选者是一个类名和解析器威胁它作为一个鉴别器值(用于实体子类)返回null.
在该解析器之后,在select的显式列表的转换期间查找Candidatenull并尝试解析为函数,因为null它不是有效的dataType(实体,原语或其他有效的数据类型),因此尝试将它们解析为函数; 值null我们用作函数的参数SQLFunctionRegistry.findSQLFunction(),作为这个体:

public SQLFunction findSQLFunction(String functionName) {
        return sfi.getSqlFunctionRegistry().findSQLFunction( functionName.toLowerCase() );
    }
Run Code Online (Sandbox Code Playgroud)

functionName.toLowerCase()导致NPE.