杰瑞科技汇

Java如何向MySQL高效执行insert语句?

Of course! Here is a comprehensive guide on how to insert data into a MySQL database from a Java application, covering the best practices with modern JDBC.

Java如何向MySQL高效执行insert语句?-图1
(图片来源网络,侵删)

We'll cover:

  1. The Basic Approach (The "Old" Way): Good for understanding the fundamentals.
  2. The Modern Approach (Recommended): Using PreparedStatement to prevent SQL injection and improve performance.
  3. Using a Connection Pool: Essential for any real-world application.
  4. Complete, Runnable Example: A full Java program you can adapt and run.

Prerequisites

  1. MySQL Server: Installed and running.

  2. A Database and Table: Let's create a simple one.

    -- Create a database if it doesn't exist
    CREATE DATABASE IF NOT EXISTS my_company;
    -- Use the new database
    USE my_company;
    -- Create an 'employees' table
    CREATE TABLE IF NOT EXISTS employees (
        id INT AUTO_INCREMENT PRIMARY KEY,
        first_name VARCHAR(50) NOT NULL,
        last_name VARCHAR(50) NOT NULL,
        email VARCHAR(100) UNIQUE NOT NULL,
        hire_date DATE NOT NULL
    );
  3. MySQL JDBC Driver: You need the JAR file. The easiest way to manage dependencies is with a build tool like Maven or Gradle.

    Java如何向MySQL高效执行insert语句?-图2
    (图片来源网络,侵删)

Using Maven (Recommended)

Add this dependency to your pom.xml file. The version 0.33 is an example; check for the latest version on the MySQL Connector/J Maven Repository.

<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>8.0.33</version>
</dependency>

The Basic Approach (String Concatenation)

This method involves building the SQL query by concatenating strings. This is highly discouraged because it makes your application vulnerable to SQL Injection attacks.

String url = "jdbc:mysql://localhost:3306/my_company";
String user = "root";
String password = "your_password";
String firstName = "John";
String lastName = "Doe";
String email = "john.doe@example.com";
String hireDate = "2025-10-27";
String sql = "INSERT INTO employees (first_name, last_name, email, hire_date) " +
             "VALUES ('" + firstName + "', '" + lastName + "', '" + email + "', '" + hireDate + "')";
try (Connection conn = DriverManager.getConnection(url, user, password);
     Statement stmt = conn.createStatement()) {
    int rowsAffected = stmt.executeUpdate(sql);
    System.out.println(rowsAffected + " row(s) inserted.");
} catch (SQLException e) {
    e.printStackTrace();
}

Why is this bad? If a malicious user controlled the email variable, they could input something like '); DROP TABLE employees; --, which could execute a destructive command.


The Modern & Recommended Approach: PreparedStatement

A PreparedStatement pre-compiles the SQL statement and sends the data separately. This is the standard, secure, and efficient way to execute parameterized queries.

Java如何向MySQL高效执行insert语句?-图3
(图片来源网络,侵删)

Key Advantages:

  • Prevents SQL Injection: The database driver treats the data as parameters, not as part of the SQL command.
  • Performance: If you execute the same query multiple times (e.g., in a loop), the database can reuse the pre-compiled execution plan.
  • Readability: Code is cleaner and easier to maintain.

