搞懂JDBC这一篇就够了!!!(二)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 搞懂JDBC这一篇就够了!!!(二)

三、JDBC工具类



目的


简化书写


分析


1.注册驱动也抽取


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


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


解决:properties配置文件


url=jdbc:mysql:///db2
user=root
password=root
driver=com.mysql.jdbc.Driver


抽取一个方法释放资源


package cn.caq.utils;
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 res = classLoader.getResource("jdbc.properties");//得到文件的绝对路径
            String path = res.getPath();//将绝对路径转化为字符串形式
            //FileReader用来读用户本地的文件
            pro.load(new FileReader(path));
            //2.加载文件
    //pro.load(new FileReader("src/jdbc.properties"));
            //3.获取数据,赋值
            url = pro.getProperty("url");
            user = pro.getProperty("user");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");
            //4.注册驱动
            Class.forName(driver);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    /**
     * 获取连接的方法
     */
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, user, password);
    }
    /**
     * 释放资源的方法
     */
    public static void close(ResultSet rs, Statement stmt, Connection conn) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}


使用工具类


package cn.caq.jdbc;
import cn.caq.domain.Emp;
import cn.caq.utils.JDBCutils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public class JdbcDemo07 {
    public static void main(String[] args) {
        List<Emp> list = new JdbcDemo07().findall2();
        System.out.println(list);
    }
    /**
     * 演示JDBC工具类
     */
    public List<Emp> findall2() {
        Connection conn = null;
        Statement stmt = null;
        ResultSet res = null;
        ArrayList<Emp> list = null;
        try {
//            //1.注册驱动
//            Class.forName("com.mysql.jdbc.Driver");
//            //2.获取连接对象
//            conn = DriverManager.getConnection("jdbc:mysql:///db2", "root", "root");
            conn = JDBCutils.getConnection();
            //3.定义sql
            String sql = "select * from emp";
            //4.获取执行sql对象
            stmt = conn.createStatement();
            //5.执行sql
            res = stmt.executeQuery(sql);
            //6.处理结果
            Emp emp = null;
            list = new ArrayList<>();
            while (res.next()) {
                int id = res.getInt("id");
                String ename = res.getString("ename");
                int job_id = res.getInt("job_id");
                //创建emp对象,并赋值
                emp = new Emp();
                emp.setId(id);
                emp.setEname(ename);
                emp.setJob_id(job_id);
                //装载集合
                list.add(emp);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            JDBCutils.close(res,stmt,conn);
        }
        return list;
    }
}


登陆练习


需求:


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


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


select * from user where username = “” and password = “”;


如果这个sql有查询结果,则成功反之失败


数据库


image.png


代码


package cn.caq.jdbc;
import cn.caq.utils.JDBCutils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
/**
 * 需求:
 * 1.通过键盘录入用户名和密码
 * 2.判断用户是否登录成功
 */
public class JDBCDemo08 {
    public static void main(String[]args){
        //1.键盘录入,接受用户名和密码
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入username:");
        String username = scanner.nextLine();
        System.out.println("请输入password");
        String password = scanner.nextLine();
        //2.调用方法
//        JDBCDemo08 jdbcDemo08 = new JDBCDemo08();
//        boolean login = jdbcDemo08.login(username, password);
        boolean flag = new JDBCDemo08().login(username, password);
        //3.判断结果,输出不同语句
        if (flag){
            System.out.println("Success!!!!!!");
        }else {
            System.out.println("username or passwd False!!!!!!!!");
        }
    }
    //登录方法
    public boolean login(String username,String password){
        if (username == null || password == null){
            return false;
        }
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        //1.连接数据库
        try {
            conn = JDBCutils.getConnection();
            //2.定义sql
            String sql = "select * from user where username = '"+username+"' and password = '"+password+"'";
            //3.获取执行sql的对象
            stmt = conn.createStatement();
            //4.执行sql语句
            rs = stmt.executeQuery(sql);
            //5.判断
            return rs.next();//有下一行返回true
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            JDBCutils.close(rs,stmt,conn);
        }
        return false;//如果出现异常返回false
    }
}
输出结果为:
请输入username:
zs
请输入password
123
Success!!!!!!
请输入username:
sadfa
请输入password
24323
username or passwd False!!!!!!!!


四、JDBC控制事务



1.事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。


2.操作:


1.开后事务


2.提交事务


3.回滚事务


3.使用connection对象来管理事务


开启事务: setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开后事务


在执行sql之前开启事务


提交事务: commit()


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


回滚事务: rollback()


在catch中回滚事务


转账实例


package cn.caq.jdbc;
import cn.caq.utils.JDBCutils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
 * 事务操作
 */
public class JDBCDemo10 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt1 = null;
        PreparedStatement pstmt2 = null;
        //1.获取连接
        try {
            conn = JDBCutils.getConnection();
            //开启事务
            conn.setAutoCommit(false);
            //2.定义sql
            //2.1张三 - 500
            String sql1 = "update account set balance = balance - ?  where id = ?";
            //2.1李四 + 500
            String sql2 = "update account set balance = balance + ?  where id = ?";
            //3.获取执行sql对象
            pstmt1 = conn.prepareStatement(sql1);
            pstmt2 = conn.prepareStatement(sql2);
            //4.设置参数
            pstmt1.setDouble(1, 500);
            pstmt1.setInt(2, 1);
            pstmt2.setDouble(1, 500);
            pstmt2.setInt(2, 2);
            //5.执行sql
            pstmt1.executeUpdate();
            //手动制造异常
            int i = 3 / 0;
            pstmt2.executeUpdate();
            //提交事务
            conn.commit();
        } catch (Exception throwables) {
            try {
                if (conn != null) {
                    conn.rollback();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            throwables.printStackTrace();
        }
    }
}


如果中途出现任何异常,则触发回滚操作!


   输出结果为:


java.lang.ArithmeticException: / by zero
  at cn.caq.jdbc.JDBCDemo10.main(JDBCDemo10.java:43)
金额没有发生变化


image.png


五、数据库连接池



概念


其实就是一个容器(集合),存放数据库连接的容器


当系统初始化好后,容器被初始化,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完后,会将连接对象返回给容器


好处


节约资源


高效


实现


标准的接口:DataSource javax.sql包下的


方法:


获取连接:getConnection()


归还连接:Connection.close().如果连接对象Connection是从连接池中获取的,那么调用Connection.close()不在是关闭连接,而是归还连接


2.这个接口,一般不由人为实现,而是有数据库厂商来实现


C3P0:数据库连接池技术


Druid:数据库连接池实现技术,由阿里提供


一、C3P0:数据库连接池技术


步骤:


1.导入jar包

c3p0-0.9.5.2.jar


mchange-commons-java-0.2.12.jar


还有驱动jar包


2.定义配置文件

名称:c3p0.properties或者c3p0-config.xml


路径:直接将文件放在src目录下即可


3.创建核心对象

数据库连接池对象 ComboPoolDataSource


4.获取连接

getConnection


了解即可


二、Druid:数据库连接池实现技术


1.写入jar包

druid-1.e.9.jar


2.定义配置文件

是properties形式的(properties 性能)

可以叫任意名称,可以放在任意目录下


3.获取数据库连接池对象:通过工厂类来获取

DruidDataSourceFactory


4.获取连接

getConnection


5.实例


package com.caq.datasource.druid;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
public class DruidDemo01 {
    public static void main(String[] args) throws Exception {
        //1.导入Jar包
        //2.定义配置文件
        //3.加载配置文件
        Properties pro = new Properties();
        InputStream is = DruidDemo01.class.getClassLoader().getResourceAsStream("druid.properties");//得到输出流
        pro.load(is);//获取文件的路径
        //4.获取连接池对象
        DataSource ds = DruidDataSourceFactory.createDataSource(pro);
        //5.获取连接
        Connection conn = ds.getConnection();
        System.out.println(conn);
    }
}
输出结果为:
十月 20, 2021 10:32:02 下午 com.alibaba.druid.pool.DruidAbstractDataSource error
严重: maxIdle is deprecated
十月 20, 2021 10:32:03 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited
com.mysql.jdbc.JDBC4Connection@6956de9


三、Druid工具类


1.定义一个类JDBCUtils


2.提供静态代码块加载配置文件,初始化连接池对象


3.提供方法


1.获取连接方法:通过数据库连接池获取


2.释放资源


3.获取连接池的方法


实例

详细的注释都写在代码中了!


package com.caq.datasource.utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
 * Druid连接池工具类
 */
public class JDBCUtils {
    //1.定义成员变量  DataSource
    private static DataSource ds;
    static {
        try {
            //1.加载配置文件
            Properties pro = new Properties();
            pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
            //2.获取DataSource
            ds = DruidDataSourceFactory.createDataSource(pro);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 获取连接
     */
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }
    /**
     * 释放资源
     */
    //第一种情况,执行DML语句,需要释放connection数据库连接对象和statementsql语句执行对象
    public static void close(Statement stmt, Connection conn) {
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close(); //归还连接,不在是释放了
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
    //第二种情况,执行DQL语句,释放三个资源,conn,stmt和resultSet结果集对象
    //这里写一个方法重载即可
    public static void close(ResultSet rs, Statement stmt, Connection conn) {
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close(); //归还连接,不在是释放了
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
    /**
     * 获取连接池的方法
     */
    public static DataSource getDataSource(){
        return ds;
    }
}
测试
package com.caq.datasource.druid;
import com.caq.datasource.utils.JDBCUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
 * 使用新的工具类
 */
public class DruidDemo02 {
    public static void main(String[] args) {
        /*
        完成添加的操作 给account表添加一条记录
         */
        Connection conn = null;
        PreparedStatement pstmt = null;
        try {
            //1.获取连接
            conn = JDBCUtils.getConnection();
            //2.定义sql
            String sql = "insert into account values(null,?,?)";
            //3.获取pstmt对象
            pstmt = conn.prepareStatement(sql);
            //4.给sql赋值
            pstmt.setString(1, "王五");//给第一个参数赋值为王五
            pstmt.setDouble(2, 3000);//给第二个参数赋值为3000
            //5.执行sql
            int count = pstmt.executeUpdate();
            System.out.println(count);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            //6.释放资源
            JDBCUtils.close(pstmt,conn);
        }
    }
}
输出结果为
十月 21, 2021 8:40:18 下午 com.alibaba.druid.pool.DruidAbstractDataSource error
严重: maxIdle is deprecated
十月 21, 2021 8:40:19 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited


查看数据库


image.png


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
3月前
|
Java 数据库连接
JDBC连接复习
JDBC连接复习
38 1
|
28天前
|
SQL Java 数据库连接
一文搞懂JDBC
一文搞懂JDBC
26 12
|
SQL Ubuntu Java
一文搞懂JDBC应该怎么用,附代码实例
说到Java的常见框架,JDBC一定是榜上有名。 虽然大多数人会使用Mybatis来做Java应用和MySQL之间的数据交互,但了解JDBC依然是一个Java工程师的基本功。 本篇文章,就来介绍一下JDBC这个框架,最后内会附上代码实例。
180 1
一文搞懂JDBC应该怎么用,附代码实例
|
存储 开发者
彻底搞懂函数,读这篇文章就够了
如果你之前使用过任何一门编程语言,那么对于你来讲想必已经知道什么是函数,以及如何使用函数了,那你大可不必往下读了。这篇文章是写给新手看的,也就是说我假设你对于函数没有任何的概念。 我们就先从什么是函数来说起吧!
115 0
|
SQL Java 关系型数据库
JDBC面试核心必考知识点
JDBC核心知识点 如有编辑错误联系作者 如果有比较好的文章欢迎分享给我,我会取其精华去其糟粕 王恒杰 男、95后 现居天津 是一名学习java的菜鸟 是万千程序猿中的一只 喜欢编程,喜欢探索新技术,大学生活迷茫过,失落过,还好没有放弃 希望看到这里的你也不要轻易地放弃 这条路上的你并不是孤军奋战,有千千万万的猿在陪你前行
148 0
JDBC面试核心必考知识点
|
编解码 NoSQL 安全
lettuce连接池很香,撸撸它的源代码(上)
lettuce连接池很香,撸撸它的源代码
976 0
lettuce连接池很香,撸撸它的源代码(上)
|
监控 Java uml
lettuce连接池很香,撸撸它的源代码(下)
lettuce连接池很香,撸撸它的源代码
431 0
lettuce连接池很香,撸撸它的源代码(下)
|
SQL Oracle Java
《JavaWeb篇》02.JDBC看这一篇就够了(一)
《JavaWeb篇》02.JDBC看这一篇就够了(一)
179 0
《JavaWeb篇》02.JDBC看这一篇就够了(一)
|
druid Java 数据库连接
《JavaWeb篇》02.JDBC看这一篇就够了(三)
《JavaWeb篇》02.JDBC看这一篇就够了(三)
157 0
《JavaWeb篇》02.JDBC看这一篇就够了(三)
|
SQL 存储 安全
《JavaWeb篇》02.JDBC看这一篇就够了(二)
《JavaWeb篇》02.JDBC看这一篇就够了(二)
142 0
《JavaWeb篇》02.JDBC看这一篇就够了(二)
下一篇
无影云桌面