JDBC应用

1.概述 

一、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和数据库之间属于进程间的通信,开启之后一定要记得关闭

2.IDEA编写JDBC连接MySQL

2.1 mysql-connector-java的不同版本对比

MySQL Connector / J 5.1 5.1版本支持java5及其以上的版本,支持5.6、5.7、8.0版本的mysql数据库,支持3.0、4.0、4.1、4.2版本的jdbc。在5.1中,Driver的实现类的全路径名是com.mysql.jdbc.Driver。

MySQL Connector / J 8.0 8.0版本支持java8及其以上的版本,支持5.6、5.7、8.0版本的mysql数据库,支持4.2版本的jdbc。在8.0中,Driver的实现类的全路径名是com.mysql.cj.jdbc.Driver。

下图是官网上mysql-connector-java的版本对应的mysql版本和jdk的版本。

  

2.2

2.2.1下载驱动jar包 mysql-connector-java

要使用mysql连接器,就要先下载它。如果是一般的项目,那我们需要下载jar包,然后放到项目的lib目录下。如果使用maven构建的项目,我们可以通过maven直接安装。不同的下载方式有不同的操作,常见的有直接官网下载和maven下载(下周讲解maven)。 下载jar包最直接的方式是从官网下载,官网地址是:MySQL :: Download Connector/J。直接点链接进入mysql官网,选择所需的版本和操作系统(要下载jar包就要选:Platform Independent),然后点击download按钮就可以下载了。为java提供的连接器是Connector / J,也就是mysql-connector-java,它分为5.1版本和8.0版本。Connector / J实现了JDBC,为使用java开发的程序提供连接,方便java程序操作数据库。

  

2.2.2 从maven安装

使用maven安装mysql-connector-java就简单很多,直接打开maven的中央仓库地址,输入mysql-connector-java就可以找到不同版本的依赖。地址:https://mvnrepository.com/artifact/mysql/mysql-connector-java

2.2.3 IDEA导入jar包

先检查jar包位置:在目录里新建一个文件夹 libs,把jar包复制进去

然后右键选择新建文件夹libs转成library

然后就可以写代码啦!

根据六步编写代码:先不写处理代码

3 JDBC连接mysql 程序编写

3.1 第一种注册驱动方式

import com.mysql.jdbc.Driver;
​
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
​
/*
    1.注册驱动(告诉Java程序,即将连接的是哪个品牌的数据库)
    2.获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,使用完后记得关闭通道)。
    3.获取数据库操作对象(专门执行sql语句的对象)
    4.执行SQL语句(DQL,DML…)
    5.处理查询结果集 (只有当第四步执行的是select语句的时候,才有本步)
    6.释放资源(使用完资源后一定要关闭资源,Java和数据库之间属于进程间的通信,开启之后一定要记得关闭)
 */