Here is the correct way to insert data:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Date;
public class JdbcInsertExample {
    // Database connection details
    private static final String DB_URL = "jdbc:mysql://localhost:3306/my_company?useSSL=false&serverTimezone=UTC";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "your_password";
    public static void main(String[] args) {
        // Data to be inserted
        String firstName = "Jane";
        String lastName = "Smith";
        String email = "jane.smith@example.com";
        // java.sql.Date is required for SQL DATE type
        Date hireDate = Date.valueOf("2025-10-26");
        // The SQL query with placeholders (?)
        String sql = "INSERT INTO employees (first_name, last_name, email, hire_date) VALUES (?, ?, ?, ?)";
        // Using try-with-resources to ensure the connection is closed automatically
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            // Set the parameters for the prepared statement
            // Index starts at 1
            pstmt.setString(1, firstName);
            pstmt.setString(2, lastName);
            pstmt.setString(3, email);
            pstmt.setDate(4, hireDate);
            // Execute the update
            int rowsAffected = pstmt.executeUpdate();
            System.out.println(rowsAffected + " row(s) inserted successfully.");
        } catch (SQLException e) {
            System.err.println("Database error: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

Explanation:

  1. SQL with Placeholders: We use as placeholders for the values we want to insert.
  2. PreparedStatement: We create a PreparedStatement object from the Connection by passing the SQL query.
  3. setX() methods: We use methods like setString(), setInt(), setDate(), etc., to assign values to each placeholder. The index (1, 2, 3, 4) corresponds to the position of the .
  4. executeUpdate(): This method executes the SQL statement. It returns an integer representing the number of rows affected.

Best Practice: Using a Connection Pool

Creating a new database connection for every single operation is very inefficient. A connection pool maintains a cache of database connections that can be reused, dramatically improving performance.

A popular and robust choice is HikariCP, which is often the default in many frameworks.

Step 1: Add HikariCP to your pom.xml

<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
    <version>5.0.1</version> <!-- Check for the latest version -->
</dependency>

Step 2: Refactor the code to use the pool

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Date;
public class JdbcInsertWithPool {
    // HikariCP DataSource (this should be a singleton in your application)
    private static HikariDataSource dataSource;
    static {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:mysql://localhost:3306/my_company?useSSL=false&serverTimezone=UTC");
        config.setUsername("root");
        config.setPassword("your_password");
        // Optional but recommended pool settings
        config.addDataSourceProperty("cachePrepStmts", "true");
        config.addDataSourceProperty("prepStmtCacheSize", "250");
        config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
        dataSource = new HikariDataSource(config);
    }
    public static void insertEmployee(String firstName, String lastName, String email, Date hireDate) {
        String sql = "INSERT INTO employees (first_name, last_name, email, hire_date) VALUES (?, ?, ?, ?)";
        // Using try-with-resources for both the connection and the statement
        try (Connection conn = dataSource.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, firstName);
            pstmt.setString(2, lastName);
            pstmt.setString(3, email);
            pstmt.setDate(4, hireDate);
            int rowsAffected = pstmt.executeUpdate();
            System.out.println(rowsAffected + " row(s) inserted.");
        } catch (SQLException e) {
            System.err.println("Database error: " + e.getMessage());
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        // Example usage
        insertEmployee("Peter", "Jones", "peter.jones@example.com", Date.valueOf("2025-10-25"));
    }
}

Complete, Runnable Example (with Maven)

Here is a full project structure and code you can use to get started.

Project Structure

jdbc-insert-demo/
├── pom.xml
└── src/
    └── main/
        └── java/
            └── com/
                └── example/
                    └── JdbcMain.java

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>jdbc-insert-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>
    <dependencies>
        <!-- MySQL Connector/J -->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.0.33</version>
        </dependency>
        <!-- HikariCP Connection Pool -->
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
            <version>5.0.1</version>
        </dependency>
    </dependencies>
</project>

src/main/java/com/example/JdbcMain.java

package com.example;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Date;
public class JdbcMain {
    // --- Database Configuration ---
    private static final String DB_URL = "jdbc:mysql://localhost:3306/my_company?useSSL=false&serverTimezone=UTC";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "your_password"; // CHANGE THIS
    // --- Connection Pool Setup ---
    private static HikariDataSource dataSource;
    static {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(DB_URL);
        config.setUsername(DB_USER);
        config.setPassword(DB_PASSWORD);
        dataSource = new HikariDataSource(config);
    }
    public static void main(String[] args) {
        // Data to insert
        String firstName = "Mary";
        String lastName = "Williams";
        String email = "mary.williams@example.com";
        Date hireDate = Date.valueOf("2025-10-24");
        // Call the method to perform the insert
        insertEmployee(firstName, lastName, email, hireDate);
    }
    /**
     * Inserts a new employee into the database using a PreparedStatement and a connection pool.
     * @param firstName The employee's first name.
     * @param lastName The employee's last name.
     * @param email The employee's email.
     * @param hireDate The employee's hire date.
     */
    public static void insertEmployee(String firstName, String lastName, String email, Date hireDate) {
        // SQL query with placeholders
        String sql = "INSERT INTO employees (first_name, last_name, email, hire_date) VALUES (?, ?, ?, ?)";
        // Use try-with-resources to ensure connection and statement are closed automatically
        try (Connection conn = dataSource.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            // Set the parameters for the prepared statement
            pstmt.setString(1, firstName);
            pstmt.setString(2, lastName);
            pstmt.setString(3, email);
            pstmt.setDate(4, hireDate);
            // Execute the update
            int rowsAffected = pstmt.executeUpdate();
            if (rowsAffected > 0) {
                System.out.println("Successfully inserted " + rowsAffected + " employee.");
            } else {
                System.out.println("No rows were inserted.");
            }
        } catch (SQLException e) {
            System.err.println("Error inserting employee: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

Summary of Best Practices

  1. Always use PreparedStatement: Never build SQL queries with string concatenation for user-supplied data.
  2. Use try-with-resources: This ensures that your Connection, Statement, and ResultSet objects are always closed, preventing resource leaks.
  3. Use a Connection Pool: For any non-trivial application, a connection pool like HikariCP is essential for performance and scalability.
  4. Handle Exceptions: Catch SQLException and handle it gracefully (e.g., log the error and inform the user).
  5. Externalize Configuration: Don't hardcode credentials in your code. Use configuration files (like application.properties) or environment variables.
分享:
扫描分享到社交APP
上一篇
下一篇