zoukankan      html  css  js  c++  java
  • JDBC数据库连接

    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:
    用于执行返回多个结果集、多个更新计数或二者组合的语句。因为多数程序员不会需要该高级功能

  • 相关阅读:
    编码导致 html和aspx 样式差异,变形
    Recommand of the Day:Names in English
    NSBundle常用方法及解释
    在K8S 中部署 Spring Boot 应用,爽!
    如果抛开 Spring,如何自己实现 AOP?面试必问。。。
    为什么阿里强制 boolean 类型变量不能使用 is 开头?
    CTO 说禁用 Lombok,看我怼死他。。
    面试官:什么是 YAML?和 Spring Boot 有什么关系?
    面试官:线程池多余的线程是如何回收的?
    JetBrains 发布下一代 IDE,无比轻量,几秒就能启动干活,IDEA 可以扔了。。
  • 原文地址:https://www.cnblogs.com/Java-125/p/8744464.html
Copyright © 2011-2022 走看看