67、SQL数据库操作与Java应用实践

SQL数据库操作与Java应用实践

在数据库操作中,我们常常需要创建、删除表,甚至创建新的数据库。同时,对于查询结果的处理和展示也是重要的环节。下面将详细介绍相关的操作和技术。

1. 创建和删除表

在SQL中,我们可以使用 CREATE TABLE 语句来创建数据库表,使用 DROP TABLE 语句来删除表。

1.1 创建表的一般格式
CREATE TABLE TableName
   (ColumnName1 DataType1,
   ColumnName2 DataType2,
   etc... )

例如,创建一个名为 Customer 的表:

CREATE TABLE Customer
   ( Name CHAR(25),
     Address CHAR(25),
     City CHAR(12),
     State CHAR(2),
     Zip CHAR(5) )

如果需要指定某一列为主键,可以在列的数据类型后添加 PRIMARY KEY 限定符,同时建议使用 NOT NULL 限定符,确保该列每一行都有值。例如:

CREATE TABLE Customer
   ( CustomerNumber CHAR(10) NOT NULL PRIMARY KEY,
     Name CHAR(25),
     Address CHAR(25),
     City CHAR(12),
     State CHAR(2),
     Zip CHAR(5) )

以下是一个Java程序示例,用于在 CoffeeDB 数据库中创建 Customer 表并插入数据:

import java.sql.*;     // Needed for JDBC classes

/**
 * This program creates a Customer
 * table in the CoffeeDB database.
 */
public class CreateCustomerTable
{
    public static void main(String[] args)
    {
        // Create a named constant for the URL.
        // NOTE: This value is specific for Java DB.
        final String DB_URL = "jdbc:derby:CoffeeDB";

        try
        {
            // Create a connection to the database.
            Connection conn = DriverManager.getConnection(DB_URL);

            // Get a Statement object.
            Statement stmt = conn.createStatement();

            // Make an SQL statement to create the table.
            String sql = "CREATE TABLE Customer" +
                    "( CustomerNumber CHAR(10) NOT NULL PRIMARY KEY, " +
                    " Name CHAR(25)," +
                    " Address CHAR(25)," +
                    " City CHAR(12)," +
                    " State CHAR(2)," +
                    " Zip CHAR(5) )";

            // Execute the statement.
            stmt.execute(sql);

            // Add some rows to the new table.
            sql = "INSERT INTO Customer VALUES" +
                    "('101', 'Downtown Cafe', '17 N. Main Street'," +
                    " 'Asheville', 'NC', '55515')";
            stmt.executeUpdate(sql);

            sql = "INSERT INTO Customer VALUES" +
                    "('102', 'Main Street Grocery'," +
                    " '110 E. Main Street'," +
                    " 'Canton', 'NC', '55555')";
            stmt.executeUpdate(sql);

            sql = "INSERT INTO Customer VALUES" +
                    "('103', 'The Coffee Place', '101 Center Plaza'," +
                    " 'Waynesville', 'NC', '55516')";
            stmt.executeUpdate(sql);

            // Close the connection.
            conn.close();
        }
        catch (Exception ex)
        {
            System.out.println("ERROR: " + ex.getMessage());
        }
    }
}

插入到 Customer 表的数据如下:
| CustomerNumber | Name | Address | City | State | Zip |
| — | — | — | — | — | — |
| 101 | Downtown Cafe | 17 N. Main Street | Asheville | NC | 55515 |
| 102 | Main Street Grocery | 110 E. Main Street | Canton | NC | 55555 |
| 103 | The Coffee Place | 101 Center Plaza | Waynesville | NC | 55516 |

1.2 删除表

如果需要从数据库中删除表,可以使用 DROP TABLE 语句,其一般格式为:

DROP TABLE TableName

例如,删除 Customer 表的语句为:

DROP TABLE Customer
2. 创建新数据库

使用JDBC创建新数据库非常简单,只需在数据库URL中添加 ;create=true 属性,然后使用SQL创建表即可。

例如,创建一个名为 EntertainmentDB 的新数据库,用于存储DVD收藏数据,Java代码如下:

import java.sql.*;

/**
 * This program shows how to create a new database
 * using Java DB.
 */
