zoukankan      html  css  js  c++  java
  • 10.1(java学习笔记)JDBC基本操作(连接,执行SQL语句,获取结果集)

    一、JDBC

      JDBC的全称是java database connection java数据库连接。

      在java中需要对数据库进行一系列的操作,这时就需要使用JDBC。

      sun公司制定了关于数据库操作的组接口,数据库厂商需要按照这个接口编写对应的实现类。

      数据库厂商编写的实现类就称为数据库驱动。

      java访问数据库流程:

      1.加载驱动:加载数据库厂商提供的实现类。

         2.建立连接:建立程序与数据库的连接

      3.SQL语句:执行相应SQL语句

      4.结果集:得到查询结果。

    二、JDBC访问数据库

      为了便于查看和操作数据库可以下载数据库可视化软件(例如Navicat)。

      2.1准备工作:

        2.1.1 下载驱动

          首先我们需要下载数据库厂商提供的JDBC驱动。

           2.1.2 导入驱动

          由于这些驱动是数据库厂商实现的,并不在java本身的库中,所以需要从外部导入到项目中。

          鼠标右击项目名称--->Bulid Path-->Configure Build Path... --> Libraries  --> Add External JARs...

          -->-->-->

          然后找到下载的JDBC驱动所在文件夹,选择里面的mysql-connector-java-x.x.xx.jar,然后点击OK即可。

          

          添加完毕后项目显示添加的驱动。

          

     

      2.2加载驱动    

    public class TestJDBC{
        public static void main(String[] args){
            try {
                //加载驱动
                System.out.println(Class.forName("com.mysql.cj.jdbc.Driver"));
                //调用froName("x")会初始化名为x的类
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    运行结果:
    class com.mysql.cj.jdbc.Driver

      这样就代表驱动已经加载好了,这里的“com.mysql.cj.jdbc”根据下载的JDBC版本不同可能会略有不同。

      一开始我写的是com.mysql.jdbc,运行后控制台提示:

      Loading class `com.mysql.jdbc.Driver'.
      This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'.

      后来修改为com.mysql.cj.jdbc.Driver就没有问题了,这个在网上查下就可以解决了。

        

      2.3建立连接:建立程序与数据库的连接

        建立数据库连接首先我们需要了解一个类:DriverManager。

        DriverManager:管理JDBC驱动的基本服务,作用于用户和驱动程序之间。

        追踪可用的驱动程序,并在数据库和相关的驱动程序之间建立连接。

        

        主要方法:

        public static Connection getConnection(String url,String user, String password);

        //根据给定的url地址,尝试建立数据库连接。返回一个Connection对象。

        //user,password为用户名和密码。

        

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    
    public class TestJDBC{
        public static void main(String[] args){
            final String connectionUrl = "jdbc:mysql://localhost:3306/mybatis";
            String userName = "root";
            String passWord = "123456";
            try {
                //加载驱动
                System.out.println(Class.forName("com.mysql.cj.jdbc.Driver"));
                Connection conn = DriverManager.getConnection(connectionUrl,userName,passWord);
                //调用froName("x")会初始化名为x的类
                
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    运行后没有报错,代表基本的连接没有问题,报错的原因有很多,一般是url格式错误,或用户名密码错误。

      2.4SQL语句:执行相应SQL语句

        本例所用表结构: (数据库名:mybatis,表名:tadd)

    CREATE TABLE `tadd` (
      `id` varchar(50) NOT NULL,
      `tname` varchar(50) DEFAULT NULL,
      `tpwd` varchar(50) DEFAULT NULL,
      `tstudentnum` varchar(50) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

        上面通过getConnection()建立了连接,并且返回了一个Connection对象。

        我们来看下Connection对象的作用及方法。

        Connection:代表了一个与指定数据库的连接,执行SQL语句返回并在连接上下文中返回结果。

        主要方法:

        Statement createStatement();//创建将SQL语句发送到数据库的语句对象。

        PreparedStatement(String sql);//创建PreparedStatement对象。

        2.4.1 Statement

        Statement:主要用于执行静态的SQL语句,并返回其生成的结果对象。

        主要方法:

        boolean execute(String sql);执行给定的sql语句,可能返回多个结果。

           

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public class TestJDBC{
        public static void main(String[] args){
            final String connectionUrl = "jdbc:mysql://localhost:3306/mybatis";
            String userName = "root";
            String passWord = "123456";
            try {
                //加载驱动
                System.out.println(Class.forName("com.mysql.cj.jdbc.Driver"));
                Connection conn = DriverManager.getConnection(connectionUrl,userName,passWord);
                Statement sta = conn.createStatement();
                boolean b = sta.execute("INSERT INTO `mybatis`.`tadd`"
                        + "(`id`, `tname`, `tpwd`, `tstudentnum`) "
                        + "VALUES ('17', '17', '77', '777');");
                
                System.out.println("执行成功");    
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    运行结果:
    class com.mysql.cj.jdbc.Driver
    执行成功

    我们使用可视化软件查看,发现对应数据库(mybatis)中,对应的表(tadd)里面添加了一条记录。

    Statement有个缺点,不能防止SQL注入。

    例如:

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public class TestJDBC{
        public static void main(String[] args){
            final String connectionUrl = "jdbc:mysql://localhost:3306/mybatis";
            String userName = "root";
            String passWord = "123456";
            try {
                //加载驱动
                System.out.println(Class.forName("com.mysql.cj.jdbc.Driver"));
            //建立连接 Connection conn
    = DriverManager.getConnection(connectionUrl,userName,passWord); // Statement sta = conn.createStatement(); String sql = "delete from tadd where id = 1 or 1=1"; Statement ps = conn.createStatement();//创建Statement对象 ps.execute(sql);//执行SQL语句 System.out.println("执行成功"); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
    运行结果:
    class com.mysql.cj.jdbc.Driver
    执行成功

    使用可视化软件我们可以看到整个表的信息都被删除了。

    这时因为 where id = 1 or 1=1,关键就在后面的or 1=1,在满足id = 1 或者 1=1的条件下删除。

    可1=1恒成立,加上两者又是or的关系,所以所有信息都满足删除都被删除了。

      2.4.2PreparedStatement

        上面我们是使用Statments来执行SQL语句,但它存在一定的缺点。

        这时我们可以使用PreparedStatement,它可以防止SQL注入。

        PreparedStatement:表示预编译SQL语句的对象。

        SQL语句预编译并存储在PreparedStatement对象中。然后可以使用此对象多次高效地执行此语句。

        继承自Statement接口,用于发送一个或多个待输入参数的sql语句。

        主要方法:

        void setObject(int parameterIndex, Object x);//给指定的参数索引设置指定对象x。

        使用Oject的话不用在意参数类型,比较方便。

        除了Object作为参数类型外,还有一些设置具体类型的函数。

        void setNString(int parameterIndex, String value);给指定的参数索引设置指定的String类型的值。

        void setInt(int parameterIndex, int x);给指定的参数索引设置指定的int类型的值。

        void setXXX..(int parameterIndex, XXX x);设置对应类型的值,此处就不一一举例了,详见API。

        此处的参数索引代表占位符的位序,具体含义详见下列代码注释。

        boolean execute();执行SQL语句

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    
    public class TestJDBC{
        public static void main(String[] args){
            final String connectionUrl = "jdbc:mysql://localhost:3306/mybatis";
            String userName = "root";
            String passWord = "123456";
            try {
                //加载驱动
                System.out.println(Class.forName("com.mysql.cj.jdbc.Driver"));
                Connection conn = DriverManager.getConnection(connectionUrl,userName,passWord);
            //    Statement sta = conn.createStatement();
                String sql = "INSERT INTO `mybatis`.`tadd`"
                        + "(`id`, `tname`, `tpwd`, `tstudentnum`) "
                        + "VALUES (?, ?, ?, ?)";//?代表占位符, parameterIndex分别为1,2,3,4
                PreparedStatement ps = conn.prepareStatement(sql);
                ps.setObject(1, "p1");//此处的1代表第一个占位符,即sql语句中第一个问号
                ps.setObject(2, "p2");//第二个占位符,后面参数代表该占位符所代表的值
                ps.setObject(3, "p3");//可用setNString(3,"p3")代替
                ps.setObject(4, "p4");
                ps.execute();//执行sql语句
                System.out.println("执行成功");    
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    运行结果:
    class com.mysql.cj.jdbc.Driver
    执行成功

    可以将sql语句设置为 delete from tadd where id = ?

    再将?设置为 1 or 1= 1,可以发现表中数据并没有被全部删除。

      2.5结果集:得到查询结果。

        boolean excute();返回类型是布尔,如果执行SQL语句返回的是结果集则为true,其他防护false;

        一般select语句才会返回结果集,所以执行select语句execute()返回true.其余语句一般为false.

        excuteQuery();返回结果集,主要用于运行select语句。

        excuteUpdata():返回改变的行数,主要用于insert,update,delete语句。

           

        我们可以根据我们执行的语句,选择合适的方法得到对应的返回值。

        Resultset:表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。

        主要方法:

        boolean next();//将游标移动一行,判断当前移动后的一行是否有数据。

        例如,返回的结果集有,3行(编号依次为1,2,3),游标初始值为0,

        调用next()方法后移动到第一行,如果第一行有数据返回true,反之返回false.

        String getString(int columnLabel);//将当前行中指定列的内容转换为字符串形式。

        注意这里的列从1开始计数,即数据库表中第一列数字为1,第二列数字为2.

        

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    public class TestJDBC{
        public static void main(String[] args){
            final String connectionUrl = "jdbc:mysql://localhost:3306/mybatis";
            String userName = "root";
            String passWord = "123456";
            try {
                //加载驱动
                Class.forName("com.mysql.cj.jdbc.Driver");
                Connection conn = DriverManager.getConnection(connectionUrl,userName,passWord);
            //    Statement sta = conn.createStatement();
                String sql = "select * from tadd where id = ?";
                PreparedStatement ps = conn.prepareStatement(sql);
                ps.setObject(1,"p1");
                ResultSet rs = ps.executeQuery();//返回一个结果集对象
                while(rs.next()){//判断是否有数据
                    System.out.println("查询结果:" +//获取对应列数据
                                       rs.getString(1) + "---" + 
                                       rs.getString(2) + "---" +
                                       rs.getString(3) + "---" +
                                       rs.getString(4));
                }
                System.out.println("执行成功");    
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    运行结果:
    查询结果:p1---p2---p3---p4
    执行成功

    数据库查询完毕后要将创建的各个对象依次关闭,一般是先创立的后关闭。

    以上述代码为例,关闭顺序应该是Resultset-->PreparedStatement-->Connection.

    关闭时最好为每一个对象添加一个try catch语句,不要将三个对象的关闭放在一个try catch中,

    避免关闭其中一个出现异常时,导致其它对象没有关闭。 

    三、批处理

      当我们需要大量(比如上万条)执行某一语句时,建议采用批处理这样可以提高执行效率。

      由于PreparedStatement预编译空间有限,当数据量较大时可能出现异常,所以建议使用Statement。

      基本操作和之前的没有太大区别,只是使用了几个方法。

      setAutoCommit(boolean autoCommit);设置自动提交,默认为true即自动提交,false不自动提交。

      addBatch(String sql);添加处理语句到批中。

      excuteBatch();提交批。

      commit();手动提交

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public class TestJDBC{
        public static void main(String[] args){
            final String connectionUrl = "jdbc:mysql://localhost:3306/mybatis";
            String userName = "root";
            String passWord = "123456";
            Connection conn = null;
            Statement ps = null;
            ResultSet rs = null;
            try {
                //加载驱动
                Class.forName("com.mysql.cj.jdbc.Driver");
                //建立连接
                conn = DriverManager.getConnection(connectionUrl,userName,passWord);
                conn.setAutoCommit(false);//将自动提交设为false,即不进行自动提交
                String sql = "select * from tadd where id = ?";
                ps = conn.createStatement();
                //批处理
                for(int i = 0; i < 10000; i++){
                    ps.addBatch("INSERT INTO `mybatis`.`tadd`"
                            + "(`id`, `tname`, `tpwd`, `tstudentnum`) "
                            + "VALUES ('"+i+"', 'p1', 'p2', 'p3');");
                }
                ps.executeBatch();
                conn.commit();//手动提交
                
                System.out.println("执行成功");    
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally{
                //依次关闭连接
                try {
                    rs.close();
                } catch (Exception e) {
                    // TODO: handle exception
                }
                try{
                    ps.close();
                }catch(Exception e){
                    
                }
                try{
                    conn.close();
                }catch(Exception e){
                }
            }
        }
    }
    运行结果:
    执行成功
    查看数据库可以看到添加了10000条数据。
    批处理就相当于将一个批次的语句打包一起执行,这样比一条一条单独执行效率要高。
  • 相关阅读:
    检测http方法是否开启put方法
    md5爆破工具
    admin密码对应的MD5值
    http账户密码的截取
    CTreeCtrl和CListCtrl失去焦点时高亮选中项
    向OSG视图Viewer发送消息
    在ASP.NET MVC中使用jQuery的Load方法加载静态页面的一个注意点
    jQuery把所有被选中的checkbox的某个属性值连接成字符串
    报错:Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
    在ASP.NET MVC下有关上传图片脏数据的解决方案
  • 原文地址:https://www.cnblogs.com/huang-changfan/p/10244855.html
Copyright © 2011-2022 走看看