【java】第十八章、使用JDBC操作数据库

一、数据库基础

在这里插入图片描述
在这里插入图片描述
单靠客户端或者服务器管理这些数据是不可能的,所以就出现了数据库的概念
将所有数据都放在数据库中保存,程序需要什么样的数据,直接让数据库提供相关的数据就可以了
程序把管理数据的功能分离了出去,既可以减轻程序的负荷,又能减少程序所占的硬盘大小,这是一个非常好的开发模式
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、JDBC简介

在这里插入图片描述
JDBC技术是数据库与java应用程序间的纽带***
程序用java代码写,而程序产生的数据往往存在了数据库这一端,两个分离的程序需要一个连接的桥梁,这个桥梁就是JDBC技术
JDBC可以
将程序需要执行的SQL语句传递给数据库,也可以将数据库查到的结果传递给程序
*(但JDBC并不能直接访问数据库,必须依赖于数据库厂商提供的驱动程序
每一种数据库都有独立的驱动jar包,这就使得JDBC连接数据库的底层机制都不一样,但JDBC提供给程序的接口是保持不变的
DriverManager类:每种数据库的驱动都不一样,我们需要在这里指定数据库的驱动类型,并配置好要连接的数据库地址和账号密码
因为连接数据库涉及到了数据流的操作,所以在使用完这些连接之后要及时关闭,顺序是从下往上依次关闭

三、链接数据库

在这里插入图片描述
**注意:**在运行这行代码时,必须要保证驱动包已经导入进来了。(若没有导入驱动包而直接加载驱动的话,它会报出一个类找不到的异常)
通过DriverManager.getConnection()方法获得数据库的连接对象(第一个参数是数据库的URL,后面是数据库的账号密码),这样就创建了一个Connection对象
在这里插入图片描述
在这里插入图片描述

package c11;

import java.sql.*;

public class L11_01_DBUtils {
	// 数据库驱动程序
	private static String DRIVERCLASS = "com.mysql.cj.jdbc.Driver";
	// 连接数据的URL
	private static String URL = "jdbc:mysql://localhost:3306/test";
	// 连接数据库的用户名和密码
	private static String USERNAME = "root";
	private static String PASSWORD = "123456";

	/**
	 * 获取数据库连接对象
	 * 
	 * @throws SQLException
	 */
	public Connection getConnection() throws ClassNotFoundException, SQLException {
		// 加载驱动程序
		Class.forName(DRIVERCLASS);
		// 建立与MySQL数据库的连接
		Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
		return conn;
	}

	/**
	 * 关闭连接对象,释放资源
	 */
	public void close(ResultSet rs, Statement stmt, Connection conn) {
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		L11_01_DBUtils dbUtils = new L11_01_DBUtils();
		Connection conn = null;
		try {
			conn = dbUtils.getConnection();
			System.out.println("数据库连接成功-" + conn);
		} catch (ClassNotFoundException e) {
			System.out.println("数据库连接失败-" + e.getMessage());
		} catch (SQLException e) {
			System.out.println("数据库连接失败-" + e.getMessage());
		} finally {
			dbUtils.close(null, null, conn);
		}
	}
}

四、数据库查询

在这里插入图片描述
Connection对象提供了一个程序到数据库的连接
查询数据库内容:创建Statement接口对象
ResultSet接口:将数据库返回的结果放入结果集中

创建接口对象

在这里插入图片描述

ResultSet接口常用方法

ResultSet结果集有个特点:指针(最开始没有指向任何一个位置)
在这里插入图片描述
我们获取到一行数据之后,需要将一行里的数据拆分开(ResultSet有多种返回类型,每一种方法都有两种重载方式,也就是两种参数)
在这里插入图片描述
在这里插入图片描述
其中,列数必须是大于等于1的正整数
finally代码块中:从后往前关闭数据流

package query;

import java.sql.*;

public class Query {
	// 数据库驱动程序
	private static String DRIVERCLASS = "com.mysql.cj.jdbc.Driver";
	// 连接数据的URL
	private static String URL = "jdbc:mysql://localhost:3306/test";
	// 连接数据库的用户名和密码
	private static String USERNAME = "root";
	private static String PASSWORD = "123456";

	/**
	 * 获取数据库连接对象
	 * 
	 * @throws SQLException
	 */
	public Connection getConnection() throws ClassNotFoundException, SQLException {
		// 加载驱动程序
		Class.forName(DRIVERCLASS);
		// 建立与MySQL数据库的连接
		Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
		return conn;
	}

	/**
	 * 关闭连接对象,释放资源
	 */
	public void close(ResultSet rs, Statement stmt, Connection conn) {
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		Query qry = new Query();
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			conn = qry.getConnection();
			stmt = conn.createStatement();   //创建Statement对象
			rs = stmt.executeQuery("select * from user");    //注意:可以不写分号
			while(rs.next()) {               //下一行数据
				int id = rs.getInt("id");    //获取id这一列的值
				String name = rs.getString(2);    //获取第二列的值
				String phone = rs.getString("phone"); 
				String email = rs.getString(4);
				System.out.println("编号=" + id + " 姓名=" + name + " 电话=" + phone + " 邮箱=" + email);
			}		
//			System.out.println("数据库连接成功-" + conn);
		} catch (ClassNotFoundException e) {
			System.out.println("数据库连接失败-" + e.getMessage());
		} catch (SQLException e) {
			System.out.println("数据库连接失败-" + e.getMessage());
		} finally {
			qry.close(rs, stmt, conn);
		}
	}
}