public class BuildEntertainmentDB
{
    public static void main(String[] args)
            throws Exception
    {
        final String DB_URL =
                "jdbc:derby:EntertainmentDB;create=true";

        try
        {
            // Create a connection to the database.
            Connection conn =
                    DriverManager.getConnection(DB_URL);

            // Create a Statement object.
            Statement stmt = conn.createStatement();

            // Create the Dvd table.
            System.out.println("Creating the Dvd table...");
            stmt.execute("CREATE TABLE Dvd (" +
                    "Title CHAR(25), " +
                    "Minutes INTEGER, " +
                    "Price DOUBLE)");

            // Close the resources.
            stmt.close();
            conn.close();
            System.out.println("Done");
        }
        catch(Exception ex)
        {
            System.out.println("ERROR: " + ex.getMessage());
        }
    }
}

当运行该程序时,由于数据库URL中包含 ;create=true 属性,程序会创建 EntertainmentDB 数据库,然后创建 Dvd 表。

3. 可滚动结果集

默认情况下, ResultSet 对象只能向前移动游标,一旦游标移动过某一行,就无法再向后移动读取该行。如果需要向后移动游标,可以创建可滚动结果集。

创建可滚动结果集时,需要使用 Connection 对象的 createStatement 方法的重载版本,该方法接受两个参数:
- 第一个参数指定结果集的滚动类型,可使用以下常量:
- ResultSet.TYPE_FORWARD_ONLY :默认滚动类型,游标只能向前移动。
- ResultSet.TYPE_SCROLL_INSENSITIVE :结果集可滚动,游标可前后移动,且对数据库的更改不敏感。
- ResultSet.TYPE_SCROLL_SENSITIVE :结果集可滚动,游标可前后移动,且对数据库的更改敏感。
- 第二个参数指定结果集的并发级别,可使用以下常量:
- ResultSet.CONCUR_READ_ONLY :默认并发级别,结果集为只读,不能通过更改结果集内容来修改数据库。
- ResultSet.CONCUR_UPDATEABLE :结果集可更新,可对结果集进行更改并保存到数据库。

示例代码如下:

Statement stmt =
    conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
                         ResultSet.CONCUR_READ_ONLY);

创建可滚动结果集后,可以使用以下 ResultSet 方法移动游标:
- first() :将游标移动到结果集的第一行。
- last() :将游标移动到结果集的最后一行。
- next() :将游标移动到结果集的下一行。
- previous() :将游标移动到结果集的上一行。
- relative(rows) :相对于当前行,将游标移动指定的行数。例如, relative(2) 将游标向前移动2行, relative(-1) 将游标向后移动1行。
- absolute(row) :将游标移动到指定的行,行号从1开始。例如, absolute(1) 将游标移动到结果集的第一行。

以下代码展示了如何使用这些方法确定结果集中的行数:

resultSet.last();                 // Move to the last row
int numRows = resultSet.getRow(); // Get the current row number
resultSet.first();                // Move back to the first row
4. 结果集元数据

结果集元数据描述了结果集的内容,可用于确定执行未知查询时返回的列。通过 ResultSet 对象的 getMetaData 方法可以获取 ResultSetMetaData 对象。

ResultSetMetaData 接口提供了许多方法,部分方法如下表所示:
| 方法 | 描述 |
| — | — |
| int getColumnCount() | 返回结果集中的列数 |
| String getColumnName(int col) | 返回指定列的名称,列号从1开始 |
| String getColumnTypeName(int col) | 返回指定列的数据类型名称,列号从1开始 |
| int getColumnDisplaySize(int col) | 返回指定列的显示宽度,列号从1开始 |
| String getTableName(int col) | 返回与指定列关联的表名,列号从1开始 |

以下Java程序演示了如何使用元数据:

import java.sql.*;
import java.util.Scanner;

/**
 * This program demonstrates result set metadata.
 */
