Java语法进阶及常用技术(一)--JDBC入门

JDBC入门

一、什么是JDBC

Java数据库连接-Java DataBase Connectivity
JDBC可让Java通过程序操作关系型数据库
JDBC基于驱动程序实现与数据库的连接与操作
在这里插入图片描述

1、JDBC的优点

统一的API,提供一致的开发过程
易于学习,容易上手,代码结构稳定
功能强大,执行效率高,可处理海量数据

二、JDBC驱动的秘密

1、创建数据库连接代码

在这里插入图片描述
Class.forName的作用:
用于加载指定的JDBC驱动类。
本质是通过JDBC注册这个驱动类。
驱动由数据库厂商自行开发,连接字符串也不同。
在这里插入图片描述
DriverManager
用于注册/管理JDBC驱动程序。
DriverManager.getConnection(连接字符串,用户名,密码)
返回值Connection对象,对应数据库的物理网络连接。
Connection对象
用于JDBC与数据库的网络通信对象。
java.sql.Connection是一个接口,具体由驱动厂商实现。
所有数据库的操作都建立在Connection基础上。
在这里插入图片描述
MySQL连接字符串
格式:jdbc:mysql://[主机ip][:端口]/数据库名?参数列表
主机ip与端口是可选设置,默认值为127.0.0.1与3306
参数列表采用url编码,格式:参数1=值1&参数2=值2&…
在这里插入图片描述

三、JDBC开发流程

public class QueryCommand implements Command{
	public void execute(){
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try{
		//1.加载并注册JDBC驱动
		Class.forName("com.mysql.cj.jdbc.Driver");
		//2.创建数据库连接
		conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/databaseName?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrievel=true","root","root");
		//3.创建Statement对象
		stmt = conn.createStatement();
		//结果集
		rs = stmt.executeQuery("select * from employee where dname='研发部'");
		//4.遍历查询结果
		//rs.next()返回布尔值,代表是否存在下一条记录
		//如果有,返回true,同时结果集提取下一条记录
		//如果没有,返回false,循环会停止
		while(rs.next()){
			Integer eno = rs.getInt(1);//JDBC中字段索引从1开始,而非0
			String ename = rs.getString("ename");
			sout(eno+":"+ename);
		}
		}catch(ClassNotFoundException e){
			e.printStackTrace();
		}catch(SQLException e){
			e.printStackTrace();
		}finally{
			//5.关闭连接,释放资源
			try{
				if(rs!=null){
					rs.close();
				}
			}catch(SQLException e){
				e.printStackTrace();
			}
			try{
				if(stmt!=null){
					stmt.close();
				}
			}catch(SQLException e){
				e.printStackTrace();
			}
			try{
				if(conn!=null){
					conn.close();
				}
			}catch(SQLException e){
				e.printStackTrace();
			}
		}
	}
}

四、PreparedStatement

1、SQL注入攻击

SQL注入攻击是指利用SQL漏铜越权获取数据的黑客行为。
SQL注入攻击根源是未对原始SQL中的敏感字符做特殊处理。
解决方法:放弃Statement改用PreparedStatement处理SQL。

2、PreparedStatement

PreparedStatement 预编译Statement是Statement的子接口。
PreparedStatement对SQL进行参数化,预防SQL注入攻击。
原始代码:
在这里插入图片描述
用PreparedStatement改造之后的代码:
在这里插入图片描述

3、PreparedStatement开发流程

public class PstmtQueryCommand implements Command{
	public void execute(){
		System.out.print("请输入部门名称:");
		Scanner in = new Scanner(System.in);
		String pdname = in.nextLine();
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try{
		//1.加载并注册JDBC驱动
		Class.forName("com.mysql.cj.jdbc.Driver");
		//2.创建数据库连接
		conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/databaseName?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrievel=true","root","root");
		//3.创建Statement对象
		String sql = "select * from employee where dname = ? ";
		pstmt = conn.prepareStatement(sql);
		pstmt.setString(1, pdname);//注意:参数索引从1开始
		//结果集
		rs = pstmt.executeQuery();
		//4.遍历查询结果
		//rs.next()返回布尔值,代表是否存在下一条记录
		//如果有,返回true,同时结果集提取下一条记录
		//如果没有,返回false,循环会停止
		while(rs.next()){
			Integer eno = rs.getInt(1);//JDBC中字段索引从1开始,而非0
			String ename = rs.getString("ename");
			sout(eno+":"+ename);
		}
		}catch(ClassNotFoundException e){
			e.printStackTrace();
		}catch(SQLException e){
			e.printStackTrace();
		}finally{
			//5.关闭连接,释放资源
			try{
				if(rs!=null){
					rs.close();
				}
			}catch(SQLException e){
				e.printStackTrace();
			}
			try{
				if(stmt!=null){
					stmt.close();
				}
			}catch(SQLException e){
				e.printStackTrace();
			}
			try{
				if(conn!=null){
					conn.close();
				}
			}catch(SQLException e){
				e.printStackTrace();
			}
		}
	}
}

错误的使用方式
select * from employee where ?=‘abc’
select * from employee where salary = ?+100
select ? from employee where ename = ?