在这里插入图片描述

五、添加、修改和删除数据

添加、修改和删除数据用到的都是一个方法:executeUpdate()
在这里插入图片描述
用statement接口执行插入、修改、删除这三个sql:

package update;

import java.sql.*;

public class Update {
	// 数据库驱动程序
	private static String DRIVERCLASS = "com.mysql.cj.jdbc.Driver";
	// 连接数据的URL
	private static String URL = "jdbc:mysql://localhost:3306/test";
	// 连接数据库的用户名和密码
	private static String USERNAME = "root";
	private static String PASSWORD = "123456";

	/**
	 * 获取数据库连接对象
	 * 
	 * @throws SQLException
	 */
	public Connection getConnection() throws ClassNotFoundException, SQLException {
		// 加载驱动程序
		Class.forName(DRIVERCLASS);
		// 建立与MySQL数据库的连接
		Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
		return conn;
	}

	/**
	 * 关闭连接对象,释放资源
	 */
	public void close(ResultSet rs, Statement stmt, Connection conn) {
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		Update upd = new Update();
		Connection conn = null;
		Statement stmt = null;
		
		try {
			conn = upd.getConnection();
			stmt = conn.createStatement();   //创建Statement对象
			
			//插入数据
			String sql1 = "insert into user(name, phone, email) values('tom', '123456', 'vrf@42few.com')";
			int result1 = stmt.executeUpdate(sql1);
			System.out.println("有" + result1 + "行记录被修改");
			
			//修改数据
			String sql2 = "update user set phone = '999999' where name = 'tom'";
			int result2 = stmt.executeUpdate(sql2);
			System.out.println("有" + result2 + "行记录被修改");
			
			//删除数据
			String sql3 = "delete from user where name = 'tom'";
			int result3 = stmt.executeUpdate(sql3);
			System.out.println("有" + result3 + "行记录被修改");
			
//			System.out.println("数据库连接成功-" + conn);
		} catch (ClassNotFoundException e) {
			System.out.println("数据库连接失败-" + e.getMessage());
		} catch (SQLException e) {
			System.out.println("数据库连接失败-" + e.getMessage());
		} finally {
			upd.close(null, stmt, conn);
		}
	}
}

在这里插入图片描述
在这里插入图片描述

六、批处理

在这里插入图片描述
一次运行很多条sql语句,用之前讲过的方法:
先创建Statement接口,然后调用它的executeUpdate()方法,执行第一句sql后关闭;然后再创建一个Statement对象,执行第二个sql,执行完关闭…直到将所有sql都运行完
代码量太大
所以Statement提供了批量操作的功能:
在这里插入图片描述

package batch;

import java.sql.*;

public class Batch {
	// 数据库驱动程序
	private static String DRIVERCLASS = "com.mysql.cj.jdbc.Driver";
	// 连接数据的URL
	private static String URL = "jdbc:mysql://localhost:3306/test";
	// 连接数据库的用户名和密码
	private static String USERNAME = "root";
	private static String PASSWORD = "123456";

	/**
	 * 获取数据库连接对象
	 * 
	 * @throws SQLException
	 */
	public Connection getConnection() throws ClassNotFoundException, SQLException {
		// 加载驱动程序
		Class.forName(DRIVERCLASS);
		// 建立与MySQL数据库的连接
		Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
		return conn;
	}

	/**
	 * 关闭连接对象,释放资源
	 */
	public void close(ResultSet rs, Statement stmt, Connection conn) {
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		Batch bat = new Batch();
		Connection conn = null;
		Statement stmt = null;
		
		try {
			conn = bat.getConnection();
			stmt = conn.createStatement();
			stmt.addBatch("insert into user(name, phone, email) values('阿呆', '4532435', 'we@34f.com')");
			stmt.addBatch("insert into user(name, phone, email) values('翠花', '9348235', 'nuy@43df.com')");
			stmt.addBatch("insert into user(name, phone, email) values('二蛋', '4598871', 'jij@879hu.com')");
			
			int results[] = stmt.executeBatch();
			for(int result: results) {
				System.out.println("影响的行数为:" + result);
			}
			
//			System.out.println("数据库连接成功-" + conn);
		} catch (ClassNotFoundException e) {
			System.out.println("数据库连接失败-" + e.getMessage());
		} catch (SQLException e) {
			System.out.println("数据库连接失败-" + e.getMessage());
		} finally {
			bat.close(null, stmt, conn);
		}
	}
}

在这里插入图片描述
在这里插入图片描述
我们调用了executeBatch()方法,执行列表中的sql,一次性执行这样能大大提高执行效率

