JDBC(基本概念) - G-holic/Java-Web GitHub Wiki

JDBC:

1.概念:Java Databases Connectivity   Java 数据库连接, Java语言操作数据库
	* JDBC本质:其实是官方(sun公司)定义的一套所有关系型数据库的规则,即接口。
	  各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)
	  编程,真正执行的代码是驱动jar包中的实现类。
	  
2.快速入门:
	* 步骤:
		1.导入驱动jar包   mysql-connector-java-8.0.25.jar
			1.复制 mysql-connector-java-8.0.25.jar 到项目的lib目录下
			2.右键 -->Add As Library
		2.注册驱动
		3.获取数据库连接对象 Connection
		4.定义sql
		5.获取执行sql语句的对象 Statement
		6.执行sql,接受返回结果
		7.处理结果
		8.释放资源 
		
	* 代码实现:
		//1.导入驱动jar包
		//2.注册驱动
		Class.forName("com.mysql.cj.jdbc.Driver");
		//3.获取数据库连接对象
		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/office", "root", "123456");
		//4.定义sql语句
		String sql = "update acount set balance = 500 where id = 1";
		//5.获取执行sql对象 Statement
		Statement stmt = conn.createStatement();
		//6.执行sql
		int count = stmt.executeUpdate(sql);
		//7.处理结果
		System.out.println(count);
		//8.释放资源
		stmt.close();
		conn.close();
	
