上一篇
使用JDBC连接数据库,加载驱动后建立Connection对象,通过Statement或PreparedStatement执行SQL查询语句,用ResultSet接收返回数据并遍历结果集,最后关闭资源确保连接释放。
在Java中查找数据库是开发中常见任务,核心是通过JDBC或ORM框架实现,以下是详细步骤和最佳实践:
基础方法:使用JDBC(Java Database Connectivity)
环境准备
- 引入数据库驱动(Maven示例):
<!-- MySQL驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency>
核心步骤
import java.sql.*;
public class JdbcExample {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC";
String user = "root";
String password = "yourpassword";
try (Connection conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement()) {
// 执行查询
String sql = "SELECT id, name, email FROM users WHERE age > ?";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setInt(1, 18); // 防止SQL注入
ResultSet rs = pstmt.executeQuery();
// 处理结果集
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
String email = rs.getString("email");
System.out.println("ID: " + id + ", Name: " + name + ", Email: " + email);
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
关键点说明:
- 连接参数:包含时区(
serverTimezone)和SSL配置,避免常见连接错误。 - PreparedStatement:强制使用参数化查询,杜绝SQL注入风险。
- Try-with-resources:自动关闭连接/语句,防止资源泄漏。
高效方案:使用ORM框架(MyBatis示例)
添加依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
配置文件(mybatis-config.xml)
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value="yourpassword"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/example/mapper/UserMapper.xml"/>
</mappers>
</configuration>
创建Mapper接口和XML
// UserMapper.java
public interface UserMapper {
List<User> selectUsersByAge(@Param("minAge") int minAge);
}
<!-- UserMapper.xml -->
<mapper namespace="com.example.mapper.UserMapper">
<select id="selectUsersByAge" resultType="com.example.model.User">
SELECT id, name, email
FROM users
WHERE age > #{minAge}
</select>
</mapper>
执行查询
try (SqlSession session = sqlSessionFactory.openSession()) {
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> users = mapper.selectUsersByAge(18);
users.forEach(user -> System.out.println(user.getName()));
}
最佳实践与注意事项
-
连接池优化
- 使用HikariCP或Druid提升性能:
<dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> <version>5.0.1</version> </dependency>
- 使用HikariCP或Druid提升性能:
-
SQL注入防御
- 禁止拼接SQL字符串,坚持使用:
- JDBC:
PreparedStatement - MyBatis:语法(非)
- JDBC:
- 禁止拼接SQL字符串,坚持使用:
-
异常处理
- 捕获特定异常(如
SQLException),记录详细日志:catch (SQLException e) { logger.error("数据库错误: 状态码={}, 消息={}", e.getSQLState(), e.getMessage()); }
- 捕获特定异常(如
-
事务管理
- 关键操作添加事务:
try { conn.setAutoCommit(false); // 执行多个更新... conn.commit(); } catch (SQLException e) { conn.rollback(); }
- 关键操作添加事务:
常见问题解决
- 连接失败:检查防火墙、数据库权限、驱动版本。
- 性能瓶颈:
- 启用连接池(如HikariCP)
- 添加数据库索引(如
CREATE INDEX idx_age ON users(age))
- 结果集为空:
- 调试SQL:在数据库客户端直接运行查询语句
- 检查参数传递(如MyBatis的
@Param注解)
框架选型建议
| 场景 | 推荐方案 | 优势 |
|---|---|---|
| 简单查询/小项目 | JDBC | 无依赖、直接控制SQL |
| 复杂业务/中大型项目 | MyBatis或Spring Data JPA | 减少模板代码、强类型安全 |
引用说明:本文代码示例基于MySQL 8.0和MyBatis官方文档实现,JDBC规范参考Oracle官方教程,安全实践遵循OWASP SQL注入防护指南,性能建议来自生产环境优化经验。
