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.

We'll cover:
- The Basic Approach (The "Old" Way): Good for understanding the fundamentals.
- The Modern Approach (Recommended): Using
PreparedStatementto prevent SQL injection and improve performance. - Using a Connection Pool: Essential for any real-world application.
- Complete, Runnable Example: A full Java program you can adapt and run.
Prerequisites
-
MySQL Server: Installed and running.
-
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 ); -
MySQL JDBC Driver: You need the JAR file. The easiest way to manage dependencies is with a build tool like Maven or Gradle.
(图片来源网络,侵删)
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.

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:
- SQL with Placeholders: We use as placeholders for the values we want to insert.
PreparedStatement: We create aPreparedStatementobject from theConnectionby passing the SQL query.setX()methods: We use methods likesetString(),setInt(),setDate(), etc., to assign values to each placeholder. The index (1, 2, 3, 4) corresponds to the position of the .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
- Always use
PreparedStatement: Never build SQL queries with string concatenation for user-supplied data. - Use
try-with-resources: This ensures that yourConnection,Statement, andResultSetobjects are always closed, preventing resource leaks. - Use a Connection Pool: For any non-trivial application, a connection pool like HikariCP is essential for performance and scalability.
- Handle Exceptions: Catch
SQLExceptionand handle it gracefully (e.g., log the error and inform the user). - Externalize Configuration: Don't hardcode credentials in your code. Use configuration files (like
application.properties) or environment variables.
