JDBC 1、jdbc简介 JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统的。通用的SQL数据库存取和操作的公共接口(一组API),定义了用来采访数据库的标准java类库,使用这个类库可以以一种标准的方法,方便的访问数据库资源(java.sql包中)
JDBC为访问不同的数据库提供了一种统一的途径,JDBC对开发组屏蔽了一些细节问题。
JDBC的目标是使应用程序开发人员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统,这样就使得程序员无需对特定的数据库系统的特点有过多的了解,从而大大简化和加快了开发过程。
JDBC包括两个层次
面向应用的API:Java API,抽象接口,供应用程序开发人员使用(连接数据库,执行SQL语句,获得结果集)
面向数据库API:Java Driver API,供开发数开发数据库驱动程序
主要概念
DriverManager(java.sql.DriverManager)
装载驱动程序,管理应用程序与驱动程序之间的连接
Driver(由驱动程序开放式提供)
将应用程序的API请求转换为特定的数据库请求
Connection(java.sql.Connection)
将应用程序连接到特定的数据库
Statement
在一个给定的连接中,用于执行一个数据库SQL语句u
ResultSet
SQL语句完成 后,返回的数据库结果集(包括行、列)
2、jdbc操作 1>添加jar文件,测试jar文件是否添加成功
2>加载驱动
1 Class.forName("com.mysql.cj.jdbc.Driver" );
3>获取与数据库的链接
1 2 3 4 String url="jdbc:mysql:///oa?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true" ; String username = "root" ;String pwd="123456" ; Connection connection = DriverManager.getConnection(url,username,pwd);
链接数据库需要提供什么? 链接的url 用户名 密码
5.x 链接数据库的url jdbc:mysql://localhost:3306/test 如果是本机,端口号没改变 jdbc:mysql:///test
8.x url
4>创建通道,发送sql指令
1 Statement stmt = connection.createStatement();
创建Statement 通过改对象发送sql指令
1 2 3 4 1、execute 该方法可以发送select或者 insert update delete语句,如果是增删改方法 返回false,如果是select语句返回true 该方法不常用 2、executeUpdate 返回sql语句影响的行数 3、exexuteQuery 返回结果集
5>需要处理结果集
ResultSet
1 2 3 4 5 6 7 String sql="SELECT deptid did,deptname dname FROM dept" ; rs = stmt.executeQuery(sql); while (rs.next()){ int id = rs.getInt("did" ); int id1 = rs.getInt(1 ); System.out.println(id+"---" +id1); }
6>关闭资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public static void main (String[] args) { Connection connection = null ; Statement stmt = null ; try { Class.forName(JDBCUtils.DRIVER); connection = DriverManager.getConnection(JDBCUtils.URL,JDBCUtils.USERNAME,JDBCUtils.PASSWORD); stmt = connection.createStatement(); String sql="delete from dept where deptid=3" ; int rows = stmt.executeUpdate(sql); System.out.println(rows); } catch (Exception e) { e.printStackTrace(); } finally { try { if (stmt!=null ){ stmt.close(); } if (connection!=null ){ connection.close(); } } catch (SQLException throwables) { throwables.printStackTrace(); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public static void main(String[] args) { Connection conn = null ; Statement stmt = null ; ResultSet rs = null ; try { Class.forName(JDBCUtils.DRIVER); conn = DriverManager.getConnection(JDBCUtils.URL,JDBCUtils.USERNAME,JDBCUtils.PASSWORD); stmt = conn.createStatement(); / / String sql = "select * from dept"; String sql = "SELECT deptid did,deptname dname FROM dept"; rs = stmt.executeQuery(sql ); while(rs.next()){ int id = rs.getInt("did");/ / 通过查询结果的列名获取数据 int id1 = rs.getInt(1 );/ / 通过列序号,从1 开始 System.out.println(id+ "---"+ id1); } } catch (Exception e) { e.printStackTrace(); } finally { try { if(rs!= null ){ rs.close(); } if(stmt!= null ){ stmt.close(); } if(conn!= null ){ conn.close(); } } catch (SQLException throwables) { throwables.printStackTrace(); } } }
3、sql注入与PreparedStatement 1、sql注入的含义
通过拼接特殊sql语句,获取到不该获取的数据
1 2 3 String sql="SELECT * FROM users WHERE uname='" +uname+"' AND upwd='" +upwd+"'" ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public static void main(String[] args) { String inname ="aa"; String inpwd = "' OR '1'='1"; Connection connection = null; Statement stmt = null; ResultSet rs = null; try { Class.forName(JDBCUtils.DRIVER); connection = DriverManager.getConnection(JDBCUtils.URL,JDBCUtils.USERNAME,JDBCUtils.PASSWORD); stmt = connection.createStatement(); String sql="SELECT * FROM users WHERE uname='"+inname+"' AND upwd='"+inpwd+"'"; System.out.println(sql); rs = stmt.executeQuery(sql); while (rs.next()){ int id = rs.getInt("uid"); String name = rs.getString("uname"); String pwd = rs.getString("upwd"); System.out.println(id+"\t"+name+"\t"+pwd); } } catch (Exception e) { e.printStackTrace(); } finally { .... //输入用户名和密码获取信息 }
如果避免,java提供了PreparedStatement 防止sql注入:在使用PreparedStatement的时候,sql语句中的参数,全部通过占位符的方式来使用,给占位符赋值
1 2 3 4 5 6 7 8 .... String sql="SELECT * FROM users WHERE uname=? and upwd=? " ; ..... pstmt = connection.prepareStatement(sql); pstmt.setString(1 ,inname); pstmt.setString(2 ,inpwd); rs = pstmt.executeQuery();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public static void main (String[] args) { String inname = "zs" ; String inpwd="147258" ; Connection connection = null ; PreparedStatement pstmt = null ; ResultSet rs = null ; String sql="SELECT * FROM users WHERE uname=? and upwd=? " ; try { Class.forName(JDBCUtils.DRIVER); connection = DriverManager.getConnection(JDBCUtils.URL,JDBCUtils.USERNAME,JDBCUtils.PASSWORD); pstmt = connection.prepareStatement(sql); pstmt.setString(1 ,inname); pstmt.setString(2 ,inpwd); rs = pstmt.executeQuery(); while (rs.next()){ int id = rs.getInt("uid" ); String name = rs.getString("uname" ); String pwd = rs.getString("upwd" ); System.out.println(id+"\t" +name+"\t" +pwd); } } catch (Exception e) { e.printStackTrace(); } finally { .... } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Connection connection = null ; PreparedStatement pstmt = null ; ResultSet rs = null ; try { Class.forName(JDBCUtils.DRIVER); connection = DriverManager.getConnection(JDBCUtils.URL,JDBCUtils.USERNAME,JDBCUtils.PASSWORD); String sql="INSERT INTO dept VALUES(NULL,?,?,?)" ; pstmt = connection.prepareStatement(sql); pstmt.setString(1 ,"采购部" ); pstmt.setString(2 ,"pstmt实现" ); pstmt.setInt(3 ,5 ); int rows = pstmt.executeUpdate(); System.out.println(rows); } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.close(connection,pstmt,rs); }
日期类型的处理
Java事务的类型有三种:JDBC事务、JTA(Java Transaction API)事务、容器事务。
事务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public static void main (String[] args) { Scanner input = new Scanner (System.in); Connection conn = null ; Statement stmt = null ; System.out.println("请输入一个数" ); int num = input.nextInt(); try { Class.forName(JDBCUtils.DRIVER); conn = DriverManager.getConnection(JDBCUtils.URL,JDBCUtils.USERNAME,JDBCUtils.PASSWORD); conn.setAutoCommit(false ); stmt = conn.createStatement(); stmt.executeUpdate("INSERT INTO dept VALUES(NULL,'ceshinew2','xx',0)" ); if (num==0 ){ throw new RuntimeException ("数据添加失败" ); } stmt.executeUpdate("INSERT INTO dept VALUES(NULL,'ceshinew3','xx',0)" ); conn.commit(); } catch (Exception e) { e.printStackTrace(); try { conn.rollback(); } catch (SQLException throwables) { throwables.printStackTrace(); } } finally { JDBCUtils.close(conn,stmt,null ); } }
打点事务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 public static void test01 () { JDBCUtils jdbcUtils = new JDBCUtils (); Connection connection = null ; Statement stmt = null ; Savepoint sp = null ; Scanner input = new Scanner (System.in); System.out.println("请输入一个数" ); int num = input.nextInt(); try { connection = jdbcUtils.getConnection(); connection.setAutoCommit(false ); stmt = connection.createStatement(); stmt.executeUpdate("update account set balance=balance-50 where accid=1" ); sp = connection.setSavepoint(); stmt.executeUpdate("update account set balance=balance-5000 where accid=1" ); if (num==2 ){ throw new RuntimeException ("失败了" ); } stmt.executeUpdate("update account set balance=balance+5000 where accid=2" ); } catch (SQLException throwables) { System.err.println("发生了数据库异常" ); try { connection.rollback(sp); } catch (SQLException e) { e.printStackTrace(); } }catch (RuntimeException e){ System.err.println("发生未知的异常:" +e.getMessage()); try { connection.rollback(sp); } catch (SQLException e1) { e1.printStackTrace(); } }finally { try { connection.commit(); } catch (SQLException throwables) { throwables.printStackTrace(); } jdbcUtils.close(connection,stmt,null ); } }
批处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public static void test02 () { JDBCUtils jdbcUtils = new JDBCUtils (); Connection connection = null ; PreparedStatement pstmt = null ; try { connection = jdbcUtils.getConnection(); pstmt = connection.prepareStatement("INSERT INTO cities VALUES(NULL,?,NULL)" ); long start = System.currentTimeMillis(); for (int i=1 ;i<=10000 ;i++){ pstmt.setString(1 ,"c" +i); pstmt.addBatch(); if (i%1000 ==0 ){ pstmt.executeBatch(); pstmt.clearBatch(); } } long end = System.currentTimeMillis(); System.out.println("====" +(end-start)); } catch (SQLException throwables) { throwables.printStackTrace(); } finally { jdbcUtils.close(connection,pstmt,null ); } }
获取自增主键的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public static void main (String[] args) { Connection conn = null ; PreparedStatement pstmt = null ; ResultSet rs = null ; JDBCUtils jdbcUtils = new JDBCUtils (); try { conn = jdbcUtils.getConnection(); pstmt = conn.prepareStatement("INSERT INTO cities VALUES(NULL,'c',NULL),(NULL,'c2',NULL);" , Statement.RETURN_GENERATED_KEYS); pstmt.executeUpdate(); rs = pstmt.getGeneratedKeys(); while (rs.next()){ Object id = rs.getObject(1 ); System.out.println(id); } } catch (SQLException throwables) { throwables.printStackTrace(); } finally { jdbcUtils.close(conn,pstmt,rs); } }
callabledStatement的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public static void test01 () { Connection conn = null ; CallableStatement cstmt = null ; JDBCUtils jdbcUtils = new JDBCUtils (); try { Class.forName("com.mysql.cj.jdbc.Driver" ); conn = DriverManager.getConnection("jdbc:mysql:///mydb?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true" ,"root" ,"123456" ); cstmt = conn.prepareCall("{call demo08(?,?,?,?)}" ); cstmt.setInt(1 ,3 ); cstmt.registerOutParameter(2 , Types.VARCHAR); cstmt.registerOutParameter(3 ,Types.VARCHAR); cstmt.registerOutParameter(4 ,Types.INTEGER); cstmt.execute(); String name = cstmt.getString(2 ); String subname = cstmt.getString(3 ); int score = cstmt.getInt(4 ); System.out.println(name+"\t" +subname+"\t" +score); } catch (Exception e) { e.printStackTrace(); } finally { jdbcUtils.close(conn,cstmt,null ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public static void test02 () { Connection conn = null ; CallableStatement cstmt = null ; JDBCUtils jdbcUtils = new JDBCUtils (); try { Class.forName("com.mysql.cj.jdbc.Driver" ); conn = DriverManager.getConnection("jdbc:mysql:///mydb?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true" ,"root" ,"123456" ); cstmt = conn.prepareCall("{?=call fun_02(?)}" ); cstmt.registerOutParameter(1 ,Types.VARCHAR); cstmt.setInt(2 ,2 ); cstmt.execute(); String res = cstmt.getString(1 ); System.out.println(res); } catch (Exception e) { e.printStackTrace(); } finally { jdbcUtils.close(conn,cstmt,null ); } }
源数据【】
1 2 3 4 5 输入用户名 xx 输入密码 xx 1、查看信息 2、添加 3、修改 4、删除 0、退出
面向对象的思想操作数据库【必须掌握】
4、内容回顾 1>jdbc意义 接口 具体的实现是各个数据库厂商做的实现
2>jdbc使用步骤
添加Jar
加载驱动
获取链接
创建通道 发送sql指令
处理结果集
关闭资源
3>Statement sql注入
4>RestultSet next() getXXX()
5>PrepareStatement ? 占位符的方式
6>事务与批处理 主键自增 自动事务,可以设置手动 打点事务 pstmt批处理
7>CallabledStatement 调用存储过程和存储 函数的
5、面向对象的思想操作数据库 java 数据库【crud操作】
类 表
属性类型 列类型
属性属性名 列名
对象 记录
业务中也是crud操作
分层:单人单职
bean:实体类,与数据库表对应的,属性和数据库的字段对应
dao:数据访问层,与底层数据交互
view:与使用软件的人交互