public class MetaDataDemo
{
    public static void main(String[] args) throws Exception
    {
        // Create a named constant for the URL.
        // NOTE: This value is specific for Java DB.
        final String DB_URL = "jdbc:derby:CoffeeDB";

        try
        {
            // Create a Scanner object for keyboard input.
            Scanner keyboard = new Scanner(System.in);

            // Get a SELECT statement from the user.
            System.out.println("Enter a SELECT statement for " +
                    "the CoffeeDB database:");
            String sql = keyboard.nextLine();

            // Create a connection to the database.
            Connection conn =
                    DriverManager.getConnection(DB_URL);

            // Create a Statement object.
            Statement stmt = conn.createStatement();

            // Execute the query.
            ResultSet resultSet = stmt.executeQuery(sql);

            // Get the result set metadata.
            ResultSetMetaData meta = resultSet.getMetaData();

            // Display the number of columns returned.
            System.out.println("The result set has " +
                    meta.getColumnCount() +
                    " column(s).");

            // Display the column names and types.
            for (int i = 1; i <= meta.getColumnCount(); i++)
            {
                System.out.println(meta.getColumnName(i) + ", " +
                        meta.getColumnTypeName(i));
            }

            // Display the contents of the rows.
            System.out.println("\nHere are the result set rows:");
            while (resultSet.next())
            {
                // Display a row.
                for (int i = 1; i <= meta.getColumnCount(); i++)
                {
                    System.out.print(resultSet.getString(i));
                }
                System.out.println();
            }

            // Close the statement and the connection.
            stmt.close();
            conn.close();
        }
        catch(Exception ex)
        {
            System.out.println("ERROR: " + ex.getMessage());
        }
    }
}

通过上述内容,我们了解了数据库表的创建、删除,新数据库的创建,可滚动结果集的使用以及结果集元数据的获取和应用。这些技术在数据库操作和Java应用开发中非常实用。

SQL数据库操作与Java应用实践(下半部分)

5. 在JTable中显示查询结果

JTable 是Swing类,可用于在GUI应用程序中显示表格数据,非常适合显示数据库查询结果。

5.1 JTable的基本使用

JTable 类有多个构造函数,常用的构造函数格式为:

JTable(Object[][] rowData, Object[] colNames)
  • rowData :二维对象数组,包含要显示在表格中的数据,数组中的每一行对应表格中的一行,每一列对应表格中的一列。
  • colNames :一维对象数组,包含要显示的列名。

以下是一个简单的 JTable 组件设置示例:

String[] colNames = {"Name", "Telephone" };
String[][] rowData = {{ "Jean",  "555-2222" },
                      { "Tim",   "555-1212" },
                      { "Matt",  "555-9999" },
                      { "Rose",  "555-4545" },
                      { "Geri",  "555-5214" },
                      { "Shawn", "555-7821" },
                      { "Renee", "555-9640" },
                      { "Joe",   "555-8657" } };
JTable myTable = new JTable(rowData, colNames);
JScrollPane scrollPane = new JScrollPane(myTable);

在上述代码中, colNames 数组包含列名, rowData 数组包含要显示在表格中的数据。创建 JTable 对象后,将其添加到 JScrollPane 对象中。

5.2 使用JTable显示数据库查询结果

为了使用 JTable 显示数据库查询结果,我们将使用三个类: TableFormatter CoffeeDBQuery CoffeeDBViewer

  • TableFormatter类 :继承自 JFrame ,用于显示填充好数据的 JTable
import javax.swing.*;
import java.awt.*;

/**
 * The TableFormatter class displays a populated JTable.
 */
public class TableFormatter extends JFrame
{
    // Constants for size.
    private final int WIDTH = 400;
    private final int HEIGHT = 200;

    /**
     * Constructor
     */
    public TableFormatter(Object[][] data, Object[] colNames)
    {
        // Specify an action for the close button.
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        // Create a JTable with the results.
        JTable table = new JTable(data, colNames);

        // Put the table in a scroll pane.
        JScrollPane scrollPane = new JScrollPane(table);

        // Add the table to the content pane.
        add(scrollPane, BorderLayout.CENTER);

        // Set the size and display.
        setSize(WIDTH, HEIGHT);
        setVisible(true);
    }
}

该类的构造函数接受二维对象数组 data 和一维对象数组 colNames ,用于创建 JTable 并显示在 JFrame 中。

  • CoffeeDBQuery类 :用于执行对 CoffeeDB 数据库的查询,并通过访问器方法提供结果集数据和列名。
