• Java Web系列之JDBC


    本文最初由security发布于security的博客,禁止任何形式的剽窃行为
    转载原创文章请注明,转载自:security的博客

    本文学习自DT课堂原名颜群

    JDBC

    • JDBC:Java DataBase Connectivity
      可以为多种不同关系型数据库提供统一访问方式,用Java操作数据库
    • 架构:
    1. Java程序
      通过JDBC操纵
      JDBC DriverManager
      操纵
      Oracle或MySQL等关系型数据库驱动程序(jar包)
      操纵
      Oracle或MySQL数据库等
    • jdbc接口、方法、类:API
    1. jdbc API:提供了各种操作访问接口,Connection、Statement、PreparedStatement、ResultSet
    2. jdbc DriverManger:给管理不同的数据库驱动
    3. 各种数据库驱动:相应的数据库厂商提供的(第三方公司提供),连接或者直接操作数据库

    JDBC API主要功能

    • DriverManger:管理驱动

    • Connection:连接(通过DriverManager产生)

    • Statement(PreparedStatement):增删改查(通过Connection产生)

    • CallableStatement:调用数据库中的存储过程/存储函数(通过Connection产生)

    • ResultSet:返回的结果集(上面的Statement等产生)

    • Connection产生操作数据库的对象:
    • Connection产生Statement对象:createStatement()
    • Connection产生PreparedStatement对象:prepareStatement()
    • Connection产生CallableStatement对象:prepareCall()
    • Statement操作数据库:
    • 增删改:executeUpdate()
    • 查:executeQuery()
    • PreparedStatement操作数据库(与Statement操作数据库不同的是SQL语句需要放在前面,执行时不需要SQL,因为之前已经预编译
    • 增删改:executeUpdate()
    • 查:executeQuery()
    • 赋值操作:set...()先用?充当占位符,再用set..更改?
    • 推荐使用PreparedStatement:原因如下:
    1. 编码更加简便,避免了字符串拼接
    2. 提高性能,因为有预编译,编译一次,重复使用
    3. 安全(可以有效防止SQL注入)

    SQL注入:将客户输入的内容和开发人员的SQL语句混为一体 Statement:存在被SQL注入的风险 (例如输入用户名:任意值 ' or 1=1 -- 密码:任意值)

    • CallableStatement:调用存储过程、存储函数
    • connection.prepareCall(参数:存储过程或存储函数名)
    • 参数格式:
    1. 存储过程(无返回值return,用out参数替代):
      {call 存储过程名(参数列表)}
    2. 存储函数(有返回值return)
      {?=call 存储函数名(参数列表)}
    • ResultSet:保存结果集
    • next():光标下移判断是否有下一条数据,true/false
    • previous():true/false
    • getXXX(字段名|位置):获取具体的字段值

    JDBC访问数据库的具体步骤

    1. 导入驱动包,加载具体的驱动类
    2. 与数据库建立连接
    3. 发送sql,执行
    4. 处理结果集(查询)

    JDBCDemo代码

    import java.sql.*;
    
    
    public class JDBCDemo {
    
    	private static final String URL="jdbc:mysql://localhost:3306/学生作业管理数据库?serverTimezone=UTC";
    	private static final String USERNAME="root";
    	private static final String PWD="1998";
    	
    /*	
    	public static void update() { //增删改
    		Connection con =null;
    		Statement stmt = null;
    		try {
    			//1. 导入驱动,加载具体的驱动类
    			Class.forName("com.mysql.jdbc.Driver");
    			//2. 与数据库建立连接
    			con= DriverManager.getConnection(URL,USERNAME,PWD);
    			
    			
    			//3. 发送sql,执行(增删改、查)
    			stmt=con.createStatement();
    			String sql="INSERT INTO 学生表 (学号,姓名,性别,专业班级,出生日期,联系电话) "
    					+ "VALUES(0538,'于兰兰','女','生物05','1984-2-20',	'1331200××××');";
    			//4. 执行SQL
    			int count = stmt.executeUpdate(sql);
    			
    			
    			//5. 处理结果
    			if (count>0)
    			{
    				System.out.println("操作成功");
    			}		
    		}
    		catch(ClassNotFoundException e) {
    			e.printStackTrace();	
    		}
    		catch(SQLException e) {
    			e.printStackTrace();
    		}
    		catch(Exception e) {
    			e.printStackTrace();
    		}
    		finally{
    			try{
    				if(stmt!=null)
    					stmt.close();
    				if(con!=null)
    				con.close();
    			}
    			catch(SQLException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    */	
    	public static void query() {	//查询
    		Connection con =null;
    		Statement stmt = null;
    		ResultSet rs=null;
    		try {
    			//1. 导入驱动,加载具体的驱动类
    			Class.forName("com.mysql.jdbc.Driver");
    			//2. 与数据库建立连接
    			con= DriverManager.getConnection(URL,USERNAME,PWD);
    			//3. 发送sql,执行(查)
    			stmt=con.createStatement();
    			String sql="select * from 学生表";
    			//4. 执行SQL
    			rs = stmt.executeQuery(sql);  //executeUpdate改为executeQuery
    			//5. 处理结果
    			while(rs.next()) {
    				int sno =rs.getInt("学号");
    				String sname =rs.getString("姓名");
    				System.out.println(sno+"--"+sname);
    				}
    			}
    		catch(ClassNotFoundException e) {
    			e.printStackTrace();	
    		}
    		catch(SQLException e) {
    			e.printStackTrace();
    		}
    		catch(Exception e) {
    			e.printStackTrace();
    		}
    		finally{
    			try{
    				if(rs!=null)
    					rs.close();
    				if(stmt!=null)
    					stmt.close();
    				if(con!=null)
    				con.close();
    			}
    			catch(SQLException e) {
    				e.printStackTrace();
    			}
    		}		
    	}
    	
    	public static void main(String[] args) {
    		// TODO 自动生成的方法存根
    	//	update();
    		query();
    	}
    
    }
    
    

    数据库驱动

    • Oracle
    1. 驱动jar
      ojdbc-x.jar
    2. 具体驱动类
      oracle.jdbc.OracleDriver
    3. 连接字符串(数据库名:IP:端口)
      jdbc:oracle:thin:@localhost:1521:ORCL
    • MySQL
    1. 驱动jar
      mysql-connector-java-x.jar
    2. 具体驱动类
      com.mysql.jdbc.Driver
    3. 连接字符串
      jdbc:mysql://localhost:3306/数据库实例名
    • SqlServer
    1. 驱动jar
      sqljdbc-x.jar
    2. 具体驱动类
      com.microsoft.sqlserver.jdbc.SQLServerDriver
    3. 连接字符串
      jdbc:microsoft:localhost:1433;databsename=数据库实例名
    • 使用jdbc操作数据库时,如果对数据库进行了更换,只需要替换:

    驱动、驱动类、连接字符串、用户名、密码

    处理CLOB/BLOB类型

    • 存放稍大型数据:
    1. 方法1:存储路径
      通过JDBC存储文件路径,然后根据IO操作处理
    2. 方法2
    • CLOB(Oracle叫法,mysql叫法为TEXT)字符流:大文本数据(小说->数据)
      varchar2:4000byte
    • BLOB字节流:二进制文件(一切文件、图片,音频)

    总结

    1. 导入驱动包、加载具体驱动类
    2. 与数据库建立连接
    3. 通过connection,获取操作数据库的对象
    4. 处理结果集
      while(rs.next()){ rs.get...();}
      catch(SQLException e){...}
      catch(Exception e){...}
      finallu{//打开顺序,与关闭顺序相反
      if(rs!=null) rs.close();
      if(stmt!=null) stmt.close();
      if(connection!=null) connection.close();
      }

    本文最初由security发布于security的博客,禁止任何形式的剽窃行为
    转载原创文章请注明,转载自:security的博客

  • 相关阅读:
    泛型简介
    单元测试(junit使用)
    枚举简介
    面试题:二叉树的镜像
    面试题:和为S的连续正数列
    面试题:丑数
    面试题:合并两个排序的链表
    面试题:数值的整数次方
    面试题:矩形覆盖
    面试题:数组中的逆序对
  • 原文地址:https://www.cnblogs.com/wanggang9968/p/13043654.html
Copyright © 2020-2023  润新知