3.详解各个对象:
	1.DriverManager:驱动管理对象
		* 功能:
			1.注册驱动:告诉我们程序该使用哪一个数据库驱动jar包
				static void registerDriver(Driver driver):注册与给定的驱动程序  DriverManager。
				写代码使用:Class.forName("com.mysql.cj.jdbc.Driver");
				通过查看源码发现:在com.mysql.cj.jdbc.Driver 类中存在静态代码块
					static {
							try {
								java.sql.DriverManager.registerDriver(new Driver());
							} catch (SQLEXception E){
								throw new RuntimeException("Can't register driver!");
							}
						}
						
					注意:mysql5之后的驱动jar包可以省略注册驱动的步骤。
			2. 获取数据库连接:
				* 方法:static Connection getConnection(String url, String user, String password)
				* 参数:
					* url:指定连接路径
						* 语法:jdbc:mysql://IP地址(域名):端口号/数据库名称
						* 例子:jdbc:mysql://localhost:3306/office						
					* user:用户
					* password:密码
	2.Connection:数据库连接对象
		1.功能:
			1.获取执行sql对象
				* Statement createStatement()
				* PreparedStatement prepareStatement(String sql)
			2.管理事务:
				* 开启事务:void setAutocommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
				* 提交事务:commit
				* 回滚事务:rollback()
	3.Statement:执行sql的对象
		1.执行sql
			1.boolean excute(String sql) :可以执行任意的sql 了解(可能返回多个结果)
			2.int executeUpdate(String sql) :执行DML(insert、update、delete)语句、DDL(create、alter、drop)语句(无返回结果)。
				* 返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功 ,返回值>0则执行成功,反之,则失败。(DML)
			3.ResultSet executeQuery(String url) :执行DQL语句(select)语句
		2.练习:
			1.acount表 添加一条记录
			2.acount表 修改记录
			3.acount表 删除一条记录
			* 代码:
			public static void main(String[] args) throws Exception {
				//1.注册驱动
				Class.forName("com.mysql.cj.jdbc.Driver");
				//2.获取数据库连接对象
				Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/office","root","123456");
				//3.定义sql语句
				String sql = "delete from acount where  id in (7,8)";
				//4.获取执行sql的对象
				Statement stmt = conn.createStatement();
				//5.执行sql语句
				int count = stmt.executeUpdate(sql);
				//6.处理结果
				if (count > 0){
					System.out.println("添加成功!");
				}else {
					System.out.println("添加失败!");
				}
					//7.释放资源
					stmt.close();
					conn.close();
				}
			* 代码:
			public static void main(String[] args) {
				Statement stmt = null;
				Connection conn = null;
				try {
					//1.注册驱动
					Class.forName("com.mysql.cj.jdbc.Driver");
					//2.获取数据库连接对象
					conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/office","root","123456");
					//3.定义sql
					String sql = "insert into acount values (4,'王五',5000) ";
					//4.获取执行sql的对象
					stmt = conn.createStatement();
					//5.执行sql
					int count = stmt.executeUpdate(sql);//影响的行数
					//6.处理结果
					if (count > 0){
						System.out.println("添加成功!");
					}else {
						System.out.println("添加失败!");
					}
				} catch (ClassNotFoundException | SQLException e) {
					e.printStackTrace();
				}finally {
					//stmt.close();
					//避免空指针异常
					//7.释放资源
					if (stmt != null){
						try {
							stmt.close();
						} catch (SQLException throwables) {
							throwables.printStackTrace();
						}
					 if (conn != null) {
						 try {
							 conn.close();
						 } catch (SQLException throwables) {
							 throwables.printStackTrace();
						 }
					 }

					}
				}
			}
	4.ResultSet:结果集对象,封装查询结果
		* boolean next():游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,不是则true
		* getXxx(参数):获取数据
			* Xxx:代表数据类型  如:int getInt(), String getString()
			* 参数:
				1.int;代表列的编号,从 1 开始   如:geString(1)
				2.String:代表列名称。  如:getDouble("balance")
				
		* 注意: 
			* 使用步骤:
				1.游标向下移动一行
				2.判断是否有数据
				3.获取数据
				// 循环判断是否是最后一行末尾。
				while (rs.next()) {
					//6.2获取数据
					int id = rs.getInt(1);
					String name = rs.getString("name");
					double banlance = rs.getDouble(3);
					System.out.println(id + "---" + name + "---" + banlance);
				}
				
		* 练习: 
			* 定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,返回。
				1.定义Emp类
				2.定义方法public List<Emp> findAll(){}
				3.实现方法 select * from emp;
				
			* 代码实现:
				package cn.itcast.jdbc;
				import cn.itcast.domain.Emp;
				import java.sql.*;
				import java.util.ArrayList;
				import java.util.List;
				/**
				 * 定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,返回。
				 */
				public class JdbcDemo8 {
					public static void main(String[] args) throws Exception {
						List<Emp> list = new JdbcDemo8().findAll();
						System.out.println(list);
						System.out.println(list.size());
					}
					/**
					 * 查询所有emp对象
					 * @return
					 */
					public List<Emp> findAll() throws Exception {
						//1.注册驱动
						Class.forName("com.mysql.cj.jdbc.Driver");
						//2.获取数据库连接
						Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test1", "root", "123456");
						//3.定义sql
						String sql = "select * from emp";
						//4.获取执行sql对象
						Statement stmt = conn.createStatement();
						//5.执行sql语句
						ResultSet rs = stmt.executeQuery(sql);
						//6.遍历结果集,封装对象,装载集合
						Emp emp = null;
						List<Emp> list = new ArrayList<Emp>();
						while (rs.next()){
							int id = rs.getInt("id");
							String ename = rs.getString("ename");
							int job_id = rs.getInt("job_id");
							int mgr = rs.getInt("mgr");
							Date joidate = rs.getDate("joidate");
							double salary = rs.getDouble("salary");
							double bonus = rs.getDouble("bonus");
							int dept_id = rs.getInt("dept_id");
							//创建emp对象,并赋值
							emp = new Emp();
							emp.setId(id);
							emp.setEname(ename);
							emp.setJob_id(job_id);
							emp.setMgr(mgr);
							emp.setJoidate(joidate);
							emp.setSalary(salary);
							emp.setBonus(bonus);
							emp.setBonus(bonus);
							emp.setDept_id(dept_id);
							//装载集合
							list.add(emp);
						}
						rs.close();
						stmt.close();
						conn.close();
						return list;
					}
				}

	5.PreparedStatement:执行sql对象
		1.SQL注入问题:在拼接sql时,有一些sql的特殊关键字与字符串的拼接。会造成安全性问题
			1.输入用户随便,输入密码:a' or 'a' = 'a
			2.sql:select * from user where username = 'gsadga' and password = a' or 'a' = 'a;
		
		2.解决sql注入问题:使用PreparedStatement对象来解决
		3.预编译的SQl:参数使用?作为占位符
		4.步骤:
			1.导入驱动jar包   mysql-connector-java-8.0.25.jar
					1.复制 mysql-connector-java-8.0.25.jar 到项目的lib目录下
					2.右键 -->Add As Library
			2.注册驱动
			3.获取数据库连接对象 Connection
			4.定义sql
				* 注意:sql的参数使用?作为占位符。如:select * from user where username = ? and password = ?;
			5.获取执行sql语句的对象 PreparedStatement  Connection.prepareStatement(String sql)
			6.给?赋值:
				* 方法:setXxx(参数1,参数2)
					* 参数1:?的位置 从1开始
					* 参数2:?的值
			7.执行sql,接受返回结果,不需要传递sql语句
			8.处理结果
			9.释放资源 
		5.注意:后期都会使用使用PreparedStatement对象来完成增删改查的所有操作
			1.可以防止SQL注入
			2. 效率更高
⚠️ **GitHub.com Fallback** ⚠️