前言

JDBC编程步骤❗:

  1. 加载数据库驱动程序 class
  2. 创建数据库连接对象 Connection
  3. 创建Statement语句对象(createStatement、prepareStatement)
  4. 执行SQL语句
  5. 处理结果集(只有查询需要)
  6. 释放资源 close

JDBC 的主要作用是连接 Java 数据库连接,使用它可以在Java程序中执行数据库的SQL语句

JDBC 是由 Java 语言定义接口和数据库厂商提供实现类组成。

用到的接口有:
Connection:特定数据库的连接,在连接上下文中执行SQL语句并返回结果。
Statement:用于执行静态SQL语句并返回它所生成结果的对象。
PreparedStatement:表示预编译的SQL语句的对象,继承并扩展了Statement接口。
ResultSet:装载数据库结果集的接口。

在这里插入图片描述

创建数据库

提示:下面所有代码的实现都是基于此数据库

CREATE TABLE user (
  id int(4) PRIMARY KEY auto_increment, -- 用户ID 主键 不需要强调非空
  name varchar(20) NOT NULL,   -- 用户姓名 非空
  email varchar(50) NOT NULL UNIQUE,  -- 用户邮箱 非空 唯一
  phone varchar(20) NOT NULL UNIQUE,  -- 用户电话 非空 唯一
  birth date NOT NULL  -- 用户生日 非空
);

在上面创建语句中,约束应该大写,因此 PRIMARY KEY、NOT NULL、UNIQUE 应该全部大写。

在Eclipse中新建Java项目,然后新建文件夹取名lib,放入jar包

在这里插入图片描述

以下是MySQL8版本的代码

随后右键放入的jar包,选择构建路径→添加至配置路径

在这里插入图片描述
选择完后就会看到多一个引用的库在这里插入图片描述
随后新建src新建包和类

基础版

JDBC实例添加

//所有导入的包都是java.sql的
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class InsertDemo {
	public static void main(String[] args) throws Exception {
		//JDBC编程步骤
		//1、加载数据库驱动程序
		Class.forName("com.mysql.cj.jdbc.Driver");
		//2、创建数据库连接对象
		//传入三个参数 数据库的URL、用户名、密码
		//每种数据库驱动程序的名字和数据库URL的写法都不同
		Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/user?characterEncoding=utf8&serverTimezone=Asia/Shanghai","root","123456");
		
		System.out.println(connection);
		//3、创建Statement语句对象
		Statement statement = connection.createStatement();
		//4.执行SQL语句
		//如果执行的是增加 删除 修改语句 ,调用exceuteUpdate,返回值是整数,代表的是影响数据库的行的数量
		//如果执行的是查询语句,调用的是executeQuery 返回值是结果集
		int rows = statement.executeUpdate("insert into user values(4,'赵六','124502@qq.com','12781200101','2019-08-11')"); 
		System.out.println(rows);  //rows拿到影响数据库的行数
		//5、处理结果集
		//插入语句不需要
		//6、释放资源
		//连接、语句、结果集需要释放,调用close方法,先创建的后释放
		statement.close();
		connection.close();		
	}
}

运行结果:

在这里插入图片描述
Navicat中的显示:
以此类推我们改个id和其他几个字段数据,多添加几条

在这里插入图片描述

JDBC实例删除

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class DeleteDemo {
	public static void main(String[] args) throws Exception {
		//1、加载数据库驱动程序
		Class.forName("com.mysql.cj.jdbc.Driver");
		//2、创建数据库连接对象
		Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/user?characterEncoding=utf8&serverTimezone=Asia/Shanghai","root","123456");
		//3、创建Statement语句对象
		Statement statement = connection.createStatement();
		//4、执行SQL语句
		int rows = statement.executeUpdate("delete from user where id=1");  //删除id是1的数据
		System.out.println(rows);
		//5、处理结果集,这里没有
		//6、释放资源
		statement.close();
		connection.close();
	}

}

运行结果
在这里插入图片描述

删到最后控制台就是0了

JDBC实例修改

修改按照上述方法也可以改,但我们接下来换个方法,给他封装一下
把第一步和第二步、第六步封装一下

