【JDBC】Java DataBase ConnectivityJava语言连接数据库

一、JDBC是什么?

二、JDBC的本质是什么?

三、为什么要面向接口编程?

四、为什么SUN制定一套JDBC接口呢?

五、JDBC编程六步(需要背会)

六、添加依赖

七、IDEA编写JDBC连接MySQL

八、处理结果集

九、java中的配置文件

十、用户登录例子(不安全)

十一、用户登录(安全)预编译

十二、向数据库表中插入一行数据   

十三、读取文件,将文件的多行数据插入到数据库表中

十四、优化:一次插入多行数据


一、JDBC是什么?

Java DataBase Connectivity(Java语言连接数据库)

二、JDBC的本质是什么?

JDBC是SUN公司制定的一套接口(interface)。

接口都有调用者和实现者。

面向接口调用、面向接口写实现类,这都属于面向接口编程。

三、为什么要面向接口编程?

解耦合:降低程序的耦合度,提高程序的扩展力。

多态机制就是非常典型的:面向抽象编程。(不要面向具体编程)

(这里需要画图带大家理解。。。)

四、为什么SUN制定一套JDBC接口呢?

因为每一个数据库产品都有自己独特的实现原理

五、JDBC编程六步(需要背会)

1.注册驱动(告诉Java程序,即将连接的是哪个品牌的数据库)

2.获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,使用完后记得关闭通道)。

3.获取数据库操作对象(专门执行sql语句的对象)

4.执行SQL语句(DQL,DML…)

5.处理查询结果集 (只有当第四步执行的是select语句的时候,才有本步)

6.释放资源(使用完资源后一定要关闭资源,Java和数据库之间属于进程间的通信,开启之后一定要记得关闭)

六、添加依赖

   <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>
    </dependencies>
 

七、IDEA编写JDBC连接MySQL

第一种注册驱动

package com.wx;

import  com.mysql.jdbc.Driver;

import java.sql.*;


public class Text01 {
    public static void main(String[] args) throws SQLException {

        //1、注册驱动
        //创建驱动对象
        Driver driver = new Driver();
        DriverManager.registerDriver(driver);//获取到了类型


        //2、获取连接Mysql
        //getConnection(String url, String user, String password)
        //URL -> jdbc:subprotocol:subname
        //       jdbc:mysql://192.168.253.80:3306/bigdata22?useSSL=false
        //       jdbc-> 协议
        //       mysql -> 数据库名称
        // 将SSL认证关闭
        //

        String url ="jdbc:mysql://192.168.40.100:3306/bigdata22?useSSL=false";
        String user = "root";
        String password="123456";
        //数据库的连接对象
        Connection con = DriverManager.getConnection(url, user, password);



        //3、获取执行SQL语句的·对象
        Statement statement = con.createStatement();


        //4、执行SQL
        String sql ="select * from dept";
        ResultSet resultSet = statement.executeQuery(sql);
        System.out.println(resultSet);

         //5、处理结果集
        //resultSet.next 当前光标是在数据集之外,如果执行一次next指针对应有数据,那么返回True,否则返回False

        while(resultSet.next()){
            //获取列的下标是从1开始的
            //获取第一列
            String string = resultSet.getString(1);
            String string1 = resultSet.getString(2);

            //获取loc列,名称不区分大小写
            String loc = resultSet.getString("loc");
            //System.out.println(loc);
            System.out.println(String.format("string:%s \t string1:%s \t loc:%s",string,string1,loc));
            
        }
        //6、关闭连接
        statement.close();
        con.close();
    }
}

第二中注册驱动:通过反射

package test02;

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

public class Test02 {