public class JDBCTest1 {
    public static void main(String[] args) {
        Connection conn = null;
        Statement state = null;
​
​
        //1.注册驱动(告诉Java程序,即将连接的是哪个品牌的数据库)
        //第一种注册驱动的方式
        //jdk本身提供了一个工具类DriverManager给我们使用,其中有一个方法用于注册驱动的作用,registerDriver(Driver driver)
        //注册与给定的驱动程序 DriverManager 。  可以实现注册驱动的功能
        //通过观察发现,jdk本身没有实现Driver接口的实现,但是我们在mysql驱动包中找到了实现该接口的实现类。
        try {
            DriverManager.registerDriver(new Driver());
            //2.获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,使用完后记得关闭通道)。
            //jdk中提供了一个工具类DriverManager,其中有一个静态的方法,可以让我们调用并且获取与要使用的数据的连接对象
            //static Connection getConnection(String url, String user, String password)
            //尝试建立与给定数据库URL的连接。
            /**
             * url: 统一资源定位系统
             *      http/https  通过网络去请求网络上的资源
             *      jdbc:mysql  驱动包提供的请求头
             *      请求的地址    指定mysql数据库安装的服务器地址:192.168.169.100
             *      端口号       3306
             *      useUnicode=true&characterEncoding=utf8
             *
             * jdbc:mysql://192.168.169.100:3306/数据库名?useUnicode=true&characterEncoding=utf8&useSSL=false
             */
            //mysql5.7之后警告用户不要直接访问数据库服务器
            String url = "jdbc:mysql://192.168.169.100:3306/bigdata23?useUnicode=true&characterEncoding=utf8&useSSL=false";
            String user = "root";
            String password = "123456";
            conn = DriverManager.getConnection(url, user, password);
            //如果连接不上可能导致的问题
            //1、检查虚拟机,服务器是否启动
            //2、检查防火墙是否关闭,指的是虚拟机或者服务器的防火墙
            //3、检查url地址,用户名,密码
            System.out.println("与mysql数据库建立连接成功!!" + conn);
​
            //3.获取数据库操作对象(专门执行sql语句的对象)
            state = conn.createStatement();
​
            //4.执行SQL语句(DQL,DML…)
            //DQL
            //ResultSet executeQuery(String sql)
            //执行sql语句,该语句返回查询的结果,只能是查(select)
​
            //DML
            //int executeUpdate(String sql)
            //执行给定的SQL语句,这里可以是增(insert),删(delete),更新(update)
            //该方法的返回值指的是受影响的行数
            String sql1 = "insert into dept(deptno,dname,loc) values(60,'教学部','安徽合肥')";
            int count = state.executeUpdate(sql1);
            if (count == 1) {
                System.out.println("数据保存成功!!");
            } else {
                System.out.println("数据保存失败!!");
            }
​
​
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //6.释放资源(使用完资源后一定要关闭资源,Java和数据库之间属于进程间的通信,开启之后一定要记得关闭)
            if (state != null) {
                try {
                    state.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
​
        }
​
    }
}

3.2 第二种注册驱动方式

使用反射的方式加载驱动类

​
import com.mysql.jdbc.Driver;
​
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
​
/*
    驱动注册的第二种方式
 */
public class JDBCTest2 {
    public static void main(String[] args) throws Exception {
        //使用反射的第三种方式直接获取mysql数据库的驱动类,今后最常用的方式
        Class.forName("com.mysql.jdbc.Driver");
​
        Connection conn = null;
        Statement state = null;
​
​
        //1.注册驱动(告诉Java程序,即将连接的是哪个品牌的数据库)
        //第一种注册驱动的方式
        //jdk本身提供了一个工具类DriverManager给我们使用,其中有一个方法用于注册驱动的作用,registerDriver(Driver driver)
        //注册与给定的驱动程序 DriverManager 。  可以实现注册驱动的功能
        //通过观察发现,jdk本身没有实现Driver接口的实现,但是我们在mysql驱动包中找到了实现该接口的实现类。
        try {
//            DriverManager.registerDriver(new Driver());
            //2.获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,使用完后记得关闭通道)。
            //jdk中提供了一个工具类DriverManager,其中有一个静态的方法,可以让我们调用并且获取与要使用的数据的连接对象
            //static Connection getConnection(String url, String user, String password)
            //尝试建立与给定数据库URL的连接。
            /**
             * url: 统一资源定位系统
             *      http/https  通过网络去请求网络上的资源
             *      jdbc:mysql  驱动包提供的请求头
             *      请求的地址    指定mysql数据库安装的服务器地址:192.168.169.100
             *      端口号       3306
             *      useUnicode=true&characterEncoding=utf8
             *
             * jdbc:mysql://192.168.169.100:3306/数据库名?useUnicode=true&characterEncoding=utf8&useSSL=false
             */
            //mysql5.7之后警告用户不要直接访问数据库服务器
            String url = "jdbc:mysql://192.168.169.100:3306/bigdata23?useUnicode=true&characterEncoding=utf8&useSSL=false";
            String user = "root";
            String password = "123456";
            conn = DriverManager.getConnection(url, user, password);
            //如果连接不上可能导致的问题
            //1、检查虚拟机,服务器是否启动
            //2、检查防火墙是否关闭,指的是虚拟机或者服务器的防火墙
            //3、检查url地址,用户名,密码
            System.out.println("与mysql数据库建立连接成功!!" + conn);
​
            //3.获取数据库操作对象(专门执行sql语句的对象)
            state = conn.createStatement();
​
            //4.执行SQL语句(DQL,DML…)
            //DQL
            //ResultSet executeQuery(String sql)
            //执行sql语句,该语句返回查询的结果,只能是查(select)
​
            //DML
            //int executeUpdate(String sql)
            //执行给定的SQL语句,这里可以是增(insert),删(delete),更新(update)
            //该方法的返回值指的是受影响的行数
//            String sql1 = "insert into dept(deptno,dname,loc) values(60,'教学部','安徽合肥')";
//            int count = state.executeUpdate(sql1);
//            if (count == 1) {
//                System.out.println("数据保存成功!!");
//            } else {
//                System.out.println("数据保存失败!!");
//            }
​
            //修改
//            String sql2 = "update dept set loc='合肥' where deptno=60";
//            int count2 = state.executeUpdate(sql2);
//            if (count2 == 1) {
//                System.out.println("数据修改成功!!");
//            } else {
//                System.out.println("数据修改失败!!");
//            }
​
            //删除
            String sql3 = "delete from dept where deptno=60";
            int count3 = state.executeUpdate(sql3);
            if (count3 == 1) {
                System.out.println("数据删除成功!!");
            } else {
                System.out.println("数据删除失败!!");
            }
​
​
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //6.释放资源(使用完资源后一定要关闭资源,Java和数据库之间属于进程间的通信,开启之后一定要记得关闭)
            if (state != null) {
                try {
                    state.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
​
        }
    }
}

3.3 将连接数据库的所有信息配置到配置文件中

import java.io.BufferedReader;
import java.io.FileReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.Properties;
​
/*
    通过读取配置文件获取数据库连接信息
    java xxx.jar xxx
 */
public class JDBCTest3 {
    public static void main(String[] args) throws Exception {
        //1、加载数据库的驱动
        Class.forName("com.mysql.jdbc.Driver");
​
        //读取配置文件获取url,用户名和密码
        Properties prop = new Properties();
        prop.load(new BufferedReader(new FileReader("E:\\projects\\IDEAProjects\\bigdata23-project\\bigdata23-project\\bigdata23-jdbc\\src\\main\\java\\com\\shujia\\wyh\\utils\\mysqlinfo.properties")));
        String url = prop.getProperty("url");
        String username = prop.getProperty("username");
        String password = prop.getProperty("password");
​
        //2、获取数据库的连接对象
        Connection conn = DriverManager.getConnection(url, username, password);
​
        //3、获取数据库操作对象
        Statement state = conn.createStatement();
​
        //4、编写sql语句,执行sql
        String sql = "insert into dept values(60,'兰智数加学院','安徽合肥')";
        int count = state.executeUpdate(sql);
        if(count==1){
            System.out.println("数据添加成功!!");
        }else {
            System.out.println("数据添加失败!!");
        }
​
        //6、释放资源
        state.close();
        conn.close();
    }
}

使用工具类改进获取连接代码

import java.io.BufferedReader;
import java.io.FileReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;
​
/*
    编写一个工具类获取连接对象
 */
public class MysqlTool {
    private MysqlTool(){}
    
    public static Connection getConnection(){
        Connection conn = null;
        try {
            //1、加载数据库的驱动
            Class.forName("com.mysql.jdbc.Driver");
​
            //读取配置文件获取url,用户名和密码
            Properties prop = new Properties();
            prop.load(new BufferedReader(new FileReader("E:\\projects\\IDEAProjects\\bigdata23-project\\bigdata23-project\\bigdata23-jdbc\\src\\main\\java\\com\\shujia\\wyh\\utils\\mysqlinfo.properties")));
            String url = prop.getProperty("url");
            String username = prop.getProperty("username");
            String password = prop.getProperty("password");
​
            //2、获取数据库的连接对象
            conn = DriverManager.getConnection(url, username, password);
            
        }catch (Exception e){
            e.printStackTrace();
        }
        
        if(conn!=null){
            System.out.println("与数据连接建立成功!!");
        }else {
            System.out.println("与数据连接建立失败!!");
        }
        
        return conn;
    }
    
}

3.4 处理查询结果集

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
​
public class JDBCTest4 {
    public static void main(String[] args) {
        Connection conn = null;
        Statement state = null;
        try {
            //获取连接对象
            conn = MysqlTool.getConnection();
​
            //获取数据库操作对象
            state = conn.createStatement();
​
            //查询
            String sql = "select deptno as a1,dname,loc from dept";
            ResultSet rs = state.executeQuery(sql);
            //通过观察api发现,判断下一行是否有数据,使用next()方法进行判断,如果有数据返回true,反之返回false
            while (rs.next()){
                //获取数据
                //ResultSet结果集类型中有一个方法可以获取数据
                //第一种获取数据的方式:通过列的下标索引进行获取
                //String getString(int columnIndex)
                //结果行中的列从左往右编号,从1开始
//                String deptno = rs.getString(1);
//                String dname = rs.getString(2);
//                String loc = rs.getString(3);
//                System.out.println("部门编号:"+deptno+",部门名称:"+dname+",地址:"+loc);
​
                //第二种获取数据的方式:通过列的名称进行获取
                //如果查询语句中有别名的列存在,第二种方式查询的时候,使用别名获取这一列
                String deptno = rs.getString("a1");
                String dname = rs.getString("dname");
                String loc = rs.getString("loc");
                System.out.println("部门编号:" + deptno + ",部门名称:" + dname + ",地址:" + loc);
            }
​
​
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(state!=null){
                try {
                    state.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
​
    }
}

3.5 ​登录注册案例

package com.bigdata.java;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
import java.util.UUID;

public class LoginRegisterExample {
    public static void main(String[] args) throws SQLException {
        Scanner sc = new Scanner(System.in);
        System.out.println("*********************欢迎来到测试系统**********************");

        //进行数据库连接
        Connection conn=MysqlTool.getConn();
        Statement state=conn.createStatement();

        //进行登录
        System.out.println("请输入用户名:");
        String user=sc.nextLine();
        System.out.println("请输入密码:");
        String password=sc.nextLine();

        //判断是否注册(即数据库中是否有用户信息)
        String sql="select user,password from userinfo where user='"+user+"' and password='"+password+"'";
        ResultSet rs = state.executeQuery(sql);
        if(rs.next()){
            System.out.println("登录成功!!");
        }else{
            System.out.println("登录失败!!用户信息不存在");
            System.out.println("是否进行注册(Y/N)");
            String flag =sc.nextLine();
            if("Y".equals(flag)){
                System.out.println("请输入用户名:");
                String user1=sc.nextLine();
                System.out.println("请输入密码:");
                String password1=sc.nextLine();
                System.out.println("请再次输入密码");
                String password2=sc.nextLine();
                if (password1.equals(password2)){
                    UUID uuid = UUID.randomUUID();
                    String sql1="insert into userinfo values('"+uuid+"','"+user1+"','"+password1+"')";
                    int count = state.executeUpdate(sql1);
                    if(count==1){
                        System.out.println("注册成功!!");
                    }else{
                        System.out.println("系统错误,注册失败!");
                    }
                }else{
                    System.out.println("俩次密码输入不一致,再见!!");
                }
            }else{
                System.out.println("再见,期待您的使用!");
            }

        }
    }
}

​此时会出现bug,原因是输入的字符串可能永远为true,先进行了sql的拼接,然后再编译

我们经过不断地测试发现一个问题:如果我们是先进行sql拼接,然后再对sql整体做编译的话,会将一些拼接的内容作为sql语法关键字进行处理
但是我们实际上输入的字符就是普通的字符串,不应该当作sql语法的编译。

于是java和mysql团队发现了这个bug(sql注入的问题),于是提供了另一种方式获取数据库操作对象。
解决方案:将原来的先拼接再编译sql的步骤换成:先编译再拼接。
import java.sql.*;
import java.util.Scanner;
import java.util.UUID;

public class LoginRegisterUpdate {
    public static void main(String[] args) throws SQLException {
        Scanner sc = new Scanner(System.in);
        System.out.println("*********************欢迎来到测试系统**********************");

        //进行数据库连接
        Connection conn=MysqlTool.getConn();
        //提供预编译对象进行处理,提前编译好,需要传参的地方用?代替
        PreparedStatement state=conn.prepareStatement("select user,password from userinfo where user=? and password=?");


        //进行登录
        System.out.println("请输入用户名:");
        String user=sc.nextLine();
        System.out.println("请输入密码:");
        String password=sc.nextLine();
        //传参
        state.setString(1,user);
        state.setString(2,password);

        //判断是否注册(即数据库中是否有用户信息)
        ResultSet rs = state.executeQuery();
        if(rs.next()){
            System.out.println("登录成功!!");
        }else{
            System.out.println("登录失败!!用户信息不存在");
            System.out.println("是否进行注册(Y/N)");
            String flag =sc.nextLine();
            if("Y".equals(flag)){
                System.out.println("请输入用户名:");
                String user1=sc.nextLine();
                System.out.println("请输入密码:");
                String password1=sc.nextLine();
                System.out.println("请再次输入密码");
                String password2=sc.nextLine();
                if (password1.equals(password2)){
                    UUID uuid = UUID.randomUUID();
                    String sql1="insert into userinfo values('"+uuid+"','"+user1+"','"+password1+"')";
                    int count = state.executeUpdate(sql1);
                    if(count==1){
                        System.out.println("注册成功!!");
                    }else{
                        System.out.println("系统错误,注册失败!");
                    }
                }else{
                    System.out.println("俩次密码输入不一致,再见!!");
                }
            }else{
                System.out.println("再见,期待您的使用!");
            }

        }
    }
}

JDBC事物机制:
1.JDBC中的事务自动提交的,什么是自动提交?
只要执行任意一条 DML语句,则自动提交一次。这是JDBC默认的事务行为。
但是在实际的业务中,通常都是N条DML语句共同联合才能完成,必须
保证这些DML语句在同一个事务中同时成功或者同时失败
解决方案:三行重要的代码
conn.setAutoCommit(false);//手动提交事务
conn.commit();//提交事务
conn.rooback;当发生异常时或者程序错误时,进行回滚。 

3.6 JDBC模糊查询

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

public class MysqlConnTest5 {
    public static void main(String[] args) throws SQLException {
        //进行连接
        Connection connection=MysqlTool.getConn();
        //获取数据库操作对象
        PreparedStatement pps = connection.prepareStatement("select user,password from userinfo where user like ?");
        //传参
        pps.setString(1,"小%");
        ResultSet rs = pps.executeQuery();

        while(rs.next()){
            String user=rs.getString(1);
            String password = rs.getString(2);
            System.out.println(user+"---"+password);
        }

        pps.close();
        connection.close();
    }
}

3.7 悲观锁和乐观锁的概念

事务1–>读取到版本号1.1 事务2—>读取到版本号1.1

其中事务1先修改了,修改之后看了版本号是1.1 ,于是提交修改的数据,将版本号修改为1.2 其中事务2后修改的,修改之后准备提交的时候,发现版本号是1.2 ,和它最初读的版本号不一致。回滚。

悲观锁:事务必须排队执行。数据锁住了,不允许并发。 (行级锁: select后面添加for update ) 乐观锁:支持并发,事务也不需要排队,只不过需要一个版本号。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值