五、封装DbUtils工具类

public class DbUtils{
	//创建新的数据库连接
	public static Connection getConnection() throws SQLException, ClassNotFoundException{
		//1.加载并注册JDBC驱动
		Class.forName("com.mysql.cj.jdbc.Driver");
		//2.创建数据库连接
		Connection  conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/databaseName?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrievel=true","root","root");
		return conn;
	}
	//关闭连接,释放资源
	public static void closeConnection(ResultSet rs, Statement stmt, Connection conn){
		try{
			if(rs!=null){
				rs.close();
			}
		}catch(SQLException e){
			e.printStackTrace();
		}
		try{
			if(stmt!=null){
				stmt.close();
			}
		}catch(SQLException e){
			e.printStackTrace();
		}
		try{
			if(conn!=null){
				conn.close();
			}
		}catch(SQLException e){
			e.printStackTrace();
		}
	}
}

六、JDBC实现写数据

1、JDBC执行INSERT语句

在这里插入图片描述

2、JDBC执行UPDATE语句

在这里插入图片描述

3、JDBC执行DELETE语句

在这里插入图片描述

七、JDBC事务管理

1、什么是事务

事务是以一种可靠的、一致的方式,访问和操作数据库的程序单元。
说人话:要么把事情做完,要么什么都不做,不做一半。
事务依赖于数据库实现,MySQL通过事务区作为数据缓冲地带。
事务的提交操作
在这里插入图片描述
事务的回滚操作
在这里插入图片描述

2、JDBC两种事务模式

自动提交事务模式
指每执行一次写操作SQL,自动提交事务。
自动提交开启方法:conn.setAutoCommit(true)
自动事务是JDBC默认行为,此模式无法保证多数据一致性

手动提交事务模式
指显式调用commit()与rollback()方法管理事务
手动提交开启方法:conn.setAutoCommit(false)
手动提交事务可以保证数据一致性,但必须手动调用提交/回滚方法

3、JDBC事务案例

一次性新增1000名员工:

public class TransactionSample{
	public static void main(String[] args){
		Connection conn = null;
		PreparedStatement pstmt = null;
		try{
			conn = DbUtils.getConnection();
			conn.setAutoCommit(false);//关闭自动提交
			String sql = "insert into employee(eno,ename,salary,dname) values (?,?,?,?)";
			for(int i=1000;i<2000;i++){
				if(i==1005){
					throw new RuntimeException("插入失败");
				}
				pstmt= conn.prepareStatement(sql);
				pstmt.setInt(1,i);
				pstmt.setString(2,"员工"+i);
				pstmt.setFloat(3, 4000f);
				pstmt.setString(4,"市场部");
				pstmt.executeUpdate();
			}
			conn.commit();
		}catch(Exception e){
			e.printStackTrace();
			try{
				if(conn!=null && !conn.isClosed()){
					conn.rollback();//回滚数据
				}
			}catch(SQLException ex){
				ex.printStackTrace();
			}
		}finally{
			DbUtils.closeConnection(null,pstmt,conn);
		}
	}
}

八、JDBC常用技巧

1、基于实体类实现分页数据封装

....
conn = DbUtils.getConnection();
String sql = "select * from employee limit ?,10";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, (page-1)*10);
rs = pstmt.executeQuery();
while(rs.next()){
	Integer eno = rs.getInt("eno");
	String ename = rs.getString("ename");
	Employee emp = new Employee();
	emp.setEno(eno);
	emp.setEname(ename);
	list.add(emp);
}
...

2、JDBC中Date日期对象处理

JDBC对MySQL数据库中的date和datetime类型的处理是一样的。
在封装实体类时常用java.util包中的Date类。

...
//JDBC查询时间返回的是java.sql.Date类型
java.sql.Date createTime = rs.getDate("create_time");
//java.sql.Date类型是继承自java.util.Date类型,所以把返回结果可以直接set到实体对象的java.util.Date类型的属性
emp.setCreateTime(createTime);
...

在新增操作时需要把字符串转换成java.sql.Date类型

...
String createTime = "2022-03-10 22:04:00";
//1.String转为java.util.Date
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
java.util.Date udCreateTime = sdf.parse(createTime);
//2.java.util.Date转为java.sql.Date
long time = udCreateTime.getTime();//获取自1970年到现在的毫秒数
java.sql.Date sdCreateTime = new java.sql.Date(time);
pstmt.setDate(1, sdCreateTime);
...

3、JDBC数据批处理

...
String sql = "insert into employee(eno,ename,salary,dname) values (?,?,?,?)";
pstmt= conn.prepareStatement(sql);
for(int i=1000;i<2000;i++){
	//pstmt= conn.prepareStatement(sql);
	pstmt.setInt(1,i);
	pstmt.setString(2,"员工"+i);
	pstmt.setFloat(3, 4000f);
	pstmt.setString(4,"市场部");
	pstmt.addBatch();//将参数加入批处理任务
	//pstmt.executeUpdate();
}
pstmt.executeBatch();//执行批处理任务
...
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值