import java.sql.*;

/**
 * This class executes queries on the CoffeeDB database
 * and provides the results in arrays.
 */
public class CoffeeDBQuery
{
    // Database URL Constant
    public final String DB_URL =
            "jdbc:derby:CoffeeDB";

    private Connection conn;      // Database connection
    private String[][] tableData; // Table data
    private String[] colNames;    // Column names

    /**
     * Constructor
     */
    public CoffeeDBQuery(String query)
    {
        // Get a connection to the database.
        getDatabaseConnection();

        try
        {
            // Create a Statement object for the query.
            Statement stmt =
                    conn.createStatement(
                            ResultSet.TYPE_SCROLL_INSENSITIVE,
                            ResultSet.CONCUR_READ_ONLY);

            // Execute the query.
            ResultSet resultSet =
                    stmt.executeQuery(query);

            // Get the number of rows.
            resultSet.last();                 // Move to last row
            int numRows = resultSet.getRow(); // Get row number
            resultSet.first();                // Move to first row

            // Get a metadata object for the result set.
            ResultSetMetaData meta = resultSet.getMetaData();

            // Create an array of Strings for the column names.
            colNames = new String[meta.getColumnCount()];

            // Store the column names in the colNames array.
            for (int i = 0; i < meta.getColumnCount(); i++)
            {
                // Get a column name.
                colNames[i] = meta.getColumnLabel(i+1);
            }

            // Create a 2D String array for the table data.
            tableData =
                    new String[numRows][meta.getColumnCount()];

            // Store the columns in the tableData array.
            for (int row = 0; row < numRows; row++)
            {
                for (int col = 0; col < meta.getColumnCount(); col++)
                {
                    tableData[row][col] = resultSet.getString(col + 1);
                }

                // Go to the next row in the ResultSet.
                resultSet.next();
            }

            // Close the statement and connection objects.
            stmt.close();
            conn.close();
        }
        catch (SQLException ex)
        {
            ex.printStackTrace();
        }
    }

    /**
     * The getDatabaseConnection method loads the JDBC
     * and gets a connection to the database.
     */
    private void getDatabaseConnection()
    {
        try
        {
            // Create a connection to the database.
            conn = DriverManager.getConnection(DB_URL);
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            System.exit(0);
        }
    }

    /**
     * The getColumnNames method returns the column names.
     */
    public String[] getColumnNames()
    {
        return colNames;
    }

    /**
     * The getTableData method returns the table data.
     */
    public String[][] getTableData()
    {
        return tableData;
    }
}

该类的构造函数接受一个SQL查询字符串,执行查询并将结果存储在 tableData colNames 数组中,同时提供访问这些数组的方法。

  • CoffeeDBViewer类 :允许用户输入任何 SELECT 语句,并在 TableFormatter 类的实例中显示查询结果。
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

/**
 * The CoffeeDBViewer class is a simple database viewer for
 * the CoffeeDB database.
 */
public class CoffeeDBViewer extends JFrame
{
    JPanel queryPanel;       // A panel to hold the query
    JPanel buttonPanel;      // A panel to hold the buttons
    JTextArea queryTextArea; // The user enters a query here
    JButton submitButton;    // To submit a query
    JButton exitButton;      // To quit the application

    /**
     * Constructor
     */
    public CoffeeDBViewer()
    {
        // Set the window title.
        setTitle("CoffeeDB Viewer");

        // Specify an action for the close button.
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // Build the Query Panel.
        buildQueryPanel();

        // Build the Button Panel.
        buildButtonPanel();

        // Add the panels to the content pane.
        add(queryPanel, BorderLayout.NORTH);
        add(buttonPanel, BorderLayout.SOUTH);

        // Pack and display.
        pack();
        setVisible(true);
    }

