Java 调用connection.rollback()会引发NullPointerException

Java 调用connection.rollback()会引发NullPointerException,java,mysql,nullpointerexception,Java,Mysql,Nullpointerexception,运行项目会引发以下错误: java.lang.NullPointerException com.myproject.crud.EmployeesJDBCImpl.withDB(EmployeesJDBCImpl.java:157) com.myproject.crud.EmployeesJDBCImpl.doList(EmployeesJDBCImpl.java:119) com.myproject.crud.EmployeesJDBCImpl.listEmployees

运行项目会引发以下错误:

java.lang.NullPointerException
    com.myproject.crud.EmployeesJDBCImpl.withDB(EmployeesJDBCImpl.java:157)
    com.myproject.crud.EmployeesJDBCImpl.doList(EmployeesJDBCImpl.java:119)
    com.myproject.crud.EmployeesJDBCImpl.listEmployees(EmployeesJDBCImpl.java:111)
    com.myproject.crud.EmployeesJDBCImpl$Proxy$_$$_WeldClientProxy.listEmployees(EmployeesJDBCImpl$Proxy$_$$_WeldClientProxy.java)
    com.myproject.crud.EmployeesListServlet.doGet(EmployeesListServlet.java:36)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
try
块失败,它跳转到
catch
块,调用
connection.rollback()
时,
connection
对象似乎为空。很难理解为什么会这样。
context.xml
中提供的用户名和密码正确

EmployeesJDBCImpl.java

package com.myproject.crud;

import java.util.ArrayList;
import java.util.List;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.enterprise.context.ApplicationScoped;
import javax.annotation.Resource;
import javax.sql.DataSource;

@ApplicationScoped @JDBC
public class EmployeesJDBCImpl implements EmployeesRepository {

    @Resource(name="jdbc/EmployeesDB")
    private DataSource dS;

    @Override
    public Employee viewEmployee(final String id) {
        return withDB(new JDBCRunner<Employee>(){
            @Override
            public Employee run(Connection connection) throws Exception{
                PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM employees WHERE id = ?");

                preparedStatement.setString(1, id);

                ResultSet rs = preparedStatement.executeQuery();
                if(rs.next()){
                    Employee employee = new Employee();
                    employee.setId(rs.getString("id"));
                    employee.setName(rs.getString("name"));
                    employee.setPhone(rs.getString("phone"));
                    employee.setEmail(rs.getString("email"));                   
                    return employee;
                }else{
                    return null;
                }
        }});
    }

