JDBC

2020.8.29

JDBC

  • 概念:Java DataBase Connectivity Java 数据库连接, Java语言操作数据库
  • JDBC本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。
快速入门
  • 快速入门:
    步骤:

      1. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
      	1> 复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下
      	2> 右键-->Add As Library
      2. 注册驱动
      3. 获取数据库连接对象 Connection
      4. 定义sql
      5. 获取执行sql语句的对象 Statement
      6. 执行sql,接受返回结果
      7. 处理结果
      8. 释放资源
    
package jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

/**
 * Creat by LEE on 2020/8/29 15:29
 *
 * @description:快速入门
 */
public class JDBCdemo {
    public static void main(String[] args) throws Exception {
        //1.导入驱动jar包
        //2.注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //3.获取数据库连接对象
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3", "root", "urpwd");
        //4.sql语句
        String sql = "update account set balance = 1000 where id = 1";
        //5.获取执行sql语句的对象
        Statement statement = conn.createStatement();
        //6.执行sql
        int count = statement.executeUpdate(sql);
        //7.处理返回的结果
        System.out.println(count);
        //8.释放资源
        statement.close();
        conn.close();

    }
}
详解各个对象
  • 详解各个对象:
    • DriverManager:驱动管理对象
      (方法)功能:

       1. 注册驱动:告诉程序该使用哪一个数据库驱动jar
       	static void registerDriver(Driver driver) :注册与给定的驱动程序 DriverManager 。 
       	写代码使用:  Class.forName("com.mysql.jdbc.Driver");
       	通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块
       	static {
       	        try {
       	            java.sql.DriverManager.registerDriver(new Driver());
       	        } catch (SQLException E) {
       	            throw new RuntimeException("Can't register driver!");
       	        }
       		}
      
       	注意:mysql5之后的驱动jar包可以省略注册驱动的步骤。
       2. 获取数据库连接:
       	方法:static Connection getConnection(String url, String user, String password) 
       	参数:
       		url:指定连接的路径
       			语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
       			例子:jdbc:mysql://localhost:3306/db3
       			细节:如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称
       		user:用户名
       		password:密码 
      
    • Connection:数据库连接对象
      功能:

       1. 获取执行sql 的对象
       	Statement createStatement()
       	PreparedStatement prepareStatement(String sql)  
       2. 管理事务:
       	开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
       	提交事务:commit() 
       	回滚事务:rollback() 
      
    • Statement:执行sql的对象

        1. 执行sql
        	1. boolean execute(String sql) :可以执行任意的sql 了解 
        	2. int executeUpdate(String sql) :执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句
        		 返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功 返回值>0的则执行成功,反之,则失败。
        	3. ResultSet executeQuery(String sql)  :执行DQL(select)语句
      
      package jdbc;
      
      import java.sql.Connection;
      import java.sql.DriverManager;
      import java.sql.SQLException;
      import java.sql.Statement;
      
      /**
       * Create by LEE on 2020/8/29 16:29
       *
       * @description:insert、update、delete
       */
      public class JDBCdemo2 {
          public static void main(String[] args) {
              Connection conn = null;
              Statement statement = null;
              try {
                  Class.forName("com.mysql.jdbc.Driver");
                  conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "urpwd");
                  //insert sql
                  String sql1 = "insert into account values (null,'idea',999)";
                  statement = conn.createStatement();
                  int count1 = statement.executeUpdate(sql1);
                  if (count1 > 0) {
                      System.out.println("insert success");
                  } else {
                      System.out.println("insert fail");
                  }
              } catch (ClassNotFoundException e) {
                  e.printStackTrace();
              } catch (SQLException e) {
                  e.printStackTrace();
              } finally {
                  if (statement != null) {
                      try {
                          statement.close();
                      } catch (SQLException e) {
                          e.printStackTrace();
                      }
                  }
                  if (conn != null) {
                      try {
                          conn.close();
                      } catch (SQLException e) {
                          e.printStackTrace();
                      }
                  }
              }
      
          }
      }
      
    • ResultSet:结果集对象,封装查询结果

        boolean next(): 游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回true
        getXxx(参数):获取数据
        		Xxx:代表数据类型   如: int getInt() ,	String getString()
        		参数:
        			1. int:代表列的编号,从1开始   如: getString(1)
        			2. String:代表列名称。 如: getDouble("balance")
        注意:
        	使用步骤:
        		1. 游标向下移动一行
        		2. 判断是否有数据
        		3. 获取数据
      
          Class.forName("com.mysql.jdbc.Driver");
          conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "urpwd");
          statement = conn.createStatement();
          String sql = "select * from account;";
          resultSet = statement.executeQuery(sql);
          while (resultSet.next()) {
              int id = resultSet.getInt("id");
              String name = resultSet.getString("name");
              double balance = resultSet.getDouble("balance");
              System.out.println(id + " | " + name + " | " + balance);
          }
      
        Class.forName("com.mysql.jdbc.Driver");
        conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "urpwd");
        statement = conn.createStatement();
        String sql = "select * from account;";
        resultSet = statement.executeQuery(sql);
        while (resultSet.next()) {
            int id = resultSet.getInt("id");
            String name = resultSet.getString("name");
            double balance = resultSet.getDouble("balance");
            System.out.println(id + " | " + name + " | " + balance);
        }
      
      • PreparedStatement:执行sql的对象

          具体的可以查看登录的demo,过于简单需要使用此类解决下列问题。
          1. SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题
          	输入用户随便,输入密码:a' or 'a' = 'a
          	sql:select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a' 
          2. 解决sql注入问题:使用PreparedStatement对象来解决
          3. 预编译的SQL:参数使用?作为占位符
          4. 步骤:
          			1. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
          			2. 注册驱动
          			3. 获取数据库连接对象 Connection
          			4. 定义sql
          				 注意:sql的参数使用?作为占位符。 如:select * from user where username = ? and password = ?;
          			5. 获取执行sql语句的对象 PreparedStatement  Connection.prepareStatement(String sql) 
          			6. 给?赋值:
          				方法: setXxx(参数1,参数2)
          					参数1:?的位置编号 从1 开始
          					参数2:?的值
          			7. 执行sql,接受返回结果,不需要传递sql语句
          			8. 处理结果
          			9. 释放资源
          5. 注意:后期都会使用PreparedStatement来完成增删改查的所有操作
          			1. 可以防止SQL注入
          			2. 效率更高
        
    抽取JDBC工具类
    • 抽取JDBC工具类 : JDBCUtils
      • 目的:简化书写
      • 分析:
      1. 注册驱动也抽取
      2. 抽取一个getConnection()方法获取连接对象
        需求:不想传递参数(麻烦),还得保证工具类的通用性。
        解决:配置文件
        jdbc.properties
        url=
        user=
        password=
      3. 抽取一个close()方法释放资源
      • demo
        public class JDBCUtils {
            private static String url;
            private static String user;
            private static String pwd;
            private static String driver;
            static {
                Properties prop = new Properties();
                try {
                    prop.load(JDBCUtils.class.getResourceAsStream("jdbc.properties"));
                    url = prop.getProperty("url");
                    user = prop.getProperty("user");
                    pwd = prop.getProperty("pwd");
                    driver = prop.getProperty("driver");
                    Class.forName(driver);
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
            public static Connection getConnection() throws SQLException {
                return DriverManager.getConnection(url, user, pwd);
            }
        
            public static void close(Statement statement, Connection connection) {
              ......
            }
        
            public static void close(ResultSet resultSet, Statement statement, Connection connection) {
               ......
            }
        }
        

注:在这个demo中也犯了个“相同的”错误,使用类加载器获取配置资源所产生的bug,在“静态代码块中使用类加载器”(不确定,网上也没看懂,下来自己看看类加载器)会报错java.lang.NoClassDefFoundError:Could not initialize class jdbc.JDBCUtils,这个问题参考反射–案例不使用类加载器可以解决,相应的文件位置也有区别,其他方法暂时没有了解到。

JDBC控制事务
  • JDBC控制事务:

    • 事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。
    • 操作:
      1. 开启事务
      2. 提交事务
      3. 回滚事务
    • 使用Connection对象来管理事务
      1.开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
      在执行sql之前开启事务
      2.提交事务:commit()
      当所有sql都执行完提交事务
      3.回滚事务:rollback()
      在catch中回滚事务

    demo:

    	  ...
          //获取连接
          conn = JDBCUtils.getConnection();
          //开启事务
          conn.setAutoCommit(false);
          //定义sql
          String sql1 = "update account set balance = balance - ? where id = ?;";
          String sql2 = "update account set balance = balance + ? where id = ?;";
          pstm1 = conn.prepareStatement(sql1);
          pstm2 = conn.prepareStatement(sql2);
          pstm1.setInt(1,500); -*/
          pstm1.setInt(2,1);
          pstm2.setInt(1,500);
          pstm2.setInt(2,2);
          pstm1.executeUpdate();
          int  a = 3/0;
          pstm2.executeUpdate();
          //提交事务
          conn.commit();
      } catch (Exception e) {
          if (conn != null) {//判断是否为空
              try {
                  conn.rollback();//回滚
              } catch (SQLException e1) {
                  e1.printStackTrace();
              }
          }
          e.printStackTrace();
      }...
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值