    /**
     * The buildQueryPanel method builds a panel to hold the
     * text area that the user will enter a query into.
     */
    private void buildQueryPanel()
    {
        // Create a panel.
        queryPanel = new JPanel();

        // Create a text area, 8 rows by 50 columns.
        queryTextArea = new JTextArea(8, 50);

        // Turn line wrapping on.
        queryTextArea.setLineWrap(true);

        // Add a scroll pane to the text area.
        JScrollPane qaScrollPane =
                new JScrollPane(queryTextArea);
        qaScrollPane.setHorizontalScrollBarPolicy(
                JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        qaScrollPane.setVerticalScrollBarPolicy(
                JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);

        // Add the text area to the panel.
        queryPanel.add(qaScrollPane);
    }

    /**
     * The buildButtonPanel method builds a panel
     * to hold the Submit and Exit buttons.
     */
    private void buildButtonPanel()
    {
        // Create a panel.
        buttonPanel = new JPanel();

        // Create the Submit button.
        submitButton = new JButton("Submit");

        // Register an action listener for the Submit button.
        submitButton.addActionListener(new SubmitButtonListener());

        // Create the Exit button.
        exitButton = new JButton("Exit");

        // Register an action listener for the Exit button.
        exitButton.addActionListener(new ExitButtonListener());

        // Add the two buttons to the panel.
        buttonPanel.add(submitButton);
        buttonPanel.add(exitButton);
    }

    /**
     * The SubmitButtonListener class is an action listener
     * for the Submit button.
     */
    private class SubmitButtonListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            // Get the user's statement.
            String userStatement = queryTextArea.getText();

            // Qualify that it is a SELECT statement.
            if (userStatement.trim().toUpperCase()
                    .startsWith("SELECT"))
            {
                // Create a CoffeeDBQuery object for the query.
                CoffeeDBQuery dbQuery =
                        new CoffeeDBQuery(userStatement);

                // Get the column names.
                String[] colNames = dbQuery.getColumnNames();

                // Get the table data.
                String[][] data = dbQuery.getTableData();

                // Display the results in a table.
                TableFormatter table =
                        new TableFormatter(data, colNames);
            }
            else
            {
                JOptionPane.showMessageDialog(null,
                        "Only enter SELECT statements.");
            }
        }
    }

    /**
     * The ExitButtonListener class is an action listener
     * for the Exit button.
     */
    private class ExitButtonListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            // End the application.
            System.exit(0);
        }
    }

    /**
     * The main method creates an instance of the class.
     */
    public static void main(String[] args)
    {
        new CoffeeDBViewer();
    }
}

该类创建一个 JFrame ,包含一个文本区域用于用户输入 SELECT 语句,以及“Submit”和“Exit”按钮。当用户点击“Submit”按钮时,程序会检查输入的语句是否为 SELECT 语句,如果是则执行查询并在 TableFormatter 中显示结果;点击“Exit”按钮则退出应用程序。

6. 总结

通过上述内容,我们全面了解了数据库操作和Java应用开发中的多个重要技术:
- 学会了使用SQL的 CREATE TABLE DROP TABLE 语句进行数据库表的创建和删除。
- 掌握了使用JDBC创建新数据库的方法,只需在数据库URL中添加 ;create=true 属性。
- 了解了可滚动结果集的使用,通过设置滚动类型和并发级别,实现游标在结果集中的前后移动。
- 掌握了结果集元数据的获取和应用,可通过 ResultSetMetaData 对象获取结果集的列数、列名、数据类型等信息。
- 学会了使用 JTable 在GUI应用程序中显示数据库查询结果,通过 TableFormatter CoffeeDBQuery CoffeeDBViewer 三个类实现了一个简单的数据库查询结果显示应用程序。

这些技术在实际的数据库操作和Java应用开发中具有重要的应用价值,能够帮助开发者更高效地处理和展示数据库数据。

下面是一个简单的流程图,展示了 CoffeeDBViewer 应用程序的工作流程:

graph TD;
    A[启动CoffeeDBViewer应用程序] --> B[用户输入SELECT语句];
    B --> C{是否为SELECT语句};
    C -- 是 --> D[创建CoffeeDBQuery对象执行查询];
    D --> E[获取查询结果的列名和数据];
    E --> F[创建TableFormatter对象显示结果];
    C -- 否 --> G[显示错误提示];

通过这个流程图,我们可以更清晰地看到 CoffeeDBViewer 应用程序的执行流程,帮助我们更好地理解和使用这些技术。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值