    public static void main(String[] args) throws Exception {


        /**
         *
         *  注册驱动的另一种方式(最常用的方式)
         *   1、注册驱动(告诉Java程序,即将连接的是哪个品牌的数据库)
         *         DriverManager.registerDriver(new com.mysql.jdbc.Driver());
         *  注册驱动的第二种写法:
         *         但是今后我们实际开发的时候,驱动包可能不太一样,今天我们连接mysql可能后天我们连接redis,所以这里的类不是一定的
         *         将来我们开发好一个程序后,这里的参数是不允许随意改动的,更希望传一个字符串,方便我们后期做配置文件传参
         *         通过反射可以获取一个字节码文件对象中的功能
         */

        Class.forName("com.mysql.jdbc.Driver");
        String url ="jdbc:mysql://192.168.40.100:3306/bigdata22?useSSL=false";
        String user ="root";
        String password = "123456";
        Connection connection = DriverManager.getConnection(url, user, password);

        Statement statement = connection.createStatement();


        String sql="select * from  dept ";
        ResultSet resultSet = statement.executeQuery(sql);


        while (resultSet.next()){
            String string = resultSet.getString(1);
            System.out.println(string);


        }

        statement.close();
        connection.close();

    }
}

八、处理结果集

1、如果是查询语句,就调用executeQuery()返回一个结果集

