zoukankan      html  css  js  c++  java
  • JavaWeb

    1.JDBC 概念  

      概念:Java DataBase Connectivity  Java数据库连接,Java语言操作数据库

      本质:其实是官方(sun)定义的一套操作所有关系型数据库的规则,既接口。各个数据库厂商去实现这套这套接口,提供数据库驱动jar包。

           我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。

     

    2.快速入门

      (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)释放资源

    public class JdbcDemo1  {
        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/db1", "root", "woaini1314");
    
            //4.定义sql语句
            String sql = "update emp set salary = 9999 where id = 1";
    
            //5.获取执行sql的对象 Statement
            Statement statement = conn.createStatement();
    
            //6.执行sql
            int count = statement.executeUpdate(sql);
    
            //7.处理结果
            System.out.println(count);
    
            //8.释放资源
            statement.close();
            conn.close();
        }
    }

    3.JDBC各个类详解

      (1)DriverManager:驱动管理对象

        *功能:

          1.注册驱动:告诉程序该使用哪一个数据库驱动jar包

            static void registerDriver(Driver  driver):注册与给定的驱动程序 DriverManager

            写代码使用:Class.forName("com.mysql.jdbc.Driver");  - - > 来自导入的jar包  

            通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块

            注意:mysql之后的驱动jar包可以省略注册驱动的步骤

          2.获取数据库连接

            *方法:static connection DriverManager.getConnection(String url,String user,String password)

            *参数:

              *url:指定连接的路径

                *语法:jdbc:mysql:// IP地址(域名):端口号/数据库名称  如:jdbc:mysql://localhost:3306/db1

                *细节:如果ip地址是本地并且端口号为3306 则可以省略不写 jdbc:mysql:///db1

              *user:用户名

              *password:密码

      (2)Connection:数据库连接对象

        *功能:

          1.获取执行sql的对象

            *statement createStatament()

            *Preparedstatement preparedStatament(String sql)

          2.管理事务:

            *开启事务:  setAutoCommit(boolean autoCommit) : 调用该方法设置参数为false,既开启事务 手动提交

            *提交事务:commit()

            *回滚事务:rollback()

      (3)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)语句

      (4)ResultSet:结果集对象,就是来封装查询结果的

          *boolean next():游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是则返回false

          *getXxx(参数):获取数据

            Xxx:代表数据类型  如:int getInt() String getString()

            参数:int - - > 代表列的编号,从1开始   String - - > 代表列名称

    基本查询:

        注意:

            正确使用步骤:

              1.游标向下移动一行

              2.判断是否有数据

              3.获取数据

    public class JdbcDemo2 {
        public static void main(String[] args) {
            //练习:往数据库db3表中添加、修改、删除
    
            Statement stmt = null; //提升作用域 因为finally中要执行释放资源
            Connection conn = null;
            ResultSet rs = null;
            try {
                //1.注册驱动
                Class.forName("com.mysql.jdbc.Driver");
                //2.定义sql
                String sql = "SELECT * from stu3";
    
                //3.获取connection对象
                conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "woaini1314");
    
                //4.获取执行sql的对象 statement
                stmt = conn.createStatement();
    
                //5.执行sql
                rs = stmt.executeQuery(sql);
    
                //6.处理结果
                    //让光标向下移动一行
                //循环判断
                while (rs.next()){
                    String name = rs.getString("name");
                    int id = rs.getInt(1);
                    System.out.println(id + "---" + name);
                };
    
    
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                //7.释放资源
                //stmt.close();
                //若用户输入密码错误,要避免空指针异常
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                if(stmt!=null){
                    try {
                        stmt.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
                if(conn!=null){
                    try {
                        conn.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    循环读取

      (5)PrepareStatement:执行Sql的对象

     

    练习:JDBC增删改

    public class JdbcDemo2 {
        public static void main(String[] args) {
            //练习:往数据库db3表中添加、修改、删除
    
            Statement stmt = null; //提升作用域 因为finally中要执行释放资源
            Connection conn = null;
            try {
                //1.注册驱动
                Class.forName("com.mysql.jdbc.Driver");
                //2.定义sql
                String sql = "insert into stu3  values(null,'joe')";
    
                //3.获取connection对象
                conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "woaini1314");
    
                //4.获取执行sql的对象 statement
                stmt = conn.createStatement();
    
                //5.执行sql
                int count = stmt.executeUpdate(sql); //影响行数
    
                //6.处理结果
                System.out.println(count);
                if(count > 0){
                    System.out.println("添加成功");
                }else {
                    System.out.println("添加失败");
                }
    
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                //7.释放资源
                //stmt.close();
                //若用户输入密码错误,要避免空指针异常
                if(stmt!=null){
                    try {
                        stmt.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
                if(conn!=null){
                    try {
                        conn.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    插入新数据
    public class JdbcDemo2 {
        public static void main(String[] args) {
            //练习:往数据库db3表中添加、修改、删除
    
            Statement stmt = null; //提升作用域 因为finally中要执行释放资源
            Connection conn = null;
            try {
                //1.注册驱动
                Class.forName("com.mysql.jdbc.Driver");
                //2.定义sql
                String sql = "UPDATE stu3 set name = 'Lindsey' where id = 2";
    
                //3.获取connection对象
                conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "woaini1314");
    
                //4.获取执行sql的对象 statement
                stmt = conn.createStatement();
    
                //5.执行sql
                int count = stmt.executeUpdate(sql); //影响行数
    
                //6.处理结果
                System.out.println(count);
                if(count > 0){
                    System.out.println("修改成功");
                }else {
                    System.out.println("修改失败");
                }
    
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                //7.释放资源
                //stmt.close();
                //若用户输入密码错误,要避免空指针异常
                if(stmt!=null){
                    try {
                        stmt.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
                if(conn!=null){
                    try {
                        conn.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    修改数据

    练习:定义一个方法,查询emp表的数据,将其封装为对象,然后装载集合,返回

    public class JdbcPractise {
        public static void main(String[] args) {
            List<Emp> list = new JdbcPractise().findAll();
            for (Emp emp : list) {
                System.out.println(emp);
            }
        }
    
        /**
         * 查询所有emp对象
         * @return
         */
        public List<Emp> findAll(){
    
            //提升变量,以防报错或空指针异常
            ResultSet rs = null;
            Connection conn = null;
            Statement stmt = null;
            List<Emp> list = null;
    
            try {
                Class.forName("com.mysql.jdbc.Driver");
                //获取连接
                conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/pratise", "root", "woaini1314");
    
                stmt = conn.createStatement();
    
                //定义sql
                String sql = "select * from emp";
                rs = stmt.executeQuery(sql);
    
                //遍历结果集 封装对象,封装集合
                Emp emp = null; //进行复用 防止反复进栈
                list = new ArrayList<Emp>();
                while (rs.next()){
                    int id = rs.getInt("id");
                    String ename = rs.getString("ename");
                    int job_id = rs.getInt("job_id");
                    int mgr = rs.getInt("mgr");
                    Date joindate = rs.getDate("joindate");
                    double salary = rs.getDouble("salary");
                    double bonus = rs.getDouble("bonus");
                    int dept_id = rs.getInt("dept_id");
    
                    //创建emp对象,并赋值
                    emp = new Emp();
                    emp.setId(id);
                    emp.setEname(ename);
                    emp.setJob_id(job_id);
                    emp.setMgr(mgr);
                    emp.setJoindate(joindate);
                    emp.setSalary(salary);
                    emp.setDept_id(dept_id);
                    emp.setBonus(bonus);
    
                    //装载集合
                    list.add(emp);
                }
    
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                if(rs!=null){
                    try {
                        rs.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
                if(stmt!=null){
                    try {
                        stmt.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
                if(conn!=null){
                    try {
                        conn.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
            return list;
        }
    }
    从数据库获取数据并封装

    4.JDBC工具类

      目的:简化书写

      *分析:

        1.注册驱动也抽取

        2.抽取一个方法获取连接对象

          *需求:不想传递参数(麻烦),还得保证工具类的通用性

          *解决方案:配置文件

            jdbc.properties

              url = 

              user = 

              password =

        3.抽取一个方法释放资源

    import javax.swing.plaf.nimbus.State;
    import java.io.FileReader;
    import java.io.IOException;
    import java.net.URL;
    import java.sql.*;
    import java.util.Properties;
    
    
    /**
         * JDBC工具类
         */
    public class JDBCUtils {
        //只有静态的变量才能被静态方法和静态代码块所访问和使用
        private static String url;
        private static String user;
        private static String password;
        private static String driver;
        /**
         * 文件的读取,只需要读取一次就可以拿到这些值。使用静态代码块
         */
        static {
            //读取资源文件,获取值
            try {
                //1.创建Properties 集合类
                Properties pro = new Properties();
    
                //获取src文件下路径的方式---> ClassLoader 类加载器
                ClassLoader classLoader = JDBCUtils.class.getClassLoader();
                URL resource = classLoader.getResource("jdbc.properties");
                String path = resource.getPath();
                System.out.println(path); //得到资源文件的绝对路径
    
                //2.加载文件
                //pro.load(new FileReader("src/jdbc.properties"));
                pro.load(new FileReader(path));
    
                //3.获取属性,并赋值
                url = pro.getProperty("url");
                user = pro.getProperty("user");
                password=pro.getProperty("password");
                driver = pro.getProperty("driver");
    
                //注册驱动
                Class.forName(driver);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 获取连接的方法
         * @return  返回连接对象
         */
        public static Connection getConnection() throws SQLException {
            return DriverManager.getConnection(url,user,password);
        }
    
        /**
         * 释放资源
         * @param stmt
         * @param conn
         */
        public static void close(Statement stmt,Connection conn){
            if(stmt!=null){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            }
        }
        //释放资源重载方法
        public static void close(ResultSet rs,Statement stmt, Connection conn){
            if(rs!=null){
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(stmt!=null){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    当配置文件在src文件下时的工具类
    import javax.swing.plaf.nimbus.State;
    import java.io.FileReader;
    import java.io.IOException;
    import java.net.URL;
    import java.sql.*;
    import java.util.Properties;
    
    
    /**
         * JDBC工具类
         */
    public class JDBCUtils {
        //只有静态的变量才能被静态方法和静态代码块所访问和使用
        private static String url;
        private static String user;
        private static String password;
        private static String driver;
        /**
         * 文件的读取,只需要读取一次就可以拿到这些值。使用静态代码块
         */
        static {
            //读取资源文件,获取值
            try {
                //1.创建Properties 集合类
                Properties pro = new Properties();
    
                //获取src文件下路径的方式---> ClassLoader 类加载器
               /* ClassLoader classLoader = JDBCUtils.class.getClassLoader();
                URL resource = classLoader.getResource("jdbc.properties");
                String path = resource.getPath();
                System.out.println(path); //得到资源文件的绝对路径*/
    
                //2.加载文件
                //pro.load(new FileReader("src/jdbc.properties"));
                pro.load(new FileReader("D:\DB\jdbc_basic\src\cn\itcast\jdbc\jdbc.properties"));
    
                //3.获取属性,并赋值
                url = pro.getProperty("url");
                user = pro.getProperty("user");
                password=pro.getProperty("password");
                driver = pro.getProperty("driver");
    
                //注册驱动
                Class.forName(driver);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 获取连接的方法
         * @return  返回连接对象
         */
        public static Connection getConnection() throws SQLException {
            return DriverManager.getConnection(url,user,password);
        }
    
        /**
         * 释放资源
         * @param stmt
         * @param conn
         */
        public static void close(Statement stmt,Connection conn){
            if(stmt!=null){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            }
        }
        //释放资源重载方法
        public static void close(ResultSet rs,Statement stmt, Connection conn){
            if(rs!=null){
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(stmt!=null){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    第二种获取地址方式

    练习:

      需求:

        1.通过键盘录入用户名和密码

        2.判断用户是否登录成功

          select * from user where username = " " and password = " ";

          *如果这个sql有查询结果,则登录成功

      步骤:

        1.创建数据库表user

    CREATE TABLE USER(
        id INT PRIMARY KEY AUTO_INCREMENT,
        username VARCHAR(32),
        PASSWORD VARCHAR(32)
    );
    
    SELECT * FROM USER;
    
    INSERT INTO USER  VALUES(NULL,'zhangsan','123');
    INSERT INTO USER  VALUES(NULL,'lisi','456');
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.Scanner;
    
    public class JdbcLogin {
        public static void main(String[] args) {
            //1.键盘录入,接收用户名和密码
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入用户名");
            String username = sc.nextLine();
            System.out.println("请输入密码");
            String password = sc.nextLine();
    
            //2.调用方法
            boolean flag = new JdbcLogin().login(username, password);
            //3.判断结果
            if(flag){
                //登录成功
                System.out.println("登录成功");
            }else {
                System.out.println("账号或密码错误");
            }
        }
    
        /**
         * 登录方法
         */
        public boolean login(String username, String password){
            if(username==null && password==null){
                return false;
            }
            //连接数据库判断是否登录成功
            Connection conn = null;
            Statement stmt = null;
            ResultSet rs = null;
            //获取数据库连接
            try {
                conn = JDBCUtils.getConnection();
                //2.定义sql
                String sql = "select * from user where username = '"+username+"' and password = '"+password+"'";
    
                //3.获取执行sql的对象
                stmt = conn.createStatement();
    
                //4.执行查询
                rs = stmt.executeQuery(sql);
    
                //5.判断
                return rs.next();
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JDBCUtils.close(rs,stmt,conn);
            }
    
            return false; //如果执行到这,说明出现了异常,返回false就好了
        }
    
    }
    练习答案

    5.PreparedStatement解决sql注入问题

      1.Sql注入问题 : 在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题

        1.随便输入用户名,输入密码:a' or 'a' = 'a

        2.sql:select * from user where username = 'asgasg' and password = a' or 'a' = 'a

       2.解决sql注入问题:使用PrepareStatement对象来解决

      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.PreparedStatement(String sql)

      (6)给?赋值

        *方法:setXxx(参数1,参数2)  参数1 是 ? 的位置编号,从1开始,参数2是问号的值

      (7)执行sql,接收返回的结果,不需要传递sql语句

      (8)处理结果

      (9)释放资源

      5.注意:后期都会只有PreparedStatemet来完成增删改查的所有操作  因为可以防止sql注入 而且效率更高

    /**
         * 登录方法
         */
        public boolean login(String username, String password){
            if(username==null && password==null){
                return false;
            }
            //连接数据库判断是否登录成功
            Connection conn = null;
            PreparedStatement pstmt = null;
            ResultSet rs = null;
            //获取数据库连接
            try {
                conn = JDBCUtils.getConnection();
                //2.定义sql
                String sql = "select * from user where username = ? and password = ?";
    
                //3.获取执行sql的对象
                pstmt = conn.prepareStatement(sql);
    
                //给?赋值
                pstmt.setString(1,username);
                pstmt.setString(2,password);
    
                //4.执行查询
                rs = pstmt.executeQuery();
    
                //5.判断
                return rs.next();
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JDBCUtils.close(rs,pstmt,conn);
            }
    
            return false; //如果执行到这,说明出现了异常,返回false就好了
        }
    方法升级

    JDBC管理事务

      管理事务:

         *开启事务:  setAutoCommit(boolean autoCommit) : 调用该方法设置参数为false,既开启事务 手动提交

            *在执行sql之前开启事务

         *提交事务:commit()

            *当所有sql都执行完提交事务

         *回滚事务:rollback()

            *在catch异常中回滚事务

    public class JdbcOperateAffair {
        /**
         * JDBC管理事务
         */
        public static void main(String[] args) {
            Connection conn = null;
            PreparedStatement pstmt = null;
            PreparedStatement pstmt2 = null;
            try {
                conn = JDBCUtils.getConnection();
                //开启事务
                conn.setAutoCommit(false);
    
                //2.定义sql
                    //张三减500 李四+500
                String sql = "update account set balance = balance - ? where id = ?";
                String sql2 = "update account set balance = balance + ? where id = ?";
    
                //3.获取执行sql的对象
                pstmt = conn.prepareStatement(sql);
                pstmt2 = conn.prepareStatement(sql2);
    
                //4.设置参数
                pstmt.setDouble(1,500);
                pstmt.setInt(2,1);
                pstmt2.setDouble(1,500);
                pstmt2.setInt(2,2);
    
                //5.执行sql
                pstmt.executeUpdate();
                pstmt2.executeUpdate();
    
                //提交事务
                conn.commit();
            } catch (Exception e) {
                //出异常了则进行事务的异常
                try {
                    if(conn!=null){
                    conn.rollback();}
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
                e.printStackTrace();
            }finally {
                JDBCUtils.close(pstmt,conn);
                JDBCUtils.close(pstmt2,null);
            }
    
        }
    }
    管理事务
  • 相关阅读:
    Reversion windows 2008 R2 STD to Datacenter
    NetAPP常用操作
    firefox解决flash崩溃
    物理和虚拟兼容性RDM的区别
    网络嗅探器Wireshark
    子网掩码在线计算换算及算法
    Debian中文字体安装
    快算24点,POJ(3983)
    第九十八周,搜索24点
    两次DFS,POJ(1481)
  • 原文地址:https://www.cnblogs.com/caixiaowu/p/13042236.html
Copyright © 2011-2022 走看看