2012-10-25 213 views
0

運行該項目引發此錯誤:調用connection.rollback()拋出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(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對象爲空時connection.rollback()被調用。很難理解爲什麼會發生這種情況。在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; 
    } 
} 

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> 

WEB-INF/web.xml中

... 
    <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> 
... 

回答

1

可能是因爲您的連接未正確創建。在執行回滾之前,您應該檢查connection是否爲空。

此外,您應該至少記錄錯誤,以便您能夠確定發生了什麼。

我懷疑你的dS對象爲空,可能是因爲名稱不匹配而導致注入不當。

+0

我同意,但爲什麼不首先正確創建是什麼混淆了我。 – user1701467

+0

@ user1701467看到我更新的答案,你應該記錄錯誤,這將指出你的問題。 – dan

+0

connection = dS.getConnection();你在哪裏初始化數據源? – agirish

1

嘗試從try塊中記錄異常。

很可能,這條線會拋出異常: connection = dS.getConnection();

一般而言,您應該避免在可能的情況下捕捉所有異常。並記錄異常,以便了解最新情況。因爲例外情況,就像名稱所暗示的那樣,並不需要。

--tb

+0

其實它給'不能創建PoolableConnectionFactory(未知數據庫'javatest')'然後回滾一個。我在'context.xml'中將'javatest'改爲了適當的數據庫名稱,但是它仍然給出同樣的錯誤'javatest'。 – user1701467

1

我看不出你有你的初始化數據源

connection = dS.getConnection(); 

您必須對德尚

東西有些相似查找代碼:

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

是的,但是這不是什麼'@Resource(name =「jdbc/EmployeesDB」)'用於? – user1701467

+0

哦,是的,我錯過了! – agirish

+0

可能會有一些不匹配 - 你可以仔細檢查你指定的數據庫屬性 – agirish

1

兩個可能的原因:

  • dS.getConnection()正在拋出異常。可以是任何例外,因爲您的catch塊抓住了一切。你得到NullPointerException裏面的 catch塊,因爲connectionnull在回滾點。
  • 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塊,檢查是否connectionnull在回滾之前。如果數據庫連接從未創建,則不必回滾。 我在大型項目的日常工作中處理這種設置,這就是我們所做的。
  • 減最佳的解決方案:一旦dS.getConnection()完成後,繼續只有如果connectionnull。根據您的需要,您可以使用if (connection != null) { /* rest of code */ }if (connection == null) throw new NullPointerException();
+0

謝謝。我會記住這些信息並相應地更改我的代碼。我們還發現它是兩個'context.xml'文件衝突。一個在我的項目文件夾中,另一個在Tomcat的Server項目文件夾中。在Tomcat的'context.xml'中擺脫了重複(但錯誤)的xml行後,修復了這個問題。 – user1701467

+0

好。我也遇到了過時的配置文件問題。無論如何,儘管配置文件是最新和正確的,但最好確保您的代碼在所有正確覆蓋的基礎上都是健壯的。 =) – ADTC

相關問題