    private <T> T withDB(JDBCRunner<T> runner){
        Connection connection = null;

        try{
            connection = dS.getConnection();
            boolean auto = connection.getAutoCommit();
            connection.setAutoCommit(false);
            T result = runner.run(connection);
            connection.commit();
            connection.setAutoCommit(auto);
            return result;
        }catch(Exception e){
            try{
                connection.rollback(); // Nullpointer exception here
            }catch(SQLException ex){
            }
            //throw new EmployeesException(e);
        }finally{
            if(connection != null){
                try{
                    connection.close();
                }catch(Exception ex){
                }
            }
        }
        return null;
    }
}
package com.myproject.crud;
导入java.util.ArrayList;
导入java.util.List;
导入java.sql.Connection;
导入java.sql.PreparedStatement;
导入java.sql.ResultSet;
导入java.sql.SQLException;
导入java.sql.Statement;
导入javax.enterprise.context.ApplicationScoped;
导入javax.annotation.Resource;
导入javax.sql.DataSource;
@ApplicationScoped@JDBC
公共类EmployeesJDBCImpl实现EmployeesRepository{
@资源(name=“jdbc/EmployeesDB”)
私有数据源dS;
@凌驾
public Employee viewEmployee(最终字符串id){
返回withDB(新JDBCRunner(){
@凌驾
公共员工运行(连接)引发异常{
PreparedStatement PreparedStatement=connection.prepareStatement(“从id=?”的员工中选择*”;
准备好的报表。设置字符串(1,id);
ResultSet rs=preparedStatement.executeQuery();
如果(rs.next()){
员工=新员工();
employee.setId(rs.getString(“id”));
employee.setName(rs.getString(“name”);
employee.setPhone(rs.getString(“phone”);
employee.setEmail(rs.getString(“email”);
返回员工;
}否则{
返回null;
}
}});
}
私有T withDB(JDBCRunner){
连接=空;
试一试{
connection=dS.getConnection();
boolean auto=connection.getAutoCommit();
connection.setAutoCommit(false);
T结果=runner.run(连接);
commit();
连接。设置自动提交(自动);
返回结果;
}捕获(例外e){
试一试{
connection.rollback();//此处出现空指针异常
}catch(SQLException-ex){
}
//向新员工抛出性别歧视(e);
}最后{
if(连接!=null){
试一试{
connection.close();
}捕获(例外情况除外){
}
}
}
返回null;
}
}
META-INF/context.xml

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <Resource name="jdbc/EmployeesDB" auth="Container" type="javax.sql.DataSource"
               maxActive="100" maxIdle="30" maxWait="10000"
               username="root" password="secret" driverClassName="com.mysql.jdbc.Driver"
               url="jdbc:mysql://localhost:3306/javatest"/>
</Context>
...
    <description>MySQL Employees App</description>
    <resource-ref>
      <description>db connection</description>
      <res-ref-name>jdbc/EmployeesDB</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
    </resource-ref>
...

WEB-INF/WEB.xml

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <Resource name="jdbc/EmployeesDB" auth="Container" type="javax.sql.DataSource"
               maxActive="100" maxIdle="30" maxWait="10000"
               username="root" password="secret" driverClassName="com.mysql.jdbc.Driver"
               url="jdbc:mysql://localhost:3306/javatest"/>
</Context>
...
    <description>MySQL Employees App</description>
    <resource-ref>
      <description>db connection</description>
      <res-ref-name>jdbc/EmployeesDB</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
    </resource-ref>
...
。。。
MySQL员工应用程序
数据库连接
jdbc/EmployeesDB
javax.sql.DataSource
容器
...

可能是因为未正确创建连接。在执行回滚之前,您应该检查
连接
是否不为空

此外,您至少应该记录错误,这样您就能够了解发生了什么


我怀疑您的
dS
对象是空的,可能是由于名称不匹配而没有正确注入

可能是因为未正确创建连接。在执行回滚之前,您应该检查
连接
是否不为空

此外,您至少应该记录错误,这样您就能够了解发生了什么


我怀疑您的
dS
对象是空的,可能是由于名称不匹配而没有正确注入

尝试从Try块记录异常

很可能,此行将引发异常: connection=dS.getConnection()

通常,如果可能,您应该避免捕获所有异常。并记录异常,以便了解发生了什么。因为正如名字所暗示的那样,例外是不需要的


--tb

尝试从Try块记录异常

很可能,此行将引发异常: connection=dS.getConnection()

通常,如果可能,您应该避免捕获所有异常。并记录异常,以便了解发生了什么。因为正如名字所暗示的那样,例外是不需要的


--tb

我看不到您在哪里初始化了数据源

 connection = dS.getConnection();
您必须有一些dS的查找代码

类似于:

Context ctx=new InitialContext();                        
DataSource dS=(DataSource)ctx.lookup("jdbc/sampledb");   
Connection con=dS.getConnection(); 

我看不到您在哪里初始化了数据源

 connection = dS.getConnection();
您必须有一些dS的查找代码

类似于:

Context ctx=new InitialContext();                        
DataSource dS=(DataSource)ctx.lookup("jdbc/sampledb");   
Connection con=dS.getConnection(); 

两个可能的原因:

  • dS.getConnection()
    正在引发异常。可以是任何异常,因为catch块捕获所有内容。您会在catch块中得到
    NullPointerException
    ,因为
    connection
    在回滚时是
    null
  • dS.getConnection()
    正在返回一个
    null
    ,这会导致
    connection.getAutoCommit()
    抛出一个
    NullPointerException
    。这是因为
    connection
    已通过
    dS.getConnection()
    设置为
    null
在catch块中,从一个
e.printStackTrace()
开始,以确定真正的问题:

    ...
    }catch(Exception e){
        e.printStackTrace(); //This should show you what the real problem is
        try{
            connection.rollback();
        }catch(SQLException ex){
        }
        //throw new EmployeesException(e);
    }finally{
    ...
解决方案:

  • 在catch块中,在执行回滚之前,检查
    连接
    是否为
    null
    。如果从未创建数据库连接,则不必回滚。我每天在大型项目中处理这种设置,这就是我们所做的
  • 不太理想的解决方案:完成
    dS.getConnection()
    后,如果
    connection
    不是
    null
    ,则只继续。您可以使用
    if(connection!=null){/*代码的其余部分*/}