JDBC(Java Data Base Connectivity,Java数据库连接)是一种用于执行SQL语句的Java API,它是一种用Java语言编写的类与接口,是Java访问数据库的标准规范。
JDBC需要连接驱动,驱动是两个设备要进行通信,满足一定通信数据格式,数据格式由设备的提供商规定,设备提供商为设备提供驱动软件,通信软件可以与该设备进行通信。
JDBC原理
JDBC是接口,驱动是接口的实现,没有驱动将无法完成数据库的连接,从而不能操作数据库!每个数据库厂商都需要提供自己的驱动,用来连接自己公司的数据库,也就是说驱动一般都由数据库生成厂商提供,自己只要会用就行。
JDBC开发步骤
1、注册驱动
告知JVM使用的是哪一类数据库的驱动
2、获得连接
使用JDBC中的类,完成对MySQL数据库的连接
3、获得语句执行平台
通过连接对象获取对SQL语句的执行者对象
4、执行SQL语句
使用执行者对象,向数据库执行SQL语句
获取到数据库的执行后的结果
5、返回结果集
6、释放资源(先开的后关)
调用一堆close()方法
导入驱动jar包
创建lib目录,用于存放当前项目需要的所有jar包
选择jar包,右键执行build path / Add to Build Path
开发第一步:注册驱动
使用Class.forName("com.mysql.jdbc.Driver"); 加载一个使用字符串描述的驱动类。
使用Class.forName()将类加载到内存,该类的静态代码块将自动执行。
查询com.mysql.jdbc.Driver源码,发现Driver类“主动”将自己进行注册 所以此时直接用Class.forName()直接将类加载到内存中,而不在重新注册 public class Driver extends NonRegisteringDriver implements java.sql.Driver { static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } } …… }
开发第二步:获得连接
获取连接的方法是DriverManager的getConnection(url,username,password)方法
url="jdbc:mysql://主机IP:端口号/数据库名"
例如:String url = "jdbc:mysql://localhost:3306/demo_jdbc?characterEncoding=utf-8";
String url = "jdbc:mysql://localhost:3306/demo_jdbc?characterEncoding=utf-8";
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
开发第三步:获取语句执行平台
Statement sta = conn.createStatement();
开发第四步:执行sql语句
String sql="某sql语句";
int row=sta.executeUpdate(sql); //executeUpdate 返回SQL语句执行后的行数
开发第五步:返回结果集
System.out.println(row);
开发第六步:释放资源(先开的后关)
例如:sta.close();
conn.close();
SQL注入问题
假设有登录案例SQL语句如下:
SELECT * FROM 用户表 WHERE NAME = 用户输入的用户名 AND PASSWORD = 用户输的密码;
此时,当用户输入正确的账号与密码后,查询到了信息则让用户登录。但是当用户输入的账号为XXX 密码为:XXX’ OR ‘a’=’a时,则真正执行的代码变为:
SELECT * FROM 用户表 WHERE NAME = ‘XXX’ AND PASSWORD =’ XXX’ OR ’a’=’a’;
此时,上述查询语句时永远可以查询出结果的。那么用户就直接登录成功了,显然我们不希望看到这样的结果,这便是SQL注入问题。
为此,我们使用PreparedStatement来解决对应的问题。
PreparedStatement预处理对象
String sql="某SQL执行语句";
PreparedStatement pst =conn.prepareStatement(sql);
执行SQL语句
int executeUpdate(); --执行insert update delete语句.
ResultSet executeQuery(); --执行select语句.
boolean execute(); --执行select返回true 执行其他的语句返回false.
设置实际参数
void setXxx(int index, Xxx xx) 将指定参数设置为给定Java的xx值。在将此值发送到数据库时,驱动程序将它转换成一个 SQL Xxx类型值。
预处理对象的executeUpdate方法
插入insert public void demo01() throws Exception { // 1注册驱动 Class.forName("com.mysql.jdbc.Driver"); // 2获取连接 Connection conn = DriverManager.getConnection ("jdbc:mysql://localhost:3306/mydb", "username", "password"); // 3获得预处理对象 String sql = "insert into sort(sname) values(?)"; PreparedStatement pst = conn.prepareStatement(sql); // 4 SQL语句占位符设置实际参数 pst.setString(1, "奢侈品"); // 5执行SQL语句 int line =pst.executeUpdate(); System.out.println("新添加记录数:" + line); // 6释放资源 pst.close(); conn.close(); }
更新update public void demo02() throws Exception { // 1注册驱动 Class.forName("com.mysql.jdbc.Driver"); // 2获取连接 Connection conn = DriverManager.getConnection ("jdbc:mysql://localhost:3306/mydb", "username", "password"); // 3获得预处理对象中 String sql = "update sort set sname=? where sid=?"; PreparedStatement pst = conn.prepareStatement(sql); // 4 SQL语句占位符设置实际参数 pst.setString(1, "数码产品"); pst.setInt(2, 1); // 5执行SQL语句 int line = pst.executeUpdate(); System.out.println("更新记录数:" + line); // 6释放资源 pst.close(); conn.close(); }
删除delete public void demo03() throws Exception { // 1注册驱动 Class.forName("com.mysql.jdbc.Driver"); // 2获取连接 Connection conn = DriverManager.getConnection ("jdbc:mysql://localhost:3306/mydb", "username", "password"); // 3获得预处理对象 String sql = "delete from sort where sid=?"; PreparedStatement pst = conn.prepareStatement(sql); // 4 SQL语句占位符设置实际参数 pst.setInt(1, 1); // 5执行SQL语句 int line = pst.executeUpdate(); System.out.println("删除记录数:" + line); // 6释放资源 pst.close(); conn.close(); }
预处理对象executeQuery方法
实现查询分类表所有记录 public void demo04() throws Exception { // 1注册驱动 Class.forName("com.mysql.jdbc.Driver"); // 2获取连接 Connection conn = DriverManager.getConnection ("jdbc:mysql://localhost:3306/mydb", "username", "password"); // 3获得预处理对象 String sql = "select * from sort"; PreparedStatement pst = conn.prepareStatement(sql); // 4 SQL语句占位符设置实际参数 // 5执行SQL语句 ResultSet rs = pst.executeQuery(); // 6处理结果集(遍历结果集合) while( rs.next() ){ //获取当前行的分类ID String sid = rs.getString("sid");//方法参数为数据库表中的列名 //获取当前行的分类名称 String sname = rs.getString("sname"); //显示数据 System.out.println(sid+"-----"+sname); } // 7释放资源 rs.close(); pst.close(); conn.close(); }
在做数据库连接时我们会发现一些重复性的代码比如:注册驱动、获得连接,释放资源,所以将其封装成一个方法以便日后去用。
package com.oracle.demo1; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class DButil { private DButil(){} static Connection conn; static{ try { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/demo_jdbc?characterEncoding=utf-8"; String username = "root"; String password = "123456"; conn = DriverManager.getConnection(url, username, password); } catch (Exception ex) { throw new RuntimeException(ex+"数据库连接失败"); } } public static Connection getConn(){ return conn; } public static void close(Statement sta,Connection conn){ if(sta!=null){ try{ sta.close(); }catch(SQLException ex){} } if(conn!=null){ try{ conn.close(); }catch(SQLException ex){} } } public static void close(ResultSet rs,Statement sta,Connection conn){ if(rs!=null){ try{ rs.close(); }catch(SQLException ex){} } if(sta!=null){ try{ sta.close(); }catch(SQLException ex){} } if(conn!=null){ try{ conn.close(); }catch(SQLException ex){} } } }
总结:
Statement 接口提供了三种执行 SQL 语句的方法:executeQuery、executeUpdate 和 execute。
使用哪一个方法由 SQL 语句所产生的内容决定。
方法executeQuery
用于产生单个结果集的语句,例如 SELECT 语句。
被使用最多的执行 SQL 语句的方法是 executeQuery。这个方法被用来执行 SELECT 语句,它几乎是使用最多的 SQL 语句。
方法executeUpdate
用于执行 INSERT、UPDATE 或 DELETE 语句以及 SQL DDL(数据定义语言)语句,
例如 CREATE TABLE 和 DROP TABLE。INSERT、UPDATE 或 DELETE 语句的效果是修改表中零行或多行中的一列或多列。
executeUpdate 的返回值是一个整数,指示受影响的行数(即更新计数)。
对于 CREATE TABLE 或 DROP TABLE 等不操作行的语句,executeUpdate 的返回值总为零。
使用executeUpdate方法是因为在 createTableCoffees 中的 SQL 语句是 DDL (数据定义语言)语句。
创建表,改变表,删除表都是 DDL 语句的例子,要用 executeUpdate 方法来执行。你也可以从它的名字里看出,方法 executeUpdate 也被用于执行更新表 SQL 语句。实际上,相对于创建表来说,executeUpdate 用于更新表的时间更多,因为表只需要创建一次,但经常被更新。
方法execute:
用于执行返回多个结果集、多个更新计数或二者组合的语句。因为多数程序员不会需要该高级功能