• java数据库编程——读写LOB、可滚动和可更新的结果集、元数据


    java 数据库编程

    1. 读写LOB

      除了数字、字符串和日期之外,许多数据库还可以存储大对象,例如图片或其它数据。在SQL中,二进制大对象称为BLOB,字符型大对象称为CLOB。

      要读取LOB,需要执行SELECT语句,然后在ResultSet上调用getBlob或getClob方法,这样就可以获得Blob或Clob类型的对象。要从Blob中获取二进制数据,可以调用getBytes或getInputStream。例如,如果你有一张保存图书封面图形的表,那么就可以像下面这样获取一张图像:

    PreparedStatement stat = conn.prepareStatement("SELECT Cover FROM BookCovers WHERE ISBN=?");
    stat.set(1, isbn);
    ResultSet result = stat.executeQuery();
    if(result.next()){
        Blob coverBlob = result.getBlob(1);
        Image coverImage = ImageIO.read(coverBlob.getBinaryStream());
    }

      类似地,如果获取了Clob对象,那么就可以通过调用getSubString或getCharacterStream方法来获取其中的字符数据。

      要将LOB置于数据库中,需要在Connection对象上调用createBlob或createClob,然后获取一个用于该LOB的输出流或写出器,写出数据,并将该对象存储到数据库中。例如,下面展示了如何存储一张图像:

    Blob coverBlob = connection.createBlob();
    int offset = 0;
    OutputStream out = coverBlob.setBinaryStream(offset);
    ImageIO.write(coverImage, "PNG", out);
    PreparedStatement stat = conn.prepareStatement("INSERT INTO Cover VALUES(?, ?)");
    stat.set(1, isbn);
    stat.set(2,coverBlob);
    stat.executeUpdate();

     2. 可滚动和可更新的结果集

      要让ResultSet可以滚动个和更新,必须在创建Statement对象的时候使用下面的方式指定对应的参数:

    Statement stmt = conn.createStatement(type, concurrency);

      对于PreparedStatement,使用下面的方式指定参数:

    PreparedStatement pstmt = conn.prepareStatement(sql, type, concurrency);

    其中,type表示ResuleSet的类型,而concurrency表示是否可以使用ResuleSet来更新数据库。

    type和concurrency的取值以及含义如下:

    ResultSet类的type值
    解释
    ResultSet.TYPE_FORWARD_ONLY 结果集不能滚动(默认值)
    ResultSet.TYPE_SCROLL_INSENSITIVE 结果集可以滚动,但ResuleSet对数据库中数据变化不敏感
     ResultSet.TYPE_SCROLL_SENSIT  IVE 结果集可以滚动,并且ResuleSet对数据库中发生的改变敏感
    ResultSet类的Concurrency值
    解释
    ResultSet.CONCUR_READ_ONLY 结果集不能用于更新数据库(默认值)
    ResultSet.CONCUR_UPDATABLE 结果集可以用于更新数据库

    JDBC的结果集有很多类型。这些结果集有不同的特性,以满足各种需要。这在高性能的JDBC数据操作中有着重要应用。下面是一个应用实例:

    package lavasoft.common; 
    
    import java.sql.Connection; 
    import java.sql.ResultSet; 
    import java.sql.SQLException; 
    import java.sql.Statement; 
    
    /** 
    * JDBC可滚动可更新感知更新结果集测试 
    * 
    * @author leizhimin 2009-12-8 20:09:03 
    */ 
    public class TestResultSet { 
            public static void main(String[] args) { 
                    testScrollResultSet(); 
                    testUpdateResultSet(); 
            } 
    
            /** 
             * 可更新结果集更新测试 
             */ 
            public static void testUpdateResultSet() { 
                    Connection conn = DBToolkit.getConnection(); 
                    String sql = "SELECT * FROM book"; 
                    try { 
                            Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); 
                            ResultSet rs = stmt.executeQuery(sql); 
    
                            System.out.println("---------原结果集--------"); 
                            while (rs.next()) { 
                                    System.out.println("[行号:" + rs.getRow() + "]	" + rs.getString(1) + "	" + rs.getString(2) + "	" + rs.getString(3)); 
                            } 
    
                            System.out.println("---------插入一条记录--------"); 
                            rs.first(); 
                            //将光标移动到插入行上 
                            rs.moveToInsertRow(); 
                            //构建行数据 
                            rs.updateString(2, "xxxx"); 
                            rs.updateString(3, "x"); 
                            //插入一行 
                            rs.insertRow(); 
    
                            System.out.println("-------------更新一条记录-------------"); 
                            rs.absolute(3); 
                            //构建行数据 
                            rs.updateString(2, "uuuu"); 
                            rs.updateString(3, "u"); 
                            rs.updateRow(); 
    
                            System.out.println("---------插入更新后的结果集--------"); 
                            rs = stmt.executeQuery(sql); 
                            while (rs.next()) { 
                                    System.out.println("[行号:" + rs.getRow() + "]	" + rs.getString(1) + "	" + rs.getString(2) + "	" + rs.getString(3)); 
                            } 
                            rs.close(); 
                            stmt.close(); 
                    } catch (SQLException e) { 
                            e.printStackTrace(); 
                    } finally { 
                            DBToolkit.closeConnection(conn); 
                    } 
            } 
    
            /** 
             * 可滚动结果集滚动测试 
             */ 
            public static void testScrollResultSet() { 
                    Connection conn = DBToolkit.getConnection(); 
                    String sql = "SELECT * FROM book"; 
                    try { 
                            Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); 
                            ResultSet rs = stmt.executeQuery(sql); 
                            while (rs.next()) { 
                                    System.out.println("[行号:" + rs.getRow() + "]	" + rs.getString(1) + "	" + rs.getString(2) + "	" + rs.getString(3)); 
                            } 
    
                            System.out.println("------前滚操作-----"); 
                            //将光标移动到此 ResultSet 对象的上一行 
                            rs.previous(); 
                            rs.previous(); 
                            System.out.println("[行号:" + rs.getRow() + "]	" + rs.getString(1) + "	" + rs.getString(2) + "	" + rs.getString(3)); 
    
                            System.out.println("------绝对定位-----"); 
                            //将光标移动到此 ResultSet 对象的给定行编号。 
                            rs.absolute(3); 
                            System.out.println("[行号:" + rs.getRow() + "]	" + rs.getString(1) + "	" + rs.getString(2) + "	" + rs.getString(3)); 
    
                            System.out.println("------移动到第一行-----"); 
                            //将光标移动到此 ResultSet 对象的第一行。 
                            if (rs.first()) { 
                                    System.out.println("[行号:" + rs.getRow() + "]	" + rs.getString(1) + "	" + rs.getString(2) + "	" + rs.getString(3)); 
                            } 
    
                            System.out.println("------移动到最后一行-----"); 
                            //将光标移动到此 ResultSet 对象的第一行。 
                            if (rs.last()) { 
                                    System.out.println("[行号:" + rs.getRow() + "]	" + rs.getString(1) + "	" + rs.getString(2) + "	" + rs.getString(3)); 
                            } 
    
                            System.out.println("------移动到第一行之前-----"); 
                            //将光标移动到此 ResultSet 对象的开头,正好位于第一行之前 
                            rs.beforeFirst(); 
                            rs.next(); 
                            System.out.println("[行号:" + rs.getRow() + "]	" + rs.getString(1) + "	" + rs.getString(2) + "	" + rs.getString(3)); 
    
                            System.out.println("------移动到最后一行之后-----"); 
                            //将光标移动到此 ResultSet 对象的末尾,正好位于最后一行之后。 
                            rs.afterLast(); 
                            rs.previous(); 
                            System.out.println("[行号:" + rs.getRow() + "]	" + rs.getString(1) + "	" + rs.getString(2) + "	" + rs.getString(3)); 
    
                            System.out.println("------相对当前行做移动-----"); 
                            rs.relative(-2); 
                            System.out.println("[行号:" + rs.getRow() + "]	" + rs.getString(1) + "	" + rs.getString(2) + "	" + rs.getString(3)); 
    
                            rs.close(); 
                            stmt.close(); 
                    } catch (SQLException e) { 
                            e.printStackTrace(); 
                    } finally { 
                            DBToolkit.closeConnection(conn); 
                    } 
            } 
    }
     

    控制台输出:

    [行号:1] 1 aaa a 
    [行号:2] 2 bbb b 
    [行号:3] 3 ccc c 
    [行号:4] 4 ddd d 
    [行号:5] 5 eee e 
    [行号:6] 6 fff f 
    [行号:7] 7 ggg g 
    [行号:8] 8 hhh h 
    ------前滚操作----- 
    [行号:7] 7 ggg g 
    ------绝对定位----- 
    [行号:3] 3 ccc c 
    ------移动到第一行----- 
    [行号:1] 1 aaa a 
    ------移动到最后一行----- 
    [行号:8] 8 hhh h 
    ------移动到第一行之前----- 
    [行号:1] 1 aaa a 
    ------移动到最后一行之后----- 
    [行号:8] 8 hhh h 
    ------相对当前行做移动----- 
    [行号:6] 6 fff f 
    ---------原结果集-------- 
    [行号:1] 1 aaa a 
    [行号:2] 2 bbb b 
    [行号:3] 3 ccc c 
    [行号:4] 4 ddd d 
    [行号:5] 5 eee e 
    [行号:6] 6 fff f 
    [行号:7] 7 ggg g 
    [行号:8] 8 hhh h 
    ---------插入一条记录-------- 
    -------------更新一条记录------------- 
    ---------插入更新后的结果集-------- 
    [行号:1] 1 aaa a 
    [行号:2] 2 bbb b 
    [行号:3] 3 uuuu u 
    [行号:4] 4 ddd d 
    [行号:5] 5 eee e 
    [行号:6] 6 fff f 
    [行号:7] 7 ggg g 
    [行号:8] 8 hhh h 
    [行号:9] 9 xxxx x
    
    Process finished with exit code 0

    可保存性:设置提交时候是否关闭结果集。

    ResultSet.HOLD_CURSORS_OVER_COMMIT :在提交后结果集还可用

    ResultSet.CLOSE_CURSORS_AT_COMMIT:在提交时候关闭结果集

    由于这些特性比较高级,不同数据库驱动对此实现也不一样。因此在使用JDBC高级特性的时候最好做个测试,以保证程序的可靠性。

    当type设置为:ResultSet.TYPE_SCROLL_INSENSITIVE 或者 ResultSet.TYPE_SCROLL_INSENSITIVE 时,游标可以移动,但是移动的位置是[1,count],记住并不是从0开始,否则会报错。

    既然可以移动,那么把移动的几个方法解释一下:

    rs = statement.executeQuery();  游标指向第一行前面的位置,这个位置是不能获取数据,否则报错:结果集没有当前行

    rs.next();  // 游标下移一个位置,如果所在位置有结果集那么返回true,否则返回false

    rs.previous(); // 游标上移一个位置,如果所在位置有结果集那么返回true,否则返回false

    rs.first(); //  游标指向第一行的位置

    rs.last(); //  游标指向最后一行的位置

    rs.beforeFirst(); // 游标指向第一行前面的位置 , 这个位置不能获取数据

    rs.afterLast(); //  游标指向最后一行后面的位置,这个位置不能获取数据

    rs.absolute(index); // 游标移动至index位置,index是[1,count]的任意数字,但是不能超出,否则报错 

    rs.relative(index); // 游标从当前位置算移动index个位置,也就是相对移动,index可以是负数,但是计算结果同样在[1,count]内

    isAfterLast(); // 判断游标是否在最后一行之后。

    isBeforeFirst();// 判断游标是否在第一行之前。

    ifFirst() ;  //判断游标是否指向结果集的第一行。

    isLast(); // 判断游标是否指向结果集的最后一行。

    getRow();// 得到当前游标所指向行的行号,行号从1开始,如果结果集没有行,返回0。

     3. 元数据

      元数据在SQL中是用来描述数据库或其组成部分的数据。我们可以获得三类元数据:关于数据库的元数据,关于结果集的元数据,关于预备语句参数的元数据。元数据是描述基本数据信息的数据,操作元数据的语法如下:
    DatabaseMetaData meta=conn.getMetaData();
    ResultSet mrs=meta.getTables(null,null,null,new String[]{"TABLE"});

    元数据结果集中第一列代表了表目录,第二列代表了表结构模式,第三列表名,第四列表类型,第五列关于表的注释。

      下面我们编写一个简单的数据库工具,通过使用元数据来浏览数据库中的所有表,该程序还展示了如何使用带缓存的行集。

    方法一:直接连接数据库,代码如下:

    package view;
    
    import java.awt.*;
    import java.awt.event.*;
    import java.io.*;
    import java.nio.file.*;
    import java.sql.*;
    import java.util.*;
    
    import javax.sql.*;
    import javax.sql.rowset.*;
    import javax.swing.*;
    
    /**
     * This program uses metadata to display arbitrary tables in a database.
     * 
     * @author DELL
     */
    public class ViewDB
    {
       public static void main(String[] args)
       {
          EventQueue.invokeLater(new Runnable()
             {
                public void run()
                {
                   JFrame frame = new ViewDBFrame();
                   frame.setTitle("ViewDB");
                   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                   frame.setVisible(true);
                }
             });
       }
    }
    
    /**
     * The frame that holds the data panel and the navigation buttons.
     */
    class ViewDBFrame extends JFrame
    {
       private JButton previousButton;
       private JButton nextButton;
       private JButton deleteButton;
       private JButton saveButton;
       private DataPanel dataPanel;
       private Component scrollPane;
       private JComboBox<String> tableNames;
       private Properties props;
       private CachedRowSet crs;
    
       public ViewDBFrame()
       {
          tableNames = new JComboBox<String>();
          tableNames.addActionListener(new ActionListener()
             {
                public void actionPerformed(ActionEvent event)
                {
                   showTable((String) tableNames.getSelectedItem());
                }
             });
          add(tableNames, BorderLayout.NORTH);
    
          try
          {
              Class.forName("com.mysql.jdbc.Driver");
              
    //         readDatabaseProperties();
             try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","1234"))
             {
                DatabaseMetaData meta = conn.getMetaData();
                ResultSet mrs = meta.getTables(null, null, null, new String[] { "TABLE" });
                while (mrs.next())
                   tableNames.addItem(mrs.getString(3));
             }
          }
          catch (SQLException e)
          {
             JOptionPane.showMessageDialog(this, e);
          } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    
          JPanel buttonPanel = new JPanel();
          add(buttonPanel, BorderLayout.SOUTH);
    
          previousButton = new JButton("Previous");
          previousButton.addActionListener(new ActionListener()
             {
                public void actionPerformed(ActionEvent event)
                {
                   showPreviousRow();
                }
             });
          buttonPanel.add(previousButton);
    
          nextButton = new JButton("Next");
          nextButton.addActionListener(new ActionListener()
             {
                public void actionPerformed(ActionEvent event)
                {
                   showNextRow();
                }
             });
          buttonPanel.add(nextButton);
    
          deleteButton = new JButton("Delete");
          deleteButton.addActionListener(new ActionListener()
             {
                public void actionPerformed(ActionEvent event)
                {
                   deleteRow();
                }
             });
          buttonPanel.add(deleteButton);
    
          saveButton = new JButton("Save");
          saveButton.addActionListener(new ActionListener()
             {
                public void actionPerformed(ActionEvent event)
                {
                   saveChanges();
                }
             });
          buttonPanel.add(saveButton);
          pack();
       }
    
       /**
        * Prepares the text fields for showing a new table, and shows the first row.
        * @param tableName the name of the table to display
        */
       public void showTable(String tableName)
       {
          try
          {
              Class.forName("com.mysql.jdbc.Driver");
             try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","1234"))
             {
                // get result set
                Statement stat = conn.createStatement();
                ResultSet result = stat.executeQuery("SELECT * FROM " + tableName);
                // copy into cached row set
                RowSetFactory factory = RowSetProvider.newFactory();            
                crs = factory.createCachedRowSet();
                crs.setTableName(tableName);
                crs.populate(result);            
             }
    
             if (scrollPane != null) remove(scrollPane);
             dataPanel = new DataPanel(crs);
             scrollPane = new JScrollPane(dataPanel);
             add(scrollPane, BorderLayout.CENTER);
             validate();
             showNextRow();
          }
          catch (SQLException e)
          {
             JOptionPane.showMessageDialog(this, e);
          } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       }
    
       /**
        * Moves to the previous table row.
        */
       public void showPreviousRow()
       {
          try
          {
             if (crs == null || crs.isFirst()) return;
             crs.previous();
             dataPanel.showRow(crs);
          }
          catch (SQLException e)
          {
             for (Throwable t : e)
                t.printStackTrace();
          }
       }
    
       /**
        * Moves to the next table row.
        */
       public void showNextRow()
       {
          try
          {
             if (crs == null || crs.isLast()) return;
             crs.next();
             dataPanel.showRow(crs);
          }
          catch (SQLException e)
          {
             JOptionPane.showMessageDialog(this, e);
          }
       }
    
       /**
        * Deletes current table row.
        */
       public void deleteRow()
       {
          try
          {
              Class.forName("com.mysql.jdbc.Driver");
             try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","1234"))
             {
                conn.setAutoCommit(false);
                crs.deleteRow();
                crs.acceptChanges(conn);
                if (crs.isAfterLast()) 
                   if (!crs.last()) crs = null;
                dataPanel.showRow(crs);
             }
          }
          catch (SQLException e)
          {
             JOptionPane.showMessageDialog(this, e);
          } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       }
    
       /**
        * Saves all changes.
        */
       public void saveChanges()
       {
          try
          {
              Class.forName("com.mysql.jdbc.Driver");
             try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","1234"))
             {
                conn.setAutoCommit(false);
                dataPanel.setRow(crs);
                crs.acceptChanges(conn);
             }
          }
          catch (SQLException e)
          {
             JOptionPane.showMessageDialog(this, e);
          } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       }
    
    //   private void readDatabaseProperties() throws IOException
    //   {
    //      props = new Properties();
    //      try (InputStream in = Files.newInputStream(Paths.get("database.properties")))
    //      {
    //         props.load(in);
    //      }
    //      String drivers = props.getProperty("jdbc.drivers");
    //      if (drivers != null) System.setProperty("jdbc.drivers", drivers);      
    //   }
       
       /**
        * Gets a connection from the properties specified in the file database.properties.
        * @return the database connection
        */
    //   private Connection getConnection() throws SQLException
    //   {
    //      String url = props.getProperty("jdbc.url");
    //      String username = props.getProperty("jdbc.username");
    //      String password = props.getProperty("jdbc.password");
    //
    //      return DriverManager.getConnection(url, username, password);
    //   }
    }
    
    /**
     * This panel displays the contents of a result set.
     */
    class DataPanel extends JPanel
    {
       private java.util.List<JTextField> fields;
    
       /**
        * Constructs the data panel.
        * @param rs the result set whose contents this panel displays
        */
       public DataPanel(RowSet rs) throws SQLException
       {
          fields = new ArrayList<>();
          setLayout(new GridBagLayout());
          GridBagConstraints gbc = new GridBagConstraints();
          gbc.gridwidth = 1;
          gbc.gridheight = 1;
    
          ResultSetMetaData rsmd = rs.getMetaData();
          for (int i = 1; i <= rsmd.getColumnCount(); i++)
          {
             gbc.gridy = i - 1;
    
             String columnName = rsmd.getColumnLabel(i);
             gbc.gridx = 0;
             gbc.anchor = GridBagConstraints.EAST;
             add(new JLabel(columnName), gbc);
    
             int columnWidth = rsmd.getColumnDisplaySize(i);
             JTextField tb = new JTextField(columnWidth);
             if (!rsmd.getColumnClassName(i).equals("java.lang.String"))
                tb.setEditable(false);
                   
             fields.add(tb);
    
             gbc.gridx = 1;
             gbc.anchor = GridBagConstraints.WEST;
             add(tb, gbc);
          }
       }
    
       /**
        * Shows a database row by populating all text fields with the column values.
        */
       public void showRow(ResultSet rs) throws SQLException
       {
          for (int i = 1; i <= fields.size(); i++)
          {
             String field = rs == null ? "" : rs.getString(i);
             JTextField tb = fields.get(i - 1);
             tb.setText(field);
          }
       }
       
       /**
        * Updates changed data into the current row of the row set.
        */
       public void setRow(RowSet rs) throws SQLException
       {
          for (int i = 1; i <= fields.size(); i++)
          {
             String field = rs.getString(i);
             JTextField tb = fields.get(i - 1);
             if (!field.equals(tb.getText()))
                rs.updateString(i, tb.getText());
          }
          rs.updateRow();
       }
    }

    方法二:使用database.properties配置文件,代码如下:

    package view;
    
    import java.awt.*;
    import java.awt.event.*;
    import java.io.*;
    import java.nio.file.*;
    import java.sql.*;
    import java.util.*;
    import javax.sql.*;
    import javax.sql.rowset.*;
    import javax.swing.*;
    
    /**
     * This program uses metadata to display arbitrary tables in a database.
     *
     * @author DELL
     */
    public class ViewDB
    {
       public static void main(String[] args)
       {
          EventQueue.invokeLater(new Runnable()
             {
                public void run()
                {
                   JFrame frame = new ViewDBFrame();
                   frame.setTitle("ViewDB");
                   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                   frame.setVisible(true);
                }
             });
       }
    }
    
    /**
     * The frame that holds the data panel and the navigation buttons.
     */
    class ViewDBFrame extends JFrame
    {
       private JButton previousButton;
       private JButton nextButton;
       private JButton deleteButton;
       private JButton saveButton;
       private DataPanel dataPanel;
       private Component scrollPane;
       private JComboBox<String> tableNames;
       private Properties props;
       private CachedRowSet crs;
    
       public ViewDBFrame()
       {
          tableNames = new JComboBox<String>();
          tableNames.addActionListener(new ActionListener()
             {
                public void actionPerformed(ActionEvent event)
                {
                   showTable((String) tableNames.getSelectedItem());
                }
             });
          add(tableNames, BorderLayout.NORTH);
    
          try
          {
             readDatabaseProperties();
             try (Connection conn = getConnection())
             {
                DatabaseMetaData meta = conn.getMetaData();
                ResultSet mrs = meta.getTables(null, null, null, new String[] { "TABLE" });
                while (mrs.next())
                   tableNames.addItem(mrs.getString(3));
             }
          }
          catch (SQLException e)
          {
             JOptionPane.showMessageDialog(this, e);
          }
          catch (IOException e)
          {
             JOptionPane.showMessageDialog(this, e);
          }
    
          JPanel buttonPanel = new JPanel();
          add(buttonPanel, BorderLayout.SOUTH);
    
          previousButton = new JButton("Previous");
          previousButton.addActionListener(new ActionListener()
             {
                public void actionPerformed(ActionEvent event)
                {
                   showPreviousRow();
                }
             });
          buttonPanel.add(previousButton);
    
          nextButton = new JButton("Next");
          nextButton.addActionListener(new ActionListener()
             {
                public void actionPerformed(ActionEvent event)
                {
                   showNextRow();
                }
             });
          buttonPanel.add(nextButton);
    
          deleteButton = new JButton("Delete");
          deleteButton.addActionListener(new ActionListener()
             {
                public void actionPerformed(ActionEvent event)
                {
                   deleteRow();
                }
             });
          buttonPanel.add(deleteButton);
    
          saveButton = new JButton("Save");
          saveButton.addActionListener(new ActionListener()
             {
                public void actionPerformed(ActionEvent event)
                {
                   saveChanges();
                }
             });
          buttonPanel.add(saveButton);
          pack();
       }
    
       /**
        * Prepares the text fields for showing a new table, and shows the first row.
        * @param tableName the name of the table to display
        */
       public void showTable(String tableName)
       {
          try
          {
             try (Connection conn = getConnection())
             {
                // get result set
                Statement stat = conn.createStatement();
                ResultSet result = stat.executeQuery("SELECT * FROM " + tableName);
                // copy into cached row set
                RowSetFactory factory = RowSetProvider.newFactory();            
                crs = factory.createCachedRowSet();
                crs.setTableName(tableName);
                crs.populate(result);            
             }
    
             if (scrollPane != null) remove(scrollPane);
             dataPanel = new DataPanel(crs);
             scrollPane = new JScrollPane(dataPanel);
             add(scrollPane, BorderLayout.CENTER);
             validate();
             showNextRow();
          }
          catch (SQLException e)
          {
             JOptionPane.showMessageDialog(this, e);
          }
       }
    
       /**
        * Moves to the previous table row.
        */
       public void showPreviousRow()
       {
          try
          {
             if (crs == null || crs.isFirst()) return;
             crs.previous();
             dataPanel.showRow(crs);
          }
          catch (SQLException e)
          {
             for (Throwable t : e)
                t.printStackTrace();
          }
       }
    
       /**
        * Moves to the next table row.
        */
       public void showNextRow()
       {
          try
          {
             if (crs == null || crs.isLast()) return;
             crs.next();
             dataPanel.showRow(crs);
          }
          catch (SQLException e)
          {
             JOptionPane.showMessageDialog(this, e);
          }
       }
    
       /**
        * Deletes current table row.
        */
       public void deleteRow()
       {
          try
          {
             try (Connection conn = getConnection())
             {
                conn.setAutoCommit(false);
                crs.deleteRow();
                crs.acceptChanges(conn);
                if (crs.isAfterLast()) 
                   if (!crs.last()) crs = null;
                dataPanel.showRow(crs);
             }
          }
          catch (SQLException e)
          {
             JOptionPane.showMessageDialog(this, e);
          }
       }
    
       /**
        * Saves all changes.
        */
       public void saveChanges()
       {
          try
          {
             try (Connection conn = getConnection())
             {
                conn.setAutoCommit(false);
                dataPanel.setRow(crs);
                crs.acceptChanges(conn);
             }
          }
          catch (SQLException e)
          {
             JOptionPane.showMessageDialog(this, e);
          }
       }
    
       private void readDatabaseProperties() throws IOException
       {
          props = new Properties();
          try (InputStream in = Files.newInputStream(Paths.get("database.properties")))
          {
             props.load(in);
          }
          String drivers = props.getProperty("jdbc.drivers");
          if (drivers != null) System.setProperty("jdbc.drivers", drivers);      
       }
       
       /**
        * Gets a connection from the properties specified in the file database.properties.
        * @return the database connection
        */
       private Connection getConnection() throws SQLException
       {
          String url = props.getProperty("jdbc.url");
          String username = props.getProperty("jdbc.username");
          String password = props.getProperty("jdbc.password");
    
          return DriverManager.getConnection(url, username, password);
       }
    }
    
    /**
     * This panel displays the contents of a result set.
     */
    class DataPanel extends JPanel
    {
       private java.util.List<JTextField> fields;
    
       /**
        * Constructs the data panel.
        * @param rs the result set whose contents this panel displays
        */
       public DataPanel(RowSet rs) throws SQLException
       {
          fields = new ArrayList<>();
          setLayout(new GridBagLayout());
          GridBagConstraints gbc = new GridBagConstraints();
          gbc.gridwidth = 1;
          gbc.gridheight = 1;
    
          ResultSetMetaData rsmd = rs.getMetaData();
          for (int i = 1; i <= rsmd.getColumnCount(); i++)
          {
             gbc.gridy = i - 1;
    
             String columnName = rsmd.getColumnLabel(i);
             gbc.gridx = 0;
             gbc.anchor = GridBagConstraints.EAST;
             add(new JLabel(columnName), gbc);
    
             int columnWidth = rsmd.getColumnDisplaySize(i);
             JTextField tb = new JTextField(columnWidth);
             if (!rsmd.getColumnClassName(i).equals("java.lang.String"))
                tb.setEditable(false);
                   
             fields.add(tb);
    
             gbc.gridx = 1;
             gbc.anchor = GridBagConstraints.WEST;
             add(tb, gbc);
          }
       }
    
       /**
        * Shows a database row by populating all text fields with the column values.
        */
       public void showRow(ResultSet rs) throws SQLException
       {
          for (int i = 1; i <= fields.size(); i++)
          {
             String field = rs == null ? "" : rs.getString(i);
             JTextField tb = fields.get(i - 1);
             tb.setText(field);
          }
       }
       
       /**
        * Updates changed data into the current row of the row set.
        */
       public void setRow(RowSet rs) throws SQLException
       {
          for (int i = 1; i <= fields.size(); i++)
          {
             String field = rs.getString(i);
             JTextField tb = fields.get(i - 1);
             if (!field.equals(tb.getText()))
                rs.updateString(i, tb.getText());
          }
          rs.updateRow();
       }
    }

    项目目录结构如下:

    其中database.properties的内容如下:

    1 #jdbc.drivers=com.mysql.jdbc.Driver
    2 jdbc.url=jdbc:mysql://localhost:3306/test
    3 jdbc.username=root
    4 jdbc.password=1234

    程序运行结果如下:

  • 相关阅读:
    django继承User表导致的问题
    Sublime Text 3 鼠标右键快捷选项 简单且高效
    php所有版本
    windows 安装redis
    php玩弄redis基本操作
    PHP 实现文件下载
    PHP 获取客户端的真实IP
    根据标签内个数,显示隐藏《加载更多》
    ubuntu 安装nginx+php+mysql+phpadmin环境
    面试总结
  • 原文地址:https://www.cnblogs.com/gaopeng527/p/4530168.html
Copyright © 2020-2023  润新知