Day5 JDBC
JDBC的简介
Java Database Connectivity:连接数据库技术。
SUN公司为了简化、统一对数据库的操作,定义了一套Java操作数据库的规范(接口),使用同一套程序操作不同的数据库,称之为JDBC。
简单的说,JDBC的意义在于在Java程序中执行SQL语句。
JDBC开发支持jar:
java.sql
javax.sql
驱动包
JDBC的工作原理
JDBC中核心类:DriverManager驱动管理器
JDBC主要分为两层,第一层为Java的接口层,主要面向Java的应用程序开发者,它定义了操作数据库的各种功能的接口,第二层为数据库驱动层,为数据库供应商提供了注册其数据库产品驱动程序的接口,两者之间是通过驱动管理器来负责协调和管理的。由于JDBC为所有支持的数据库提供了统一的API接口,因此在实际的开发中,如果软件产品被要求同时支持多种数据库平台,其间主要的差异将来自于不同数据库产品在特殊SQL语句方面的差异,至于调用接口方面,如果没有使用极为依赖数据库平台的接口API,那么该部分程序代码将不用作出任何改变。以下我们将通过示例代码的方式逐步了解JDBC中提供的API接口。
JDBC的开发步骤
1.实现驱动注册(DriverManager)
2.建立连接
3.创建以及发送SQL指令
4.获取以及处理响应
5.释放资源
JDBC的入门案例
1.导入驱动包,建立一个lib文件夹存放程序需要的一些jar包,建立之后将jar包复制黏贴进到lib下
2.简单案例
程序代码
package test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import com.mysql.jdbc.Driver; public class JDBCTest { public static void main(String[] args) throws Exception { // 1.借助DriverManager实现驱动的注册(mysql驱动就在DriverManager中管理) //DriverManager.registerDriver(new Driver()); // 反射(DriverManager.registerDriver()注册的唯一方法),注册驱动 Class.forName("com.mysql.jdbc.Driver"); // 2.建立连接 // jdbc:mysql://localhost:3306/db1711 // 协议:子协议://IP:端口/数据库 Connection conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/db1711",//url统一资源定位符(路径)和mysql DBMS的哪个数据库建立连接 "root",//user用户 "123456");//password密码 // 查看是否连接成功 // System.out.println(conn);//com.mysql.jdbc.JDBC4Connection@4d405ef7 // 3.发送sql指令 String sql = "select * from emp"; // 创建Statement的实现类的对象 Statement stmt = conn.createStatement(); // executeUpdate():增删该,返回的是int类型,影响的行数,0是失败 // executeQuery():查询,返回的是结果集 ResultSet rs = stmt.executeQuery(sql); // 4.结果集的处理() // rs.next():boolean类型,游标,没有值的话返回false while(rs.next()) {//遍历每一行的数据 // 依次获取每一列的数据 int empno = rs.getInt("empno"); String ename = rs.getString("ename"); System.out.println(empno+"\t"+ename); } // 5.释放资源 rs.close(); stmt.close(); conn.close(); } }
显示结果
7369 SMITH 7499 ALLEN 7521 WARD 7566 JONES 7654 MARTIN 7698 BLAKE 7782 CLARK 7788 SCOTT 7839 KING 7844 TURNER 7876 ADAMS 7900 JAMES 7902 FORD 7934 MILLER
核心API详解
DriverManager
驱动注册
第一种方式,会造成DriverManager中产生两个一样的驱动,并会对具体的驱动类产生依赖。
// 1.借助DriverManager实现驱动的注册(mysql驱动就在DriverManager中管理) DriverManager.registerDriver(new Driver());
第二种方式,反射加载(推荐),注册一次,在driver类加载的时候就注册了
// 反射(DriverManager.registerDriver()注册的唯一方法),注册驱动 Class.forName("com.mysql.jdbc.Driver");
Driver部分原码
public class Driver extends NonRegisteringDriver implements java.sql.Driver { // ~ Static fields/initializers // --------------------------------------------- // // Register ourselves with the DriverManager // static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } }
}
增删改查案例
增
1 public static void insert(int deptno,String dname,String loc) throws Exception{ 2 Class.forName("com.mysql.jdbc.Driver"); 3 Connection conn = DriverManager.getConnection( 4 "jdbc:mysql://localhost:3306/db1711", 5 "root", 6 "123456"); 7 Statement stmt = conn.createStatement(); 8 String sql = "INSERT INTO dept VALUES("+deptno+",'"+dname+"','"+loc+"')"; 9 int num = stmt.executeUpdate(sql); 10 System.out.println(num); 11 stmt.close(); 12 conn.close(); 13 14 }
删
1 public static void delete(int deptno) throws Exception{ 2 Class.forName("com.mysql.jdbc.Driver"); 3 Connection conn = DriverManager.getConnection( 4 "jdbc:mysql://localhost:3306/db1711", 5 "root", 6 "123456"); 7 Statement stmt = conn.createStatement(); 8 String sql = "delete from dept where deptno = "+deptno+""; 9 int nums = stmt.executeUpdate(sql); 10 System.out.println(nums); 11 stmt.close(); 12 conn.close(); 13 }
改
1 public static void update(int deptno,String loc) throws Exception{ 2 Class.forName("com.mysql.jdbc.Driver"); 3 Connection conn = DriverManager.getConnection( 4 "jdbc:mysql://localhost:3306/db1711", 5 "root", 6 "123456"); 7 Statement stmt = conn.createStatement(); 8 String sql = "update dept set deptno = "+deptno+" where loc = '"+loc+"'"; 9 int nums = stmt.executeUpdate(sql); 10 System.out.println(nums); 11 stmt.close(); 12 conn.close(); 13 }
查
1 public static void query() throws Exception{ 2 // 1.借助DriverManager实现驱动的注册(mysql驱动就在DriverManager中管理) 3 //DriverManager.registerDriver(new Driver()); 4 // 反射(DriverManager.registerDriver()注册的唯一方法),注册驱动 5 Class.forName("com.mysql.jdbc.Driver"); 6 7 // 2.建立连接 8 // jdbc:mysql://localhost:3306/db1711 9 // 协议:子协议://IP:端口/数据库 10 Connection conn = DriverManager.getConnection( 11 "jdbc:mysql://localhost:3306/db1711",//url统一资源定位符(路径)和mysql DBMS的哪个数据库建立连接 12 "root",//user用户 13 "123456");//password密码 14 // 查看是否连接成功 15 // System.out.println(conn);//com.mysql.jdbc.JDBC4Connection@4d405ef7 16 17 // 3.发送sql指令 18 String sql = "select * from emp"; 19 // 创建Statement的实现类的对象 20 Statement stmt = conn.createStatement(); 21 // executeUpdate():增删该,返回的是int类型,影响的行数,0是失败 22 // executeQuery():查询,返回的是结果集 23 ResultSet rs = stmt.executeQuery(sql); 24 25 // 4.结果集的处理() 26 // rs.next():boolean类型,游标,没有值的话返回false 27 while(rs.next()) {//遍历每一行的数据 28 // 依次获取每一列的数据 29 int empno = rs.getInt("empno"); 30 String ename = rs.getString("ename"); 31 System.out.println(empno+"\t"+ename); 32 } 33 34 // 5.释放资源 35 rs.close(); 36 stmt.close(); 37 conn.close(); 38 }
登录的问题
SQL注入
1 // 1.注册驱动 2 Class.forName("com.mysql.jdbc.Driver"); 3 // 2.建立连接 4 Connection conn = DriverManager.getConnection( 5 "jdbc:mysql://localhost:3306/bd1711", 6 "root", 7 "root"); 8 //3.发送sql, ?占位符 9 String sql = "select * from user where uname = ? and password = ? "; 10 //支持sql的预编译(语法检查,语义检查 ... 查询) 11 PreparedStatement ps = conn.prepareStatement(sql); 12 //赋值 13 ps.setString(1, name); 14 ps.setString(2, pwd); 15 //发送命令 16 ResultSet rs = ps.executeQuery(); 17 //4.处理响应结果 18 if(rs.next()){ 19 System.out.println("登陆成功"); 20 }else{ 21 System.out.println("登录失败"); 22 } 23 //5.释放资源 24 rs.close(); 25 ps.close(); 26 conn.close(); 27 28 1. preparestatement能够避免sql的注入攻击,安全性更高。 29 2. preparedStatment实现预编译,因此在批量的数据操作中减少语法检查的时间,效率高。 30 3. 在批处理中,preparedstatement只能批量处理单一类型的操作;statement可以一次处理增删改等多种类型的操作。 31 32 //使用preparedStatement实现批处理 33 // 1.注册驱动 34 Class.forName("com.mysql.jdbc.Driver"); 35 // 2.建立连接 36 Connection conn = DriverManager.getConnection( 37 "jdbc:mysql://localhost:3306/bd1711", 38 "root", 39 "root"); 40 //3.发送sql 41 String sql = "delete from user where uid = ?"; 42 //预编译 43 PreparedStatement ps = conn.prepareStatement(sql); 44 //赋值 45 ps.setInt(1, 1); 46 ps.addBatch(); 47 48 ps.setInt(1, 2); 49 ps.addBatch(); 50 51 //4.执行和处理响应 52 int[] rows = ps.executeBatch(); 53 System.out.println(Arrays.toString(rows)); 54 55 //5.释放资源 56 ps.close(); 57 conn.close(); 58 59 //使用Statement实现批处理 60 String sql2 = "insert"; 61 String sql3 = "delete"; 62 Statement stmt = conn.createStatement(); 63 stmt.addBatch(sql2); 64 stmt.addBatch(sql3); 65 stmt.executeBatch();
开发DAO
data access object
分层开发(实现代码复用)
DAO主要负责与数据库之间的交互。
问题:
1.硬编码:配置文件
如何使用外部配置文件:
properties配置文件:
//创建properties对象 Properties properties =new Properties(); //将propertes文件加载为流 InputStream is = EmpDao2.class .getClassLoader() .getResourceAsStream("jdbc.properties"); //加载 properties.load(is); //通过key值获取value值 String driver = properties.getProperty("driver"); String url = properties.getProperty("url"); String user = properties.getProperty("user"); String pwd = properties.getProperty("pwd"); // 1.注册驱动 Class.forName(driver); conn = DriverManager.getConnection(url,user,pwd);
封装BASEDAO
封装basedao
1 package dao; 2 3 import java.lang.reflect.Field; 4 import java.sql.Connection; 5 import java.sql.PreparedStatement; 6 import java.sql.ResultSet; 7 import java.sql.ResultSetMetaData; 8 import java.sql.SQLException; 9 import java.util.ArrayList; 10 import java.util.List; 11 12 import util.JdbcUtils; 13 14 /** 15 * 16 * @author Administrator 17 * 所有的dao的父类(通用的增删改查) 18 */ 19 public class BaseDao { 20 21 protected Connection conn = null; 22 protected PreparedStatement ps = null; 23 protected ResultSet rs = null; 24 25 //通用的增删改emp dept user 26 //1.insert update delete / emp dept user : sql ? ? 27 //2.赋值的参数的个数和类型不能确定 Object[] 28 public int executeUpdate(String sql,Object[] params){ 29 int rows = 0; 30 try { 31 //2.获取连接 32 conn = JdbcUtils.getConnecton(); 33 //3.发送sql指令 34 //预编译 35 ps = conn.prepareStatement(sql); 36 //赋值 37 for(int i=0;i<params.length;i++){ 38 ps.setObject(i+1, params[i]); 39 } 40 //处理 41 rows = ps.executeUpdate(); 42 } catch (SQLException e) { 43 e.printStackTrace(); 44 } catch (Exception e) { 45 e.printStackTrace(); 46 }finally{ 47 JdbcUtils.closeRes(rs, ps, conn); 48 } 49 return rows; 50 } 51 52 //通用查询 53 public<T> List<T> executeQuery(String sql,Object[] params,Class<T> clz){ 54 //定义集合 55 List<T> lists = new ArrayList<>(); 56 try { 57 //1.获取连接 58 conn=JdbcUtils.getConnecton(); 59 //2.发送sql 60 ps = conn.prepareStatement(sql); 61 for(int i=0;i<params.length;i++){ 62 ps.setObject(i+1, params[i]); 63 } 64 ResultSet rs = ps.executeQuery(); 65 //元数据:解释数据的数据 66 ResultSetMetaData md = rs.getMetaData(); 67 //查询的字段的总数 68 int count = md.getColumnCount(); 69 //3.处理 70 while(rs.next()){//遍历一行就需要创建一个对象进行封装 71 //创建t对象 (调用t的class对象创建t对象,调用无参构造创建对象) 72 T t = clz.newInstance(); 73 //获取每个字段的值(遍历获取每行中每个字段的值) 74 for(int i=0;i<count;i++){ 75 //先获取字段名称 76 String name = md.getColumnName(i+1); 77 //根据字段名称获取字段的值 78 Object value = rs.getObject(name); 79 //根据字段名称获取相应的属性,将字段的值赋给属性 80 Field field = clz.getDeclaredField(name); 81 //设置允许赋值 82 field.setAccessible(true); 83 //赋值 84 if(value!=null){ 85 field.set(t, value); 86 } 87 } 88 //添加到list集合 89 lists.add(t); 90 } 91 } catch (SQLException e) { 92 // TODO Auto-generated catch block 93 e.printStackTrace(); 94 } catch (Exception e) { 95 // TODO Auto-generated catch block 96 e.printStackTrace(); 97 }finally{ 98 JdbcUtils.closeRes(rs, ps, conn); 99 } 100 return lists; 101 } 102 103 104 105 106 }
调用basedao
1 package dao; 2 import java.sql.Connection; 3 import java.sql.Date; 4 import java.sql.PreparedStatement; 5 import java.sql.ResultSet; 6 import java.util.ArrayList; 7 import java.util.List; 8 import entity.Emp; 9 import util.JdbcUtils; 10 11 public class EmpDao3 extends BaseDao{ 12 13 //查询所有 14 public List<Emp> queryAll(){ 15 String sql = "select * from emp"; 16 Object[] params = {}; 17 return executeQuery(sql, params, Emp.class); 18 } 19 20 //增加 21 public int insert(Emp emp){ 22 String sql = "insert into emp(empno,ename,deptno) values(?,?,?)"; 23 Object[] params = { emp.getEmpno(),emp.getEname(),emp.getDeptno() }; 24 return executeUpdate(sql, params); 25 } 26 27 public int delete(int empno){ 28 String sql = "delete from emp where empno=? "; 29 Object[] params = { empno }; 30 return executeUpdate(sql, params); 31 } 32 33 public static void main(String[] args) { 34 EmpDao3 dao = new EmpDao3(); 35 System.out.println(dao.queryAll()); 36 } 37 }