MySQL作为最流行的开源关系型数据库,与Java的结合在企业级开发中无处不在。作为Java开发者,掌握MySQL的核心操作不仅能提升开发效率,更能深入理解数据持久化的本质。本文将带你系统学习MySQL的基本操作,并通过Java代码实践数据库交互。
一、MySQL基础操作回顾
1.1 数据库与表操作
sql
-- 创建数据库
CREATE DATABASE IF NOT EXISTS blog_system
DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
-- 使用数据库
USE blog_system;
-- 创建用户表
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
email VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
1.2 CRUD基础操作
sql
-- 插入数据
INSERT INTO users (username, password, email)
VALUES ('zhangsan', 'encrypted_password', 'zhangsan@example.com');
-- 查询数据
SELECT * FROM users WHERE id = 1;
SELECT username, email FROM users WHERE email LIKE '%@example.com';
-- 更新数据
UPDATE users SET email = 'new_email@example.com' WHERE id = 1;
-- 删除数据
DELETE FROM users WHERE id = 1;
二、Java连接MySQL的三种方式
2.1 原生JDBC连接
java
import java.sql.*;
public class MySQLBasicConnection {
private static final String URL = "jdbc:mysql://localhost:3306/blog_system";
private static final String USER = "root";
private static final String PASSWORD = "password";
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
// 1. 加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2. 建立连接
conn = DriverManager.getConnection(URL, USER, PASSWORD);
System.out.println("数据库连接成功!");
// 3. 创建Statement对象
stmt = conn.createStatement();
// 4. 执行查询
String sql = "SELECT * FROM users";
ResultSet rs = stmt.executeQuery(sql);
// 5. 处理结果集
while(rs.next()) {
System.out.println("ID: " + rs.getInt("id"));
System.out.println("用户名: " + rs.getString("username"));
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
// 6. 关闭资源
try {
if(stmt != null) stmt.close();
if(conn != null) conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
2.2 使用连接池(HikariCP)
java
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.*;
public class ConnectionPoolExample {
private static HikariDataSource dataSource;
static {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/blog_system");
config.setUsername("root");
config.setPassword("password");
config.setMaximumPoolSize(10);
config.setMinimumIdle(5);
config.setConnectionTimeout(30000);
config.setIdleTimeout(600000);
config.setMaxLifetime(1800000);
dataSource = new HikariDataSource(config);
}
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
}
2.3 使用PreparedStatement防止SQL注入
java
public class PreparedStatementExample {
public User getUserByUsernameAndPassword(String username, String password) {
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
try (Connection conn = getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, username);
pstmt.setString(2, password);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
User user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setEmail(rs.getString("email"));
return user;
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
public void batchInsertUsers(List<User> users) {
String sql = "INSERT INTO users (username, password, email) VALUES (?, ?, ?)";
try (Connection conn = getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
for (User user : users) {
pstmt.setString(1, user.getUsername());
pstmt.setString(2, user.getPassword());
pstmt.setString(3, user.getEmail());
pstmt.addBatch();
}
pstmt.executeBatch();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
三、事务管理与ACID特性
java
public class TransactionExample {
public boolean transferMoney(int fromUserId, int toUserId, double amount) {
Connection conn = null;
PreparedStatement pstmt1 = null;
PreparedStatement pstmt2 = null;
try {
conn = getConnection();
// 关闭自动提交,开启事务
conn.setAutoCommit(false);
// 扣除转出账户金额
String sql1 = "UPDATE accounts SET balance = balance - ? WHERE user_id = ? AND balance >= ?";
pstmt1 = conn.prepareStatement(sql1);
pstmt1.setDouble(1, amount);
pstmt1.setInt(2, fromUserId);
pstmt1.setDouble(3, amount);
int rows1 = pstmt1.executeUpdate();
if (rows1 == 0) {
throw new SQLException("转出账户余额不足");
}
// 增加转入账户金额
String sql2 = "UPDATE accounts SET balance = balance + ? WHERE user_id = ?";
pstmt2 = conn.prepareStatement(sql2);
pstmt2.setDouble(1, amount);
pstmt2.setInt(2, toUserId);
pstmt2.executeUpdate();
// 提交事务
conn.commit();
return true;
} catch (SQLException e) {
// 回滚事务
if (conn != null) {
try {
conn.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
e.printStackTrace();
return false;
} finally {
// 恢复自动提交并关闭连接
try {
if (conn != null) {
conn.setAutoCommit(true);
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
四、结果集处理与RowMapper模式
java
public class ResultSetHandler {
// 传统方式处理ResultSet
public List<User> getAllUsersTraditional() {
List<User> users = new ArrayList<>();
String sql = "SELECT * FROM users";
try (Connection conn = getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) {
User user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setEmail(rs.getString("email"));
user.setCreatedAt(rs.getTimestamp("created_at"));
user.setUpdatedAt(rs.getTimestamp("updated_at"));
users.add(user);
}
} catch (SQLException e) {
e.printStackTrace();
}
return users;
}
// 使用RowMapper模式
@FunctionalInterface
public interface RowMapper<T> {
T mapRow(ResultSet rs) throws SQLException;
}
public <T> List<T> query(String sql, RowMapper<T> rowMapper, Object... params) {
List<T> results = new ArrayList<>();
try (Connection conn = getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);
}
try (ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
results.add(rowMapper.mapRow(rs));
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return results;
}
// 使用示例
public List<User> getAllUsers() {
String sql = "SELECT * FROM users";
return query(sql, rs -> {
User user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setEmail(rs.getString("email"));
return user;
});
}
}
五、数据库连接最佳实践
5.1 使用try-with-resources自动关闭资源
java
public class DatabaseUtil {
public static void executeQuery(String sql) {
// try-with-resources会自动关闭Connection、Statement和ResultSet
try (Connection conn = getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) {
// 处理结果
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
5.2 配置文件管理数据库连接
java
// database.properties
// db.url=jdbc:mysql://localhost:3306/blog_system
// db.username=root
// db.password=password
// db.pool.size=10
public class ConfigManager {
private static Properties props = new Properties();
static {
try (InputStream input = ConfigManager.class
.getClassLoader()
.getResourceAsStream("database.properties")) {
props.load(input);
} catch (IOException e) {
e.printStackTrace();
}
}
public static String getProperty(String key) {
return props.getProperty(key);
}
}
六、性能优化技巧
6.1 批量操作提升性能
java
public class BatchOperationExample {
public void batchInsertWithTransaction(List<User> users) {
String sql = "INSERT INTO users (username, password, email) VALUES (?, ?, ?)";
try (Connection conn = getConnection()) {
conn.setAutoCommit(false);
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
for (User user : users) {
pstmt.setString(1, user.getUsername());
pstmt.setString(2, user.getPassword());
pstmt.setString(3, user.getEmail());
pstmt.addBatch();
// 每1000条执行一次批量提交
if (users.indexOf(user) % 1000 == 0) {
pstmt.executeBatch();
}
}
pstmt.executeBatch();
conn.commit();
} catch (SQLException e) {
conn.rollback();
throw e;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
6.2 使用连接池参数调优
java
public class OptimizedConnectionPool {
public static HikariDataSource createOptimizedDataSource() {
HikariConfig config = new HikariConfig();
// 核心配置
config.setJdbcUrl(ConfigManager.getProperty("db.url"));
config.setUsername(ConfigManager.getProperty("db.username"));
config.setPassword(ConfigManager.getProperty("db.password"));
// 性能优化配置
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
config.addDataSourceProperty("useServerPrepStmts", "true");
config.addDataSourceProperty("useLocalSessionState", "true");
config.addDataSourceProperty("rewriteBatchedStatements", "true");
config.addDataSourceProperty("cacheResultSetMetadata", "true");
config.addDataSourceProperty("cacheServerConfiguration", "true");
config.addDataSourceProperty("elideSetAutoCommits", "true");
config.addDataSourceProperty("maintainTimeStats", "false");
return new HikariDataSource(config);
}
}
七、实战:简单的博客系统DAO实现
java
// User实体类
public class User {
private Integer id;
private String username;
private String password;
private String email;
private Timestamp createdAt;
private Timestamp updatedAt;
// 构造方法、getter和setter省略
}
// UserDAO接口
public interface UserDAO {
User findById(Integer id);
List<User> findAll();
Integer insert(User user);
boolean update(User user);
boolean delete(Integer id);
User findByUsername(String username);
}
// UserDAO实现
public class UserDAOImpl implements UserDAO {
@Override
public User findById(Integer id) {
String sql = "SELECT * FROM users WHERE id = ?";
try (Connection conn = getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setInt(1, id);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
return mapUser(rs);
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
@Override
public Integer insert(User user) {
String sql = "INSERT INTO users (username, password, email) VALUES (?, ?, ?)";
try (Connection conn = getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql,
Statement.RETURN_GENERATED_KEYS)) {
pstmt.setString(1, user.getUsername());
pstmt.setString(2, user.getPassword());
pstmt.setString(3, user.getEmail());
int affectedRows = pstmt.executeUpdate();
if (affectedRows == 0) {
throw new SQLException("创建用户失败");
}
try (ResultSet generatedKeys = pstmt.getGeneratedKeys()) {
if (generatedKeys.next()) {
return generatedKeys.getInt(1);
} else {
throw new SQLException("获取生成ID失败");
}
}
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}
private User mapUser(ResultSet rs) throws SQLException {
User user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
user.setEmail(rs.getString("email"));
user.setCreatedAt(rs.getTimestamp("created_at"));
user.setUpdatedAt(rs.getTimestamp("updated_at"));
return user;
}
}
总结
通过本文的学习,我们掌握了:
-
MySQL基础操作:从DDL到DML的核心语句
-
Java连接MySQL的多种方式:原生JDBC、连接池、PreparedStatement
-
事务管理:确保数据操作的ACID特性
-
结果集处理:传统方式与RowMapper模式
-
最佳实践:资源管理、配置优化
-
性能优化:批量操作、连接池调优
-
实战应用:完整的DAO层实现
下一步学习建议
-
学习ORM框架:如MyBatis、Hibernate
-
掌握数据库设计原则:规范化、索引优化
-
学习高级特性:存储过程、触发器、视图
-
探索分库分表:应对大数据量场景
-
了解数据库监控:慢查询分析、性能调优
希望这篇博客能帮助你在Java与MySQL的学习道路上更进一步。数据库操作是后端开发的核心技能,熟练掌握这些基础将为职业生涯奠定坚实的基础。
参考资料:MySQL官方文档、JDBC API文档
原创声明:本文为原创技术博客,转载请注明出处。欢迎在评论区交流讨论!