资讯动态

Java JDBC连接MySQL数据库CRUD操作指南

发布时间:2026/9/16 8:00:27 来源:尧图企业网站定制
1. Java数据库连接基础解析Java连接数据库实现增删改查(CRUD)是每个Java开发者必须掌握的核心技能。无论你是刚入门的新手还是有一定经验的开发者理解JDBC的工作原理和最佳实践都至关重要。JDBC(Java Database Connectivity)是Java语言中用来规范客户端程序如何访问数据库的应用程序接口它为数据库操作提供了一套标准方法。在实际开发中我们通常使用MySQL作为关系型数据库的代表。MySQL因其开源、高性能和易用性成为Java后端开发中最常用的数据库之一。要使用Java操作MySQL数据库首先需要确保已经安装并配置好MySQL服务同时准备好JDBC驱动。注意MySQL 8.0版本与5.x版本在JDBC连接配置上有一些差异特别是密码加密方式的变化这在后续连接配置时需要特别注意。2. 环境准备与项目搭建2.1 数据库环境配置在开始编码前我们需要完成以下准备工作安装MySQL数据库服务推荐5.7或8.0版本创建测试数据库和用户表下载对应版本的MySQL JDBC驱动创建测试表的SQL语句示例CREATE TABLE IF NOT EXISTS users ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL, password VARCHAR(50) NOT NULL, email VARCHAR(100), create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME ON UPDATE CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;2.2 Java项目依赖配置对于Maven项目需要在pom.xml中添加MySQL驱动依赖dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.28/version /dependency如果是Gradle项目则在build.gradle中添加implementation mysql:mysql-connector-java:8.0.283. JDBC核心组件详解3.1 驱动加载与连接建立JDBC操作数据库的第一步是加载驱动并建立连接。在Java 6以后我们不再需要显式调用Class.forName()加载驱动而是通过DriverManager自动发现并注册驱动。建立数据库连接的标准代码String url jdbc:mysql://localhost:3306/test_db?useSSLfalseserverTimezoneUTC; String username root; String password 123456; try (Connection conn DriverManager.getConnection(url, username, password)) { // 数据库操作代码 } catch (SQLException e) { e.printStackTrace(); }提示使用try-with-resources语法可以确保Connection在使用后自动关闭避免资源泄漏。3.2 Statement与PreparedStatementJDBC提供了两种主要的SQL执行接口Statement用于执行静态SQL语句PreparedStatement预编译SQL语句防止SQL注入性能更好创建PreparedStatement的示例String sql INSERT INTO users(username, password, email) VALUES(?, ?, ?); try (PreparedStatement pstmt conn.prepareStatement(sql)) { pstmt.setString(1, testuser); pstmt.setString(2, password123); pstmt.setString(3, testexample.com); pstmt.executeUpdate(); }3.3 ResultSet处理查询结果查询操作会返回ResultSet对象它包含了查询结果的所有数据。处理ResultSet的典型模式String query SELECT * FROM users WHERE username ?; try (PreparedStatement pstmt conn.prepareStatement(query)) { pstmt.setString(1, testuser); try (ResultSet rs pstmt.executeQuery()) { while (rs.next()) { int id rs.getInt(id); String username rs.getString(username); String email rs.getString(email); // 处理数据... } } }4. CRUD操作完整实现4.1 增加数据(Insert)public int insertUser(User user) throws SQLException { 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); } } } }4.2 查询数据(Select)public User getUserById(int userId) throws SQLException { String sql SELECT * FROM users WHERE id ?; try (Connection conn getConnection(); PreparedStatement pstmt conn.prepareStatement(sql)) { pstmt.setInt(1, userId); try (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)); user.setCreateTime(rs.getTimestamp(create_time)); user.setUpdateTime(rs.getTimestamp(update_time)); return user; } } } return null; }4.3 更新数据(Update)public boolean updateUser(User user) throws SQLException { String sql UPDATE users SET username ?, password ?, email ? WHERE id ?; try (Connection conn getConnection(); PreparedStatement pstmt conn.prepareStatement(sql)) { pstmt.setString(1, user.getUsername()); pstmt.setString(2, user.getPassword()); pstmt.setString(3, user.getEmail()); pstmt.setInt(4, user.getId()); return pstmt.executeUpdate() 0; } }4.4 删除数据(Delete)public boolean deleteUser(int userId) throws SQLException { String sql DELETE FROM users WHERE id ?; try (Connection conn getConnection(); PreparedStatement pstmt conn.prepareStatement(sql)) { pstmt.setInt(1, userId); return pstmt.executeUpdate() 0; } }5. 高级特性与性能优化5.1 批量操作当需要执行大量相似操作时批量处理可以显著提高性能public int[] batchInsert(ListUser users) throws SQLException { 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(); } return pstmt.executeBatch(); } }5.2 事务管理确保一组操作要么全部成功要么全部失败public boolean transferMoney(int fromId, int toId, BigDecimal amount) throws SQLException { Connection conn null; try { conn getConnection(); conn.setAutoCommit(false); // 开始事务 // 扣除转出账户金额 String deductSql UPDATE accounts SET balance balance - ? WHERE id ? AND balance ?; try (PreparedStatement pstmt conn.prepareStatement(deductSql)) { pstmt.setBigDecimal(1, amount); pstmt.setInt(2, fromId); pstmt.setBigDecimal(3, amount); if (pstmt.executeUpdate() ! 1) { conn.rollback(); return false; } } // 增加转入账户金额 String addSql UPDATE accounts SET balance balance ? WHERE id ?; try (PreparedStatement pstmt conn.prepareStatement(addSql)) { pstmt.setBigDecimal(1, amount); pstmt.setInt(2, toId); if (pstmt.executeUpdate() ! 1) { conn.rollback(); return false; } } conn.commit(); // 提交事务 return true; } catch (SQLException e) { if (conn ! null) { conn.rollback(); } throw e; } finally { if (conn ! null) { conn.setAutoCommit(true); conn.close(); } } }5.3 连接池配置生产环境推荐使用连接池管理数据库连接。以HikariCP为例public class DataSourceConfig { private static HikariDataSource dataSource; static { HikariConfig config new HikariConfig(); config.setJdbcUrl(jdbc:mysql://localhost:3306/test_db); config.setUsername(root); config.setPassword(123456); config.setMaximumPoolSize(20); 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(); } }6. 常见问题与解决方案6.1 连接超时问题问题现象获取数据库连接时抛出ConnectionTimeoutException。解决方案检查数据库服务是否正常运行验证连接字符串、用户名和密码是否正确增加连接超时时间配置检查网络连接是否通畅6.2 SQL注入防护风险代码String sql SELECT * FROM users WHERE username username ; Statement stmt conn.createStatement(); ResultSet rs stmt.executeQuery(sql);安全写法String sql SELECT * FROM users WHERE username ?; PreparedStatement pstmt conn.prepareStatement(sql); pstmt.setString(1, username); ResultSet rs pstmt.executeQuery();6.3 字符编码问题问题现象中文数据存入数据库后变成乱码。解决方案确保数据库、表和字段使用utf8mb4字符集JDBC连接字符串中添加字符集参数jdbc:mysql://localhost:3306/test_db?useUnicodetruecharacterEncodingUTF-8检查应用程序的字符编码设置6.4 时区问题问题现象时间类型数据与预期不符。解决方案在JDBC连接字符串中指定时区jdbc:mysql://localhost:3306/test_db?serverTimezoneAsia/Shanghai确保数据库服务器和应用程序服务器使用相同的时区在Java代码中明确处理时区转换7. 最佳实践与性能优化7.1 资源释放确保及时释放数据库资源避免内存泄漏public ListUser getAllUsers() throws SQLException { ListUser users new ArrayList(); Connection conn null; PreparedStatement pstmt null; ResultSet rs null; try { conn getConnection(); pstmt conn.prepareStatement(SELECT * FROM users); rs pstmt.executeQuery(); while (rs.next()) { User user new User(); // 设置用户属性... users.add(user); } } finally { if (rs ! null) try { rs.close(); } catch (SQLException e) { /* 忽略 */ } if (pstmt ! null) try { pstmt.close(); } catch (SQLException e) { /* 忽略 */ } if (conn ! null) try { conn.close(); } catch (SQLException e) { /* 忽略 */ } } return users; }7.2 使用Try-With-Resources简化代码Java 7支持try-with-resources语法可以自动关闭资源public ListUser getAllUsers() throws SQLException { ListUser users new ArrayList(); String sql SELECT * FROM users; try (Connection conn getConnection(); PreparedStatement pstmt conn.prepareStatement(sql); ResultSet rs pstmt.executeQuery()) { while (rs.next()) { User user new User(); // 设置用户属性... users.add(user); } } return users; }7.3 使用RowMapper简化结果集处理定义通用的RowMapper接口FunctionalInterface public interface RowMapperT { T mapRow(ResultSet rs) throws SQLException; }实现通用的查询方法public T ListT query(String sql, RowMapperT rowMapper, Object... params) throws SQLException { ListT 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)); } } } return results; }使用示例ListUser users query(SELECT * FROM users WHERE username LIKE ?, rs - { User user new User(); user.setId(rs.getInt(id)); user.setUsername(rs.getString(username)); return user; }, %test%);7.4 使用JdbcTemplate简化JDBC操作Spring框架提供的JdbcTemplate进一步简化了JDBC操作Repository public class UserRepository { private final JdbcTemplate jdbcTemplate; Autowired public UserRepository(DataSource dataSource) { this.jdbcTemplate new JdbcTemplate(dataSource); } public User findById(int id) { String sql SELECT * FROM users WHERE id ?; return jdbcTemplate.queryForObject(sql, (rs, rowNum) - { User user new User(); user.setId(rs.getInt(id)); user.setUsername(rs.getString(username)); return user; }, id); } public int insert(User user) { String sql INSERT INTO users(username, password) VALUES(?, ?); return jdbcTemplate.update(sql, user.getUsername(), user.getPassword()); } }8. 实际项目中的扩展应用8.1 分页查询实现public PageUser findUsersByPage(int pageNum, int pageSize) throws SQLException { PageUser page new Page(); page.setPageNum(pageNum); page.setPageSize(pageSize); // 查询总数 String countSql SELECT COUNT(*) FROM users; try (Connection conn getConnection(); PreparedStatement pstmt conn.prepareStatement(countSql); ResultSet rs pstmt.executeQuery()) { if (rs.next()) { page.setTotal(rs.getInt(1)); } } // 查询分页数据 String dataSql SELECT * FROM users LIMIT ? OFFSET ?; int offset (pageNum - 1) * pageSize; try (Connection conn getConnection(); PreparedStatement pstmt conn.prepareStatement(dataSql)) { pstmt.setInt(1, pageSize); pstmt.setInt(2, offset); try (ResultSet rs pstmt.executeQuery()) { ListUser users new ArrayList(); while (rs.next()) { User user new User(); // 设置用户属性... users.add(user); } page.setData(users); } } return page; }8.2 存储过程调用public void callStoredProcedure(int userId) throws SQLException { String sql {call update_user_status(?, ?)}; try (Connection conn getConnection(); CallableStatement cstmt conn.prepareCall(sql)) { cstmt.setInt(1, userId); cstmt.registerOutParameter(2, Types.INTEGER); cstmt.execute(); int result cstmt.getInt(2); if (result ! 0) { throw new SQLException(存储过程执行失败错误码 result); } } }8.3 数据库元数据获取public void printDatabaseMetadata() throws SQLException { try (Connection conn getConnection()) { DatabaseMetaData metaData conn.getMetaData(); System.out.println(数据库产品名称: metaData.getDatabaseProductName()); System.out.println(数据库产品版本: metaData.getDatabaseProductVersion()); System.out.println(JDBC驱动名称: metaData.getDriverName()); System.out.println(JDBC驱动版本: metaData.getDriverVersion()); // 获取所有表信息 try (ResultSet tables metaData.getTables(null, null, %, new String[]{TABLE})) { while (tables.next()) { System.out.println(表名: tables.getString(TABLE_NAME)); } } } }9. 测试与调试技巧9.1 单元测试配置使用JUnit测试数据库操作public class UserDaoTest { private UserDao userDao; private Connection testConn; Before public void setUp() throws SQLException { // 初始化测试数据库连接 String url jdbc:h2:mem:test;DB_CLOSE_DELAY-1; testConn DriverManager.getConnection(url, sa, ); // 创建测试表 try (Statement stmt testConn.createStatement()) { stmt.execute(CREATE TABLE users(id INT PRIMARY KEY, username VARCHAR(50))); } userDao new UserDao(() - testConn); } Test public void testInsertAndFindUser() throws SQLException { User user new User(); user.setId(1); user.setUsername(testuser); userDao.insert(user); User found userDao.findById(1); assertNotNull(found); assertEquals(testuser, found.getUsername()); } After public void tearDown() throws SQLException { if (testConn ! null) { testConn.close(); } } }9.2 SQL日志记录配置日志框架记录执行的SQL语句# log4j.properties log4j.logger.java.sqlDEBUG log4j.logger.javax.sqlDEBUG或使用p6spy等工具拦截SQL!-- pom.xml -- dependency groupIdp6spy/groupId artifactIdp6spy/artifactId version3.9.1/version /dependency配置spy.propertiesdriverlistcom.mysql.jdbc.Driver appendercom.p6spy.engine.spy.appender.Slf4JLogger10. 从JDBC到ORM框架虽然直接使用JDBC可以完成所有数据库操作但在实际项目中我们通常会使用ORM框架如Hibernate或MyBatis来简化开发。理解JDBC原理对于使用这些框架至关重要。10.1 MyBatis基础配置!-- mybatis-config.xml -- configuration environments defaultdevelopment environment iddevelopment transactionManager typeJDBC/ dataSource typePOOLED property namedriver valuecom.mysql.jdbc.Driver/ property nameurl valuejdbc:mysql://localhost:3306/test_db/ property nameusername valueroot/ property namepassword value123456/ /dataSource /environment /environments mappers mapper resourcecom/example/mapper/UserMapper.xml/ /mappers /configuration10.2 MyBatis Mapper示例!-- UserMapper.xml -- mapper namespacecom.example.mapper.UserMapper select idfindById resultTypecom.example.model.User SELECT * FROM users WHERE id #{id} /select insert idinsert useGeneratedKeystrue keyPropertyid INSERT INTO users(username, password) VALUES(#{username}, #{password}) /insert /mapper10.3 Spring Data JPA示例Entity Table(name users) public class User { Id GeneratedValue(strategy GenerationType.IDENTITY) private Integer id; Column(nullable false, length 50) private String username; Column(nullable false, length 100) private String password; // getters and setters } public interface UserRepository extends JpaRepositoryUser, Integer { User findByUsername(String username); }在实际开发中根据项目规模和团队习惯选择合适的数据库访问方式。小型项目可以直接使用JDBC或JdbcTemplate中型项目可以考虑MyBatis大型复杂项目则可能更适合使用JPA或Hibernate。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价