接下来定义一个JDBC的工具类封装一下
这里是新建了一个包和类

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class JdbcUtil {
//加载驱动程序和创建数据库连接,封装到一个静态代码方法里
public static Connection createConnection() {
		
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			//这里不再抛出异常,而是包围它
		} catch (ClassNotFoundException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		Connection connection = null;
		try {
			connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/user?characterEncoding=utf8&serverTimezone=Asia/Shanghai","root","123456");
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		
		return connection;
	}
	
	//释放资源,封装到静态方法中,方便调用
	public static void close(Statement statement,Connection connection) {
		try {
			statement.close();
			connection.close();
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
	}	
}

回到之前的包,新建修改类

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

import com.jdbc.work.util.JdbcUtil;

public class UpdateDemo {
public static void main(String[] args) {
		
		Connection connection = null;
		Statement statement = null;
		//刚才封装到了静态方法里面,这里直接调用
		connection = JdbcUtil.createConnection();
		try {
			statement=connection.createStatement(); //这里异常也用try...catch
			
			int rows = statement.executeUpdate("update user set name='王朝',email='74123@163.com' where id=2");  //修改编号为2的用户姓名与邮箱
		System.out.println(rows);
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}finally {
			JdbcUtil.close(statement, connection);
		}  //释放资源放在finally块里,无论try内代码是否有异常,finally块内代码都会运行
	}
}

在这里插入图片描述

JDBC实例查询

只有查询用到了结果集,我们在JdbcUtil类中再写一个方法,把结果集加进去

	public static void close(ResultSet resultSet,Statement statement,Connection connection) {
		//重载
		try {
			resultSet.close();
			statement.close();
			connection.close();
		} catch (SQLException e) {
			// 包围方式 自动生成的 catch 块
			e.printStackTrace();
		}
	}

下面代码是查询方法

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;

import com.jdbc.work.util.JdbcUtil;

public class QueryDemo {
	public static void main(String[] args) {
		Connection connection = null; //连接
		Statement statement = null; //语句
		ResultSet resultSet = null;	//结果集,只有查询需要
		
		connection = JdbcUtil.createConnection();  //创建连接
		try {
			statement = connection.createStatement();
			resultSet = statement.executeQuery(" select * from user ");
			//5.处理结果集
			//处理结果集其实就是从结果集中将数据取出使用
			//使用while循环语句  次数不固定,先判断
			//结果集next方法判断是否有数据行
			while(resultSet.next()) {
				//查询语句中查询几列就需要取出几列数据
				//取数据调用结果集中的getXXX方法
				//数据库中列是整数类型 --- getInt
				//数据库中列是浮点数类型 float double decimal--- getDouble
				//数据库中是日期类型 ---- getDate
				//数据库中是字符型 char varchar ---getString
				int id = resultSet.getInt("id"); //1:第几个数据.最好放列名
				String name = resultSet.getString("name");
				String email = resultSet.getString("email");
				String phone = resultSet.getString("phone");
				Date birth = resultSet.getDate("birth");
				
				System.out.println(id+"\t"+name+"\t"+email+"\t"+phone+"\t"+birth);				
			}
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}finally {
			JdbcUtil.close(resultSet,statement, connection);
		}
		
	}

}

控制台结果:
在这里插入图片描述

高级版

上面的数据是写在代码内的,但是我们应该让他是个变量
这里用到了prepareStatement它是Statement子接口,预编译语句
因为Statement会引起SQL注入问题,同时变量的拼接很不方便

JDBC实例添加

第一种方法:

所用到的方法均作为笔记写在了注释内

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
import com.jdbc.work.util.JdbcUtil;

public class InsertDemo {
	public static void main(String[] args) {
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		//它是Statement子接口,预编译语句
		//Statement会引起SQL注入问题,同时变量的拼接很不方便
		
		connection = JdbcUtil.createConnection();
		//调用prepareStatement方法创建预编译语句对象
		//传入执行的SQL语句,SQL语句中的数据部分替换成?
		try {
			preparedStatement = connection.prepareStatement("insert into user values(?,?,?,?,?)");
			//预编译语句执行前,必须给所有?赋值
			//调用PreparedStatement(预编译)语句中的setXXX方法,类似于结果集中的getXXX对应
			Scanner scanner = new Scanner(System.in);
			int id;
			String name;
			String email;
			String phone;
			String birth;
			
			System.out.println("请输入用户id");
			id = scanner.nextInt();
			
			System.out.println("请输入用户姓名");
			name = scanner.next();
			
			System.out.println("请输入用户邮箱");
			email = scanner.next();
			
			System.out.println("请输入用户电话");
			phone = scanner.next();
			
			System.out.println("请输入用户生日");
			birth = scanner.next(); //需要转换,现在是字符串
			//调用setXXX方法,从左向右方向依次给?赋值
			preparedStatement.setInt(1, id);
			//赋值时问号的序号从1开始,数据库是个特例
			preparedStatement.setString(2, name);
			preparedStatement.setString(3, email);
			preparedStatement.setString(4, phone);
			
			//类型转换 把date类型转换成String类型
			//1.将String类型转换成java.util.Date类型 
			SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); 
			Date d1 = sdf.parse(birth);  //倒包:java.util
		    //2.将java.util.Date类型转换成java.sql.Date 
			java.sql.Date d2 = new java.sql.Date(d1.getTime()); //完整包名加上
			
			preparedStatement.setDate(5, d2);
			//预编译执行和普通语句执行的方法一致
			//执行时不需要再次指定SQL语句
			int rows = preparedStatement.executeUpdate();
			System.out.println(rows);
		} catch (Exception e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}finally {
			JdbcUtil.close(preparedStatement, connection);
		}
	}

}

输出结果:
运行时在控制台实现
在这里插入图片描述


第二种方法:

根据上面增加的例子我们可以看到date类型转换需要两步,比较麻烦
应该把转换代码封装一下,方便使用

我们依旧在JdbcUtil类中封装

	//String类型转换为java.sql.Data类型封装到一个方法里
	public static java.sql.Date toSqlDate(String string){
		java.util.Date d1 = null;
		java.sql.Date  d2 = null;
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		try {
			d1 = sdf.parse(string);
			d2 = new java.sql.Date(d1.getTime());  //try...catch后写第二次转换
		} catch (ParseException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}

		return d2;  //转换后结果的返回
	}

那现在上面写的InsertDemo(添加)内的转换代码就不需要了,可以删除
第五条preparedStatement方法需要调用一下方法,拿到转换后的SqlDate,把birth字符串传进去:

preparedStatement.setDate(5, JdbcUtil.toSqlDate(birth));

另外,在JdbcUtil内的加载驱动程序代码在实际运行中只运行了一次
在方法前面加上静态代码块,静态代码块的代码在程序中只会运行一次,所以把try…catch内的代码放在static静态代码块中
请添加图片描述

最后JdbcUtil类中代码为:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.ParseException;
import java.text.SimpleDateFormat;

public class JdbcUtil {
	static {
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			//这里不再抛出异常,而是包围它
		} catch (ClassNotFoundException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
	}
//加载驱动程序和创建数据库连接,封装到一个静态代码方法里
public static Connection createConnection() {
		
		Connection connection = null;
		try {
			connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/user?characterEncoding=utf8&serverTimezone=Asia/Shanghai","root","123456");
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		
		return connection;
	}
	
	//释放资源,封装到静态方法中,方便调用
	public static void close(Statement statement,Connection connection) {
		try {
			statement.close();
			connection.close();
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
	}	
	
	public static void close(ResultSet resultSet,Statement statement,Connection connection) {
		//重载
		try {
			resultSet.close();
			statement.close();
			connection.close();
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
	}

	//String类型转换为java.sql.Data类型封装到一个方法里
	public static java.sql.Date toSqlDate(String string){
		java.util.Date d1 = null;
		java.sql.Date  d2 = null;
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		try {
			d1 = sdf.parse(string);
			d2 = new java.sql.Date(d1.getTime());
		} catch (ParseException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}

		return d2;
	}

}

再次运行添加
在这里插入图片描述

JDBC实例删除

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;

import com.jdbc.work.util.JdbcUtil;

public class DeleteDemo {
	public static void main(String[] args) {
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		Scanner scanner = new Scanner(System.in);
		
		connection = JdbcUtil.createConnection();
		try {
			preparedStatement = connection.prepareStatement("delete from user where id=?");
			System.out.println("请输入删除的用户id");
			int id = scanner.nextInt();
			preparedStatement.setInt(1, id);
			int rows = preparedStatement.executeUpdate();
			System.out.println(rows);
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		} finally {
			JdbcUtil.close(preparedStatement, connection);
		}
		
	}

}

运行结果
在这里插入图片描述

JDBC实例修改

根据ID值改其他条件

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;

import com.jdbc.work.util.JdbcUtil;

public class UpdateDemo {
	public static void main(String[] args) {
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		Scanner scanner = new Scanner(System.in);

		connection = JdbcUtil.createConnection();
		try {
			preparedStatement = connection.prepareStatement("update user set name = ?,email=?,phone=?,birth=? where id=?");
			int id,age;
			String name,birth,pwd;

			System.out.println("请输入需要修改的用户id");
			id = scanner.nextInt();
			
			System.out.println("请输入修改后的用户名");
			name = scanner.next();
			
			System.out.println("请输入修改后的用户邮箱");
			String email = scanner.next();
			
			System.out.println("请输入修改后的用户电话");
			String phone = scanner.next();
			
			System.out.println("请输入修改后的用户生日");
			birth = scanner.next();
			
			preparedStatement.setString(1, name);
			preparedStatement.setString(2, email);
			preparedStatement.setString(3, phone);
			preparedStatement.setDate(4, JdbcUtil.toSqlDate(birth));
			preparedStatement.setInt(5, id);
			int rows = preparedStatement.executeUpdate();
			System.out.println(rows);
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}finally {
			JdbcUtil.close(preparedStatement, connection);
		}

	}

}

输出结果:
在这里插入图片描述

JDBC实例查询

模糊查询

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;

import com.jdbc.work.util.JdbcUtil;

public class QueryDemo {
	public static void main(String[] args) {
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		ResultSet resultSet = null;
		Scanner scanner = new Scanner(System.in);
		
		connection = JdbcUtil.createConnection();
		try {
			preparedStatement = connection.prepareStatement("select * from user where name like ?");
			System.out.println("请输入查询的用户名(支持模糊查询)");
			String name = scanner.next();
			preparedStatement.setString(1, "%"+name+"%");
			resultSet = preparedStatement.executeQuery();
			//处理结果集
			while(resultSet.next()) {
				int id = resultSet.getInt("id");
				name = resultSet.getString("name");
				String email = resultSet.getString("email");
				String phone = resultSet.getString("phone");
				Date birth = resultSet.getDate("birth"); 
				System.out.println(id+"\t"+name+"\t"+email+"\t"+phone+"\t"+birth);
			}
			
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}finally {
			JdbcUtil.close(resultSet, preparedStatement, connection);
		}
	}
	
}

这里为了输出美观,已提前在Navicat内更改了数据

输入要查询的数据:
在这里插入图片描述

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