七、动态查询

系统安全漏洞:sql注入
在这里插入图片描述
在这里插入图片描述
为了防止这种sql注入,JDBC提供了一种简单并实用的功能:动态查询
在这里插入图片描述
sql中有一个问号,这个问号叫做通配符:起占位作用(因为是动态查询,也就是说在查询之前,这句sql到底要查什么,谁都不知道)
在这里插入图片描述
PreparedStatement提供了很多方法,它可以给通配符赋值。
这种动态查询的效果有效避免了sql注入的问题

package dynamic_query;

import java.sql.*;

public class Dy_query {
	// 数据库驱动程序
	private static String DRIVERCLASS = "com.mysql.cj.jdbc.Driver";
	// 连接数据的URL
	private static String URL = "jdbc:mysql://localhost:3306/test";
	// 连接数据库的用户名和密码
	private static String USERNAME = "root";
	private static String PASSWORD = "123456";

	/**
	 * 获取数据库连接对象
	 * 
	 * @throws SQLException
	 */
	public Connection getConnection() throws ClassNotFoundException, SQLException {
		// 加载驱动程序
		Class.forName(DRIVERCLASS);
		// 建立与MySQL数据库的连接
		Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
		return conn;
	}

	/**
	 * 关闭连接对象,释放资源
	 */
	public void close(ResultSet rs, Statement stmt, Connection conn) {
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		Dy_query dquery = new Dy_query();
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;

		try {
			conn = dquery.getConnection();
			
			String sql = "select * from user where name = ? or phone = ?";
			ps = conn.prepareStatement(sql);
			
			ps.setString(1, "阿呆");
			ps.setString(2, "3478345");
			
			rs = ps.executeQuery();
			System.out.println("id\tname\tphone\temail");
			while(rs.next()) {
				System.out.println(rs.getInt(1) + "\t" + rs.getString(2) + "\t" + rs.getString(3) + "\t" + rs.getString(4));
			}

//				System.out.println("数据库连接成功-" + conn);
		} catch (ClassNotFoundException e) {
			System.out.println("数据库连接失败-" + e.getMessage());
		} catch (SQLException e) {
			System.out.println("数据库连接失败-" + e.getMessage());
		} finally {
			dquery.close(rs, ps, conn);
		}
	}
}

在这里插入图片描述

String sql = "select * from user where name like ? and phone = ?";
			ps = conn.prepareStatement(sql);
			
			ps.setString(1, "二%");
			ps.setString(2, "4598871");
			
			rs = ps.executeQuery();
			System.out.println("id\tname\tphone\temail");
			while(rs.next()) {
				System.out.println(rs.getInt(1) + "\t" + rs.getString(2) + "\t" + rs.getString(3) + "\t" + rs.getString(4));
			}

在这里插入图片描述
给动态sql赋完值后,去创建结果集对象
注意:它和Statement不一样,因为它创建对象时调用的这个方法是con.prepareStatement()【并且它返回结果集的时候没有参数,因为它创建对象时就要指定sql】;而Statement创建对象时调用con.createStatement()

八、调用存储过程

用java程序去调用数据库中的存储过程
在这里插入图片描述

package call_stored_procedure;

import java.sql.*;

public class Calling_Stored_Procedure {
	// 数据库驱动程序
	private static String DRIVERCLASS = "com.mysql.cj.jdbc.Driver";
	// 连接数据的URL
	private static String URL = "jdbc:mysql://localhost:3306/test";
	// 连接数据库的用户名和密码
	private static String USERNAME = "root";
	private static String PASSWORD = "123456";

	/**
	 * 获取数据库连接对象
	 * 
	 * @throws SQLException
	 */
	public Connection getConnection() throws ClassNotFoundException, SQLException {
		// 加载驱动程序
		Class.forName(DRIVERCLASS);
		// 建立与MySQL数据库的连接
		Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
		return conn;
	}

	/**
	 * 关闭连接对象,释放资源
	 */
	public void close(ResultSet rs, Statement stmt, Connection conn) {
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		Calling_Stored_Procedure call_sp = new Calling_Stored_Procedure();
		Connection conn = null;
		CallableStatement call = null;
		ResultSet rs = null;
		
		try {
			conn = call_sp.getConnection();
			call = conn.prepareCall("{call dd(?)}");
			call.setInt(1,4);
			rs = call.executeQuery();
			System.out.println("name");
			while(rs.next()) {
				System.out.println(rs.getString(1));
			}
				
//			System.out.println("数据库连接成功-" + conn);
		} catch (ClassNotFoundException e) {
			System.out.println("数据库连接失败-" + e.getMessage());
		} catch (SQLException e) {
			System.out.println("数据库连接失败-" + e.getMessage());
		} finally {
			call_sp.close(rs, call, conn);
		}
	}
}

在这里插入图片描述

在控制台创建并调用存储过程(只有一个输入参数)

在这里插入图片描述

在控制台创建并调用存储过程(一个输入参数,一个输出参数)

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值