执行 jtable 显示异常

Posted

技术标签:

【中文标题】执行 jtable 显示异常【英文标题】:executing a jtable shows exception 【发布时间】:2017-01-05 17:13:25 【问题描述】:

我正在尝试开发一个基于 jtable 的 JDBC 程序,该程序创建一个与数据库中存在的表相关的表。我创建了两个方法,即 databaseHandler() 和 graphicsHandler() 来处理与数据库和图形相关的指令。coldata 和 rowdata包含列名和结果集行数据。但是在使用这些值绘制表格时,我遇到了 NullPointerException 但我不明白为什么。非常感谢任何人的帮助。谢谢。

import java.awt.BorderLayout;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Vector;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

public class Final 
    int columnno,rowno;
    Connection connection;
    PreparedStatement preparedStatement;
    ResultSet resultSet;
    ResultSetMetaData metaData;
    Vector<String> coldata;
    Vector<Object> rowdata,temp;

    DefaultTableModel tableModel;
    JScrollPane scrollPane;
    JTable table;

    public Final() 
        // TODO Auto-generated constructor stub
        ValueHolder holder = DatabaseHandler();
        GraphicsHandler(holder.getCd(),holder.getRd());
    
    private void GraphicsHandler(Vector<String> coldata, Vector<Object> rowdata) 
        // TODO Auto-generated method stub
        JFrame frame = new JFrame();
        frame.setLayout(new BorderLayout(0, 20));  //setting up horizontal and vertical gap
        scrollPane.setViewportView(table);
        scrollPane.setWheelScrollingEnabled(true);
        frame.add(scrollPane, BorderLayout.CENTER);
        tableModel = new DefaultTableModel(rowdata,coldata);
        table = new JTable(tableModel);

        frame.setVisible(true);
        frame.pack();
    
    private ValueHolder DatabaseHandler() 
        // TODO Auto-generated method stub
        String driver = "com.mysql.jdbc.Driver";
        String url = "jdbc:mysql://localhost:3306/company?user=username&password=password";
        try 
            Class.forName(driver);
            connection = DriverManager.getConnection(url);
            preparedStatement = connection.prepareStatement("select * from product");
            resultSet = preparedStatement.executeQuery();
            metaData = resultSet.getMetaData();
            columnno = metaData.getColumnCount();
            rowno = 1;
            coldata = new Vector<String>();
            for (int i = 1; i <= columnno; i++) 
                coldata.add(metaData.getColumnLabel(i));
            
            System.out.println();
            rowdata = new Vector<Object>() ; temp = new Vector<Object>();
            while (resultSet.next()) 
                for (int i = 1; i <= columnno; i++) 
                    temp.add(resultSet.getString(i));
                
                rowdata.add(temp.clone());
                temp.clear();
                rowno++;
            
         catch (ClassNotFoundException | SQLException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
        
        return new ValueHolder(rowdata, coldata);   
    
    public static void main(String[] args) 
        // TODO Auto-generated method stub
        new Final();
    


class ValueHolder 

    Vector<Object> rd; Vector<String> cd;
    public ValueHolder(Vector<Object> rowdata, Vector<String> coldata) 
        this.rd = rowdata;
        this.cd = coldata;
    
    public Vector<Object> getRd() 
        return rd;
    

    public Vector<String> getCd() 
        return cd;
    


【问题讨论】:

What is a NullPointerException, and how do I fix it?的可能重复 【参考方案1】:

我只是通过扩展 javax.swing.table.AbstractTableModel 并添加对数据库运行查询的能力来做到这一点的。一旦这工作正常,您可以简单地在您的 Swing 项目中使用 JTable。希望这会有所帮助。

/*
  this is a dynamic JTable created out of a SQL-Query 
  it can by called by  different constructors:
  - by a javax.sql.Connection
  - by a JDBC-Driver and the connection URL

 once instatiated without any error, you call the methode excuteQuery(String sqlquery) it will create the JTable and fill it with
 the result of the query

 to display this query add the JTable to a JPanel like

JFrame frame = new JFrame("My Query Result");
frame.getContentPane.setLayout(new BorderLayout());

JdbcTable table = new JdbcTable(connection);
table.executeQuery("select * from employee");

frame.getContentPane().add(BorderLayout.CENTER,new JScrollPane(table)); 
frame.pack();
frame.setVisible(true);


*/

package test;

import java.sql.Array;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.table.AbstractTableModel;

public class JdbcTable extends AbstractTableModel 

private Connection con = null;
private Statement stmt = null;
private Logger logger = Logger.getLogger("test");
private boolean connectionEstablished;
private String[] columnNames;
private String[] fieldNames;
private int[] columnTypes;
private ResultSetMetaData rsmd;
private Vector rows;
private int counter;
private boolean standalone = false;
private String SQLError;
private SimpleDateFormat sdf;
private SimpleDateFormat sdt;
private int maxRows = 10000;
private String nullTxt;
private boolean useNullTxt = true;

/*
 instantiate JdbcTable with a java.sql.Connection
 */
public JdbcTable(Connection con) 
    setNullTxt("NULL");
    setCon(con);
    setCounter(0);
    try 
        setStmt(con.createStatement());
     catch (SQLException sqlex) 
        logSqlException("JdbcTable(Connection con)", Level.WARNING, sqlex);
        setConnectionEstablished(false);
    



/*
  instantiate JdbcTable by a JDBC-Driver and an URL
 */
public JdbcTable(String jdbcDriver, String jdbcUrl) 
    setNullTxt("NULL");
    setCounter(0);
    try 
        Class.forName(jdbcDriver);
        setCon(DriverManager.getConnection(jdbcUrl));
        setConnectionEstablished(true);
     catch (ClassNotFoundException ex) 
        logException("JdbcTable(String jdbcDriver, String jdbcUrl)", Level.SEVERE, "can not load drvier class " + ex.getMessage());
        setConnectionEstablished(false);
     catch (SQLException sqlex) 
        logSqlException("JdbcTable(Connection con)", Level.WARNING, sqlex);
        setConnectionEstablished(false);
    


/*
  close the Statement and the connection, use with care not to close your connection by fault

 */
public void close() 
    try 
        if (stmt != null) 
            stmt.close();
        
        if (con != null) 
            con.close();
        
     catch (SQLException sqlex) 
        logSqlException("close() ", Level.WARNING, sqlex);
    


/*
  execute the query if a connection exists
  @param query the SQL statement to be run
 */
public boolean executeQuery(String query) 
    if (!isConnectionEstablished()) 
        return false;
    


    sdf = (SimpleDateFormat) DateFormat.getDateTimeInstance();
    sdt = (SimpleDateFormat) DateFormat.getTimeInstance();

    Timestamp timestamp = null;
    Time time = null;
    java.sql.Date date = null;

    try 
        // we send the query to the DB
        ResultSet rs = getStmt().executeQuery(query);

        // then we need the ResultSetMetaData
        setRsmd(rs.getMetaData());

        // we loop the result and add each row to the Vector
        rows = new Vector();
        setCounter(0);
        while (rs.next()) 

            // this is just one Line
            Vector newRow = new Vector();

            // thanks to the ResultSetMetaData, we now the number of columns
            for (int i = 1; i <= getColumnCount(); i++) 

                // Depending on the Type, we add every single value
                int type = columnTypes[i - 1];
                switch (type) 
                    case Types.ARRAY:
                        newRow.add(rs.getArray(i));
                        break;
                    case Types.BIGINT:
                        newRow.add((Long) rs.getLong(i));
                        break;
                    case Types.BINARY:
                        newRow.add((String) "BINARY not supported");
                        break;
                    case Types.BIT:
                        newRow.add(rs.getBoolean(i));
                        break;
                    case Types.BLOB:
                        newRow.add((String) "BLOB not supported");
                        break;
                    case Types.BOOLEAN:
                        newRow.add(rs.getBoolean(i));
                        break;
                    case Types.CHAR:
                        newRow.add((String) rs.getString(i));
                        break;
                    case Types.CLOB:
                        newRow.add((String) "CLOB not supported");
                        break;
                    case Types.DATALINK:
                        newRow.add((String) "DATALINK not supported");
                        break;
                    case Types.DATE:
                        newRow.add((java.sql.Date) rs.getDate(i));
                        break;
                    case Types.DECIMAL:
                        newRow.add((java.math.BigDecimal) rs.getBigDecimal(i));
                        break;
                    case Types.DISTINCT:
                        newRow.add((String) "DISTINCT not supported");
                        break;
                    case Types.DOUBLE:
                        newRow.add((Double) rs.getDouble(i));
                        break;
                    case Types.FLOAT:
                        newRow.add((Float) rs.getFloat(i));
                        break;
                    case Types.INTEGER:
                        newRow.add((Integer) rs.getInt(i));
                        break;
                    case Types.JAVA_OBJECT:
                        newRow.add((String) "JAVA_OBJECT not supported");
                        break;
                    case Types.LONGNVARCHAR:
                        newRow.add((String) rs.getString(i));
                        break;
                    case Types.LONGVARBINARY:
                        newRow.add((String) "LONGVARBINARY not supported");
                        break;
                    case Types.LONGVARCHAR:
                        newRow.add((String) rs.getString(i));
                        break;
                    case Types.NCHAR:
                        newRow.add((String) rs.getString(i));
                        break;
                    case Types.NCLOB:
                        newRow.add((String) "NCLOB not supported");
                        break;
                    case Types.NULL:
                        newRow.add((String) "NULL Type not supported");
                        break;
                    case Types.NUMERIC:
                        newRow.add((java.math.BigDecimal) rs.getBigDecimal(i));
                        break;
                    case Types.NVARCHAR:
                        newRow.add((String) rs.getString(i));
                        break;
                    case Types.OTHER:
                        newRow.add((String) "OTHER Type not supported");
                        break;
                    case Types.REAL:
                        newRow.add((Float) rs.getFloat(i));
                        break;
                    case Types.REF:
                        newRow.add((String) "REF Type not supported");
                        break;
                    case Types.REF_CURSOR:
                        newRow.add((String) "REF_CURSOR Type not supported");
                        break;
                    case Types.ROWID:
                        newRow.add((String) "ROWID Type not supported");
                        break;
                    case Types.SMALLINT:
                        newRow.add((Integer) rs.getInt(i));
                        break;
                    case Types.SQLXML:
                        newRow.add((String) rs.getString(i));
                        break;
                    case Types.STRUCT:
                        newRow.add((String) "STRUCT Type not supported");
                        break;
                    case Types.TIME:
                        //newRow.add((java.sql.Time) rs.getTime(i));
                        time = rs.getTime(i);
                        if (time != null) 
                            newRow.add((String) sdt.format(time.getTime()));
                         else 
                            newRow.add((String) getNullTxt());
                        
                        break;
                    case Types.TIMESTAMP:
                        //newRow.add((java.sql.Timestamp) rs.getTimestamp(i));
                        // because JTable does format Timestmap as Date
                        timestamp = rs.getTimestamp(i);
                        if (timestamp != null) 
                            newRow.add((String) sdf.format(timestamp.getTime()));
                         else 
                            newRow.add((String) getNullTxt());
                        
                        break;
                    case Types.TIMESTAMP_WITH_TIMEZONE:
                        //newRow.add((java.sql.Timestamp) rs.getTimestamp(i));
                        timestamp = rs.getTimestamp(i);
                        if (timestamp != null) 
                            newRow.add((String) sdf.format(timestamp.getTime()));
                         else 
                            newRow.add((String) getNullTxt());
                        
                        break;
                    case Types.TIME_WITH_TIMEZONE:
                        //newRow.add((java.sql.Time) rs.getTime(i));
                        time = rs.getTime(i);
                        if (time != null) 
                            newRow.add((String) sdt.format(time.getTime()));
                         else 
                            newRow.add((String) getNullTxt());
                        
                        break;
                    case Types.TINYINT:
                        newRow.add((Integer) rs.getInt(i));
                        break;
                    case Types.VARBINARY:
                        newRow.add((String) "VARBINARY Type not supported");
                        break;
                    case Types.VARCHAR:
                        newRow.add((String) rs.getString(i));
                        break;
                    default:
                        newRow.add((String) rs.getString(i));
                        break;
                

                if (rs.wasNull()) 
                    newRow.remove(newRow.size() - 1);
                    if ((getColumnClass(newRow.size() - 1) != String.class) || ( !isUseNullTxt()) ) 
                        newRow.add(null);
                     else 
                        newRow.add(getNullTxt());
                    
                

            
            rows.add(newRow);

            /*
               We limit the numbers of rows read to the value of maxRows.
               This value is by default set to 10'000 if you set it to 0, 
               there will be no limit.
             */
            counter++;
            if ((getMaxRows() > 0) && (counter == getMaxRows())) 
                break;
            

        


     catch (SQLException sqlex) 
        logSqlException("executeQuery()", Level.WARNING, sqlex);
        return false;
    

    return true;


/*
   log a  SQLexception by providing the methode and the Exception
 */
private void logSqlException(String methode, Level level, SQLException sqlex) 
    logger.log(level, "SQL Exception in 0 : 1 SQLState: 2 SQL Error Code: 3", new Object[]methode, sqlex.getMessage(), sqlex.getSQLState(), sqlex.getErrorCode());
    setSQLError("\tSQL Exception: " + sqlex.getMessage() + "\n\tSQL State:     " +  sqlex.getSQLState() + "\n\tError-Code:    " + sqlex.getErrorCode() + "\n");       


/*
   log an exception by providing the methode and the Exception
 */
private void logException(String methode, Level level, String message) 
    logger.log(level, "Exception in 0 :  Message: 1 ", new Object[]methode, message);


@Override
public int getRowCount() 
    return rows.size();


public int getNumRows() 
    return getRowCount();


@Override
public int getColumnCount() 
    return columnNames.length;


public String getColumnName(int column) 
    if (columnNames[column] != null) 
        return columnNames[column];
     else 
        return "";
    


public Class getColumnClass(int column) 

    int type;
    try 
        type = getRsmd().getColumnType(column + 1);
     catch (Exception e) 
        logException("getColumnClass(" + column + ")", Level.WARNING, "Error fetching column class type, using default String.class. Exception: " + e.getMessage());
        return String.class;
    

    switch (type) 
        case Types.ARRAY:
            return Array.class;
        case Types.BIGINT:
            return long.class;
        case Types.BINARY:
            return byte.class;
        case Types.BIT:
            return boolean.class;
        case Types.BLOB:
            return byte.class;
        case Types.BOOLEAN:
            return boolean.class;
        case Types.CHAR:
            return String.class;
        case Types.CLOB:
            return String.class;
        case Types.DATALINK:
            return Object.class;
        case Types.DATE:
            return java.sql.Date.class;
        case Types.DECIMAL:
            return java.math.BigDecimal.class;
        case Types.DISTINCT:
            return Object.class;
        case Types.DOUBLE:
            return double.class;
        case Types.FLOAT:
            return float.class;
        case Types.INTEGER:
            return int.class;
        case Types.JAVA_OBJECT:
            return Object.class;
        case Types.LONGNVARCHAR:
            return String.class;
        case Types.LONGVARBINARY:
            return Object.class;
        case Types.LONGVARCHAR:
            return String.class;
        case Types.NCHAR:
            return String.class;
        case Types.NCLOB:
            return Object.class;
        case Types.NULL:
            return Object.class;
        case Types.NUMERIC:
            return java.math.BigDecimal.class;
        case Types.NVARCHAR:
            return String.class;
        case Types.OTHER:
            return String.class;
        case Types.REAL:
            return float.class;
        case Types.REF:
            return Object.class;
        case Types.REF_CURSOR:
            return Object.class;
        case Types.ROWID:
            return Object.class;
        case Types.SMALLINT:
            return int.class;
        case Types.SQLXML:
            return String.class;
        case Types.STRUCT:
            return Object.class;
        case Types.TIME:
            // TIME is not correctly rendered
            //return java.sql.Time.class;
            return String.class;
        case Types.TIMESTAMP:
            // Timestamp is not correctly rendered
            //return java.sql.Timestamp.class;
            return String.class;
        case Types.TIMESTAMP_WITH_TIMEZONE:
            // Timestamp is not correctly rendered
            //return java.sql.Timestamp.class;
            return String.class;
        case Types.TIME_WITH_TIMEZONE:
            // TIME is not correctly rendered
            //return java.sql.Time.class;
            return String.class;
        case Types.TINYINT:
            return int.class;
        case Types.VARBINARY:
            return String.class;
        case Types.VARCHAR:
            return String.class;
        default:
            return Object.class;
    



public boolean isCellEditable(int row, int column) 
    return false;

    /*
     is always false, in this case I do not want to write.. 

     */


@Override
public Object getValueAt(int rowIndex, int columnIndex) 
    Vector v = (Vector) rows.elementAt(rowIndex);
    return (Object) v.elementAt(columnIndex);


/**
 * @return the con
 */
public Connection getCon() 
    return con;


/**
 * @param con the con to set
 */
public void setCon(Connection con) 
    this.con = con;


/**
 * @return the stmt
 */
public Statement getStmt() 
    return stmt;


/**
 * @param stmt the stmt to set
 */
public void setStmt(Statement stmt) 
    this.stmt = stmt;


/**
 * @return the connectionEstablished
 */
public boolean isConnectionEstablished() 
    return connectionEstablished;


/**
 * @param connectionEstablished the connectionEstablished to set
 */
public void setConnectionEstablished(boolean connectionEstablished) 
    this.connectionEstablished = connectionEstablished;


/**
 * @return the rsmd
 */
public ResultSetMetaData getRsmd() 
    return rsmd;


public ResultSetMetaData getMetaData() 
    return rsmd;


/**
 * @param rsmd the rsmd to set
 */
public void setRsmd(ResultSetMetaData rsmd) 
    this.rsmd = rsmd;

    try 
        // we also set the Values for the JTable Headers
        int noCols = rsmd.getColumnCount();

        // and now we set the Column Headers and the fieldNames
        columnNames = new String[noCols];
        fieldNames = new String[noCols];
        columnTypes = new int[noCols];
        for (int i = 0; i < noCols; i++) 
            columnNames[i] = rsmd.getColumnLabel(i + 1);
            fieldNames[i] = rsmd.getColumnName(i + 1);
            columnTypes[i] = rsmd.getColumnType(i + 1);
        

     catch (SQLException sqlex) 
        logSqlException("setRsmd(ResultSetMetaData rsmd", Level.WARNING, sqlex);
    



/**
 * @return the counter
 */
public int getCounter() 
    return counter;


/**
 * @param counter the counter to set
 */
public void setCounter(int counter) 
    this.counter = counter;


/**
 * @return the standalone
 */
public boolean isStandalone() 
    return standalone;


/**
 * @param standalone the standalone to set
 */
public void setStandalone(boolean standalone) 
    this.standalone = standalone;


/**
 * @return the SQLError
 */
public String getSQLError() 
    return SQLError;


/**
 * @param SQLError the SQLError to set
 */
public void setSQLError(String SQLError) 
    this.SQLError = SQLError;


/**
 * @return the maxRows
 */
public int getMaxRows() 
    return maxRows;


public int getMaxRowCount() 
    return maxRows;

/**
 * @param maxRows the maxRows to set
 */
public void setMaxRows(int maxRows) 
    this.maxRows = maxRows;


public void setMaxRowCount(int v) 
    this.maxRows = v;


/**
 * @return the nullTxt
 */
public String getNullTxt() 
    return nullTxt;


/**
 * @param nullTxt the nullTxt to set
 */
public void setNullTxt(String nullTxt) 
    this.nullTxt = nullTxt;


/**
 * @return the useNullTxt
 */
public boolean isUseNullTxt() 
    return useNullTxt;


/**
 * @param useNullTxt the useNullTxt to set
 */
public void setUseNullTxt(boolean useNullTxt) 
    this.useNullTxt = useNullTxt;



【讨论】:

以上是关于执行 jtable 显示异常的主要内容,如果未能解决你的问题,请参考以下文章

JTable运行的时候抛出NullPointerException的问题

使用 JTable 显示 ResultSet

无法显示 JTable

从oracle数据库显示JTable中的数据[重复]

根据查询更新JTable显示(转)

如何隐藏 Mac/OSX 拖放 JTable 选择框