String sql ="select * from dept";
ResultSet resultSet = statement.executeQuery(sql);
System.out.println(resultSet);

 //处理结果集
 //resultSet.next 当前光标是在数据集之外,如果执行一次next指针对应有数据,那么返回True,否则返回False

 while(resultSet.next()){
      //获取列的下标是从1开始的
      //获取第一列
      String string = resultSet.getString(1);
      String string1 = resultSet.getString(2);
      //获取loc列,名称不区分大小写
      String loc = resultSet.getString("loc");

          
   System.out.println(String.format("string:%s \t string1:%s \t loc:%s",string,string1,loc));
            

2、如果是更新操作  insert into      delet from...........返回的是受影响的行数,可以判断是否插入成功

String sql ="delete from emp where ename in (select ena from ((select ename as ena from emp  where sal>(select avg(sal) as avg from emp)) as a))";
        int rows = statement.executeUpdate(sql);
        System.out.println(rows);

        //5、处理结果
        if(rows>0){
            System.out.println("删除成功。。。");
        }else{
            System.out.println("删除失败。。。");
        }

九、java中的配置文件

Java中的配置文件名称一般都以“.properties”和“.xml”进行结尾,这些配置文件的结构都和Java的HashMap结构是一样的,其作用是通过修改配置文件来实现代码中的参数的更改,从而实现灵活变更参数。

package com.wx;


import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;

/**
 * 需求:为了防止生产环境和开发环境所连接的Mysql数据库不一致导致需要修改代码,
 *              所以可以将连接信息放在配置文件中
 *
 *  注意在项目中,一般配置文件需要放在Resources目录中
 */
public class Test03Properties {
    public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {



        在配置文件中,文件以.properties结尾,
        // 并且文件中格式为 key=value
        //load方法其实就是逐行读取properties配置文件,
        // 分隔成两个字符串key和value,将他们放进Properties对象中。

        //后面如果需要用到这些值,直接调用Properties对象就可以了。
        Properties properties=new Properties();
        properties.load(new FileReader("D:\\Project\\bigdatda22\\mvn_project\\jdbc_mysql\\src\\main\\resources\\jdbc.properties"));

        //1、注册驱动
        //mysql驱动会改,这种方式,只需要修改配置文件就可以了
        String driver = properties.getProperty("driver");
        通过反射可以获取一个字节码文件对象中的功能
        Class.forName(driver);


        //2、获取连接

        String url = properties.getProperty("url");//读取配置文件中的属性
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");

        Connection connection = DriverManager.getConnection(url, user, password);



        //获取执行对象
        Statement statement = connection.createStatement();

        //执行sql
        String sql="select * from dept";
        ResultSet resultSet = statement.executeQuery(sql);


        //处理结果
        while (resultSet.next()){
            //光标指向的是行数据
            //取数据的时候,是一列一列取的
            //getString()方法的特点是,不管数据库中字段数据是什么类型的,取出来都是String类型
            //这里方法中的参数是int类型数据,1,2,3等代表的是第几列
            //String empno = resultSet.getString(1); //JDBC中所有的下标都是从1开始
            String string = resultSet.getString(1);
            String string1 = resultSet.getString(2);
            System.out.println(string+"\t"+string1);//通过空格拼接

        }
        //关闭连接
        //先关闭里面的
        statement.close();
        connection.close();
    }
}

配置文件

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://192.168.40.100:3306/bigdata22?useSSL=false
user=root
password=123456

十、用户登录例子(不安全)

package com.wx;

import java.sql.*;

public class Test04UserLogin {
    static Connection con;
    //在静态代码块中,创建连接
    //在类加载的时候就进行初始化
    static {
        try {
            //1、注册驱动
            通过反射可以获取一个字节码文件对象中的功能
            Class.forName("com.mysql.jdbc.Driver");

        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }


        //2、获取连接
        String url ="jdbc:mysql://192.168.40.100:3306/bigdata22?useSSL=false";
        String user = "root";
        String password="123456";
        //数据库的连接对象
        try {
            con = DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

    }

    public static boolean login(String id ,String password) throws SQLException {



        //3、获取执行的对象
        Statement statement = con.createStatement();

        //4、执行sql
        //字符串拼接
        //select * from user_info WHERE user_id = "   id " and pw = md5(" password");

        //select * from user_info WHERE user_id = '   id ' and pw = md5(' password')

        String sql =  "select * from user_info WHERE user_id = '"+ id+" ' and pw = md5('" + password + "')";


        ResultSet resultSet = statement.executeQuery(sql);

        //5、处理结果
        if(resultSet.next()){
            return true;
        }else {
            return false;
        }

    }


    public static void main(String[] args) throws SQLException {

        //boolean login = login("1001", "123456");
        //虽然加密了,任然可以登录成功,语法漏洞
        boolean login = login("1001", "')or('1'='1");

        if(login){
            System.out.println("登录成功");
        }else{
            System.out.println("登录失败");
        }
    }


}

十一、用户登录(安全)预编译

package com.wx;

import java.sql.*;

public class Test05SafeLogin02 {
    static Connection con;
    //在静态代码块中,创建连接
    //在类加载的时候就进行初始化
    static {
        try {
            //1、注册驱动
            通过反射可以获取一个字节码文件对象中的功能
            Class.forName("com.mysql.jdbc.Driver");

        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }


        //2、获取连接
        String url ="jdbc:mysql://192.168.40.100:3306/bigdata22?useSSL=false";
        String user = "root";
        String password="123456";
        //数据库的连接对象
        try {
            con = DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

    }


    public static boolean login(String id ,String password) throws SQLException {

        //3、获取执行的对象
       // Statement statement = con.createStatement();
        //4、执行sql
        //字符串拼接
        //String sql =  "select * from user_info WHERE user_id = '"+ id+" ' and pw = md5('" + password + "')";
        //ResultSet resultSet = statement.executeQuery(sql);


/**
 *      解决sql注入的问题
 只要用户提供的信息不参与sql语句编译过程就好了,这样的话问题就得到解决
 java中提供了另外一个接口给我们使用java.sql.PreparedStatement

 这个接口继承自原本Statement接口

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

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

 综上所述:大部分情况下,使用PreparedStatement,有些情况下使用statement,如果将来需要手动输入升序或者降序的时候
 */
        // 预编译模式,在SQL执行之前将SQL编译成功
        //在本地直接生成一个编译过程,再把结果发给mysql编译器
        //这里问号相当于一个占位符,将来需要传值的
        String sql =  "select * from user_info WHERE user_id = ?  and pw = md5(?)";
        //二、查询数据
        PreparedStatement preparedStatement = con.prepareStatement(sql);
        //1表示第一个占位
        // 给占位符 ? 进行传值,(第一个问号下标是1,第二个问号下标是2,依次类推)
        preparedStatement.setString(1,id);
        preparedStatement.setString(2,password);
        //执行sql
        ResultSet resultSet = preparedStatement.executeQuery();


        if(resultSet.next()){
            preparedStatement.close();
            return true;
        }else {
            preparedStatement.close();
            return false;
        }

    }


    public static void main(String[] args) throws SQLException {

        boolean login = login("1001", "123456");
        //虽然加密了,任然可以登录成功,语法漏洞
        //使用preparedStatement就不能成功了
       // boolean login = login("1001", "')or('1'='1");


        if(login){
            System.out.println("登录成功");
        }else{
            System.out.println("登录失败");
        }
    }

}

十二、向数据库表中插入一行数据   

    用preparedStatemen.setString()传值

package com.wx;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Test07Insert {


    static Connection con;

    //在静态代码块中,创建连接
    //在类加载的时候就进行初始化
    static {
        try {
            //1、注册驱动
            通过反射可以获取一个字节码文件对象中的功能
            Class.forName("com.mysql.jdbc.Driver");

        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }


        //2、获取连接
        //&useUnicode=true&characterEncoding=UTF-8

        String url ="jdbc:mysql://192.168.40.100:3306/bigdata22?useSSL=false&useUnicode=true&characterEncoding=UTF-8";
        String user = "root";
        String password="123456";
        //数据库的连接对象
        try {
            con = DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

    }



    public static void main(String[] args) throws SQLException {
        String sql = "insert into foods_info  values (?,?,?,?,?)";
//¥1590.00,4000+人付款,【情人节礼物】SK-II神仙水精华液护肤精华水补水紧致抗皱skllsk2,skii官方旗舰店,江苏 苏州
        PreparedStatement preparedStatement = con.prepareStatement(sql);
        preparedStatement.setString(1,"¥1590.00");
        preparedStatement.setString(2,"4000+人付款");
        preparedStatement.setString(3,"【情人节礼物】SK-II神仙水精华液护肤精华水补水紧致抗皱skllsk2");
        preparedStatement.setString(4,"skii官方旗舰店");
        preparedStatement.setString(5,"江苏 苏州");

        int rows = preparedStatement.executeUpdate();
        if(rows>0){
            System.out.println("插入成功");
        }else {
            System.out.println("插入失败");
        }
    }


}

十三、读取文件,将文件的多行数据插入到数据库表中

可能会存在编码格式问题,解决办法:在连接的url后面加上

&useUnicode=true&characterEncoding=UTF-8

 用preparedStatemen

package com.wx;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;


/**
 * 该方式为在while循环中,每读取一行数据,之后将数据包装并连接Mysql,将SQL发送至Mysql进行执行,再获取结果。
 *      这样整个过程相对较慢。和MySQL握手的时间较长,所以优化的方向为:减少访问次数
 *
 */

public class Test08Insert02 {

    static Connection con;

    //在静态代码块中,创建连接
    //在类加载的时候就进行初始化
    static {
        try {
            //1、注册驱动
            通过反射可以获取一个字节码文件对象中的功能
            Class.forName("com.mysql.jdbc.Driver");

        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }


        //2、获取连接
        //&useUnicode=true&characterEncoding=UTF-8

        String url ="jdbc:mysql://192.168.40.100:3306/bigdata22?useSSL=false&useUnicode=true&characterEncoding=UTF-8";
        String user = "root";
        String password="123456";
        //数据库的连接对象
        try {
            con = DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

    }


    public static void main(String[] args) throws Exception {

        long satrtTime = System.currentTimeMillis();


        //1、IO流读取数据
        //读取一行
        BufferedReader bufferedReader = new BufferedReader(new FileReader("D:\\Project\\bigdatda22\\mvn_project\\jdbc_mysql\\data\\foods.csv"));

        String sql = "insert into foods_info  values (?,?,?,?,?)";
//¥1590.00,4000+人付款,【情人节礼物】SK-II神仙水精华液护肤精华水补水紧致抗皱skllsk2,skii官方旗舰店,江苏 苏州

        PreparedStatement preparedStatement = con.prepareStatement(sql);
        String line =null;
        int count =0;
        while ((line = bufferedReader.readLine())!=null){
            //2、对数据进行切分
            String[] split = line.split(",");

            // 3、执行sql, 将数据填充到数据库
            //先传值
            preparedStatement.setString(1,split[0]);
            preparedStatement.setString(2,split[1]);
            preparedStatement.setString(3,split[2]);
            preparedStatement.setString(4,split[3]);
            preparedStatement.setString(5,split[4]);
             // 每填充一行数据,就可以到数据库中执行
            //4、再执行
            int rows = preparedStatement.executeUpdate();

            count +=1;

            if(rows>0){
                System.out.println(count+"行插入成功");
            }else {
                System.out.println("插入失败");
            }
        }

        long endTime = System.currentTimeMillis();
        System.out.println((endTime-satrtTime)/100);
        //5、关闭
        preparedStatement.close();
        con.close();
    }

}

十四、优化:一次插入多行数据

在SQL中 Values后可以跟多行数据 可以在代码中对SQL语句进行拼接 , 拼接就不能用预编译的模式。用statement。

package com.wx;

import java.io.BufferedReader;
import java.io.FileReader;
import java.sql.*;

/**
 *
 * 优化思路:
 *      在SQL中 Values后可以跟多行数据 可以在代码中对SQL语句进行拼接
 *      拼接就不能用预编译的模式
 *
 *      将数据拼接五行行以后再去提交执行。
 */


    public class Test09Insert03 {

        static Connection con;
        //在静态代码块中,创建连接
        //在类加载的时候就进行初始化
        static {
            try {
                //1、注册驱动
                通过反射可以获取一个字节码文件对象中的功能
                Class.forName("com.mysql.jdbc.Driver");

            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
            //2、获取连接
            //&useUnicode=true&characterEncoding=UTF-8

            String url ="jdbc:mysql://192.168.40.100:3306/bigdata22?useSSL=false&useUnicode=true&characterEncoding=UTF-8";
            String user = "root";
            String password="123456";
            //数据库的连接对象
            try {
                con = DriverManager.getConnection(url, user, password);
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }



        public static void main(String[] args) throws Exception {



            //1、IO流读取数据 创建读取对象 字符缓冲流
            BufferedReader bufferedReader = new BufferedReader(new FileReader("D:\\Project\\bigdatda22\\mvn_project\\jdbc_mysql\\data\\foods.csv"));

            //获取执行对象
            Statement statement = con.createStatement();


            String line =null;
            int count =0;
            long satrtTime = System.currentTimeMillis();

            while ((line = bufferedReader.readLine())!=null){

                //2、对数据进行切分
                String[] split = line.split(",");


                // 3、执行sql, 将数据填充到数据库
                String sql = "insert into foods_info  values ";
                String oneline = String.format("('%s','%s','%s','%s','%s'),", split[0], split[1], split[2], split[3], split[4]);


                //sql拼接

                sql+=oneline;
                //格式
                //sql1 = insert into foods_info  values  (split[0], split[1], split[2], split[3], split[4]), (split[0], split[1], split[2], split[3], split[4]),最后有个逗号,需要
                //count++;不能用
                count+=1;


                if(count>=5){
                    int rows = statement.executeUpdate(sql.substring(0,sql.length()-1));
                    //截取字符串获取从0开始,到倒数第二个字符的字符串,就能把逗号去掉
                    //给下次的sql初始化一下
                    sql = "insert into foods_info values ";
                    if(rows>0){
                        System.out.println(count + "行插入成功");
                    }else {
                        System.out.println("插入失败");
                    }
                    count = 0;
                }
            }


            //用时
            long endTime = System.currentTimeMillis();
            System.out.println((endTime-satrtTime)/10);


            //5、关闭
            statement.close();
            con.close();
        }

    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值