JDBC(Java DataBase Connectivity)是 Java 和数据库之间的一个桥梁,是一个规范而不是一个实现,能够执行 SQL 语句。它由一组 Java 语言编写的类和接口组成,各种不同类型的数据库都有相应的实现,下面的示例代码是采用 MySQL 数据库实现的。
1567043260200.pngJDBC 编程步骤
(1)装载相应的数据库的 JDBC 驱动并进行初始化
-
导入 jar 包,或者通过 maven 添加依赖都可以。
-
初始化驱动
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 注意:Class.forName 需要捕获 ClassNotFoundException
// Class.forName 是把这个类加载到 JVM 中,加载的时候,会执行其中的静态初始化块,完成驱动的初始化的相关工作
(2)建立 JDBC 和数据库之间的 Connection 连接
需要知道的数据库信息:
-
数据库所处于的 ip ,如:127.0.0.1
-
数据库的端口号: 3306 (mysql专用端口号)
-
数据库名称:eee
-
编码方式:UTF-8
-
账号:root,密码:root
Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/exam?characterEncoding=UTF-8", "root", "root");
// Connection 是与特定数据库连接的接口,使用的时候需要导包,在程序结束的时候需要将其关闭
// getConnection 会抛出 SQLException 异常
封装后的 getConnection 方法,便于将来直接调用
public static Connection getConnection(){
Connection conn = null;
try {
//初始化驱动类com.mysql.jdbc.Driver
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/exam?characterEncoding=UTF-8","root", "root");
//该类就在 mysql-connector-java-5.0.8-bin.jar中,如果忘记了第一个步骤的导包,就会抛出ClassNotFoundException
}catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
(3)创建 Statement 或者 PreparedStatement 接口,执行 SQL 语句
- 使用 Statement 接口
Statement s = conn.createStatement();
// 准备 sql 语句
// 注意: 字符串要用单引号'
String sql = "insert into t_courses values(null,"+"'数学')";
//在 statement 中使用字符串拼接的方式,这种方式存在诸多问题
s.execute(sql);
System.out.println("执行插入语句成功");
注意:在 statement 中使用字符串拼接的方式,这种方式存在诸多问题。
- 使用 PreparedStatement 接口
// add 操作
public void addCourse(String courseName){
String sql = "insert into t_course(course_name) values(?)";
//该语句为每个 IN 参数保留一个问号(“?”)作为占位符
Connection conn = null; //和数据库取得连接
PreparedStatement pstmt = null; //创建statement
try{
conn = DbUtil.getConnection();
pstmt = (PreparedStatement) conn.prepareStatement(sql);
pstmt.setString(1, courseName); //给占位符赋值
pstmt.executeUpdate(); //执行
}catch(SQLException e){
e.printStackTrace();
}
finally{
DbUtil.close(pstmt);
DbUtil.close(conn); //必须关闭
}
}
// delete 操作
public void delCourse(int courseId){
String sql = "delete from t_course where course_id = ?";
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = DbUtil.getConnection();
pstmt = (PreparedStatement) conn.prepareStatement(sql);
pstmt.setInt(1, courseId);
pstmt.executeUpdate();
} catch (SQLException e) {
// TODO: handle exception
e.printStackTrace();
}finally{
DbUtil.close(pstmt);
DbUtil.close(conn); //必须关闭
}
}
// update 操作
public void modifyCourse(int courseId,String courseName){
String sql = "update t_course set course_name =? where course_id=?";
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = DbUtil.getConnection();
pstmt = (PreparedStatement) conn.prepareStatement(sql);
pstmt.setString(1, courseName); //利用Preparedstatement的set方法给占位符赋值
pstmt.setInt(2, courseId);
pstmt.executeUpdate();
} catch (SQLException e) {
// TODO: handle exception
e.printStackTrace();
}finally{
DbUtil.close(pstmt);
DbUtil.close(conn); //必须关闭
}
}
注意:
- 使用 PreparedStatement 时,它的 SQL 语句不再采用字符串拼接的方式,而是采用占位符的方式。“?”在这里就起到占位符的作用。这种方式除了避免了 statement 拼接字符串的繁琐之外,还能够提高性能。每次 SQL 语句都是一样的,数据库就不会再次编译,这样能够显著提高性能。
String sql = "update t_course set course_name =? where course_id=?";
- 用到 PreparedStatement 接口创建的 pstmt 的 set 方法给占位符进行赋值。注意一点,这里的参数索引是从1开始的。
pstmt = (PreparedStatement) conn.prepareStatement(sql);
pstmt.setString(1, courseName); //利用Preparedstatement的set方法给占位符赋值
pstmt.setInt(2, courseId);
pstmt.executeUpdate();
- 使用 PreparedStatement 进行批量操作
for(int i=1;i<100;i++){
pstmt.setInt(1,8000+i);
pstmt.setString(2,"赵_"+i);
pstmt.addBatch();
//批量更新
if(i%10 == 0){
pstmt.executeBatch();
}
}
(4)查询操作 & 处理显示结果
public List<Course> findCourseList(){
String sql = "select * from t_course order by course_id";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
//创建一个集合对象用来存放查询到的数据
List<Course> courseList = new ArrayList<>();
try {
conn = DbUtil.getConnection();
pstmt = (PreparedStatement) conn.prepareStatement(sql);
rs = (ResultSet) pstmt.executeQuery();
while (rs.next()){
int courseId = rs.getInt("course_id"); // 可以填属性值
String courseName = rs.getString("course_name");
//每个记录对应一个对象
Course course = new Course();
course.setCourseId(courseId);
course.setCourseName(courseName);
//将对象放到集合中
courseList.add(course);
}
} catch (SQLException e) {
// TODO: handle exception
e.printStackTrace();
}finally{
DbUtil.close(pstmt);
DbUtil.close(conn); //必须关闭
}
return courseList;
}
(5)释放资源
public static void close(PreparedStatement pstmt){
if(pstmt != null){ //避免出现空指针异常
try{
pstmt.close();
}catch(SQLException e){
e.printStackTrace();
}
}
}
public static void close(Connection conn){
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
public static void close(ResultSet rs){
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
Statement 和 PreparedStatement 的比较
相同点:
- 两者都是用来执 SQL 语句的。
不同点:
- PreparedStatement 需要根据 SQL 语句来创建,它能够通过设置参数,指定相应的值。
- Statement 使用字符串拼接的方式。
PreparedStatement 的优点:
- 其使用参数设置,可读性好,不易记错。在 statement 中使用字符串拼接,可读性和维护性比较差。
- 其具有预编译机制,性能比 statement 更快。
- 其能够有效防止 SQL 注入攻击。
execute 和 executeUpdate 的区别
相同点:二者都能够执行增加、删除、修改等操作。
不同点:
- execute可以执行查询语句,然后通过 getResult 把结果取出来。
- executeUpdate 不能执行查询语句。
- execute 返回 Boolean 类型,true 表示执行的是查询语句,false 表示执行的 insert、delete、update 等。
- executeUpdate 的返回值是 int,表示有多少条数据受到了影响。
网友评论