java-JDBC

news2024/11/28 7:38:53

java-JDBC

在这里插入图片描述

1. JDBC概念

JDBC 就是使用Java语言操作关系型数据库的一套API
全称:( Java DataBase Connectivity ) Java 数据库连接

在这里插入图片描述

sun公司就指定了一套标准接口(JDBC),JDBC中定义了所有操作关系型数据库的规则。
我们需要使用接口的实现类,而这套实现类(称之为:驱动)就由各自的数据库厂商给出。

2. JDBC流程

先来看看通过Java操作数据库的流程

在这里插入图片描述

  • 第一步:编写Java代码
  • 第二步:Java代码将SQL发送到MySQL服务端
  • 第三步:MySQL服务端接收到SQL语句并执行该SQL语句
  • 第四步:将SQL语句执行的结果返回给Java代码

2.1 编码步骤

		// 1. 注册驱动
        Class.forName("com.mysql.jdbc.Driver");

        // 2.获取链接
        String url = "jdbc:mysql://127.0.0.1:3306/db1";
        String username = "root";
        String pwd = "123456";
        Connection conn = DriverManager.getConnection(url, username, pwd);

        // 3.定义sql
        String sql = "UPDATE account SET money = 2000 where id = 1";

        // 4.获取执行sql的对象 statement
        Statement stmt = conn.createStatement();

        // 5.执行sql
        int count = stmt.executeUpdate(sql);

        // 6.处理结果
        System.out.println(count);

        // 7.释放资源
        stmt.close();
        conn.close();

上述代码中

  • 注册驱动 可以省略

    MySQL 5之后的驱动包,可以省略注册驱动的步骤

    Class.forName("com.mysql.jdbc.Driver");
    
  • url : 连接路径

    语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2…
    示例:jdbc:mysql://127.0.0.1:3306/db1

    注意:

    • 如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称?参数键值对
    • 配置 useSSL=false 参数,禁用安全连接方式,解决警告提示

3. JDBC API

3.1 DriverManager

DriverManager(驱动管理类)作用:

  • 注册驱动
    registerDriver静态方法是用于注册驱动
    上述代码虽然通过反射来注册驱动,但是源码中依然是使用 DriverManager.registerDriver(new Driver()) 来实现
    public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    	public Driver() throws SQLException {
    	}
    
    	static {
        	try {
            	DriverManager.registerDriver(new Driver());
        	} catch (SQLException var1) {
            	throw new RuntimeException("Can't register driver!");
        	}
    	}
    }
    
    我们只需要加载 Driver 类,该静态代码块就会执行。
    Class.forName("com.mysql.jdbc.Driver"); 就可以加载 Driver 类。

3.2 Connection

Connection(数据库连接对象)作用:

  • 获取执行 SQL 的对象

    • 普通执行SQL对象 createStatement

      Statement createStatement()
      
    • 预编译SQL的执行SQL对象:防止SQL注入prepareStatement

      PreparedStatement  prepareStatement(sql)
      

      通过这种方式获取的 PreparedStatement SQL语句执行对象,它可以防止SQL注入。

    • 执行存储过程的对象 prepareCall

      CallableStatement prepareCall(sql)
      

      通过这种方式获取的 CallableStatement 执行对象是用来执行存储过程的,而存储过程在MySQL中不常用

  • 管理事务
    MySQL事务管理的操作

    MySQL默认是自动提交事务

    • 开启事务 : BEGIN; 或者 START TRANSACTION;
    • 提交事务 : COMMIT;
    • 回滚事务 : ROLLBACK;

    Connection 接口中定义了3个对应的方法:

    • 开启事务 :setAutoCommit(boolean autoCommit)
      // 开启事务
      conn.setAutoCommit(false);
      
      参与autoCommit 表示是否自动提交事务,true表示自动提交事务,false表示手动提交事务。而开启事务需要将该参数设为为false。
    • 提交事务 : commit();
      // 提交事务
      conn.commit();
      
    • 回滚事务 : rollback();
      // 回滚事务
      conn.rollback();
      
  • 案例代码
    	String url = "jdbc:mysql:///db1?useSSL=false";
        String username = "root";
        String pwd = "123123";
    
        Connection conn = DriverManager.getConnection(url, username, pwd);
    
        String sql1 = "UPDATE account SET money = 3000 where id = 1";
        String sql2 = "UPDATE account SET money = 3000 where id = 2";
    
        Statement stmt = conn.createStatement();
    
        try {
            // 开启事务
            conn.setAutoCommit(false);
    
            int count1 = stmt.executeUpdate(sql1);
            System.out.println(count1);
    
            int count2 = stmt.executeUpdate(sql2);
            System.out.println(count2);
    
            // 提交事务
            conn.commit();
    
        } catch (Exception throwables) {
            // 回滚事务
            conn.rollback();
            throwables.printStackTrace();
        }
    
        stmt.close();
        conn.close();
    

3.3 Statement

Statement对象的作用就是用来执行SQL语句。而针对不同类型的SQL语句使用的方法也不一样。

  • 执行DDL、DML语句
    int executeUpdate(String sql)
    可能是 INSERT INTOUPDATEDELETE语句

  • 执行DQL语句
    ResultSet executeQuery(String sql)
    执行指定的sql语句,返回单个 ResultSet 对象

  • 案例代码

    • 执行DML语句

      //3. 定义sql
      String sql = "update account set money = 3000 where id = 1";
      //4. 获取执行sql的对象 Statement
      Statement stmt = conn.createStatement();
      //5. 执行sql
      int count = stmt.executeUpdate(sql);//执行完DML语句,受影响的行数
      //6. 处理结果
      //System.out.println(count);
      if(count > 0){
      	System.out.println("修改成功~");
      }else{
      	System.out.println("修改失败~");
      }
      
    • 执行DDL语句

      //3. 定义sql
      String sql = "drop database db2";
      //4. 获取执行sql的对象 Statement
      Statement stmt = conn.createStatement();
      //5. 执行sql
      int count = stmt.executeUpdate(sql);//执行完DDL语句,可能是0
      //6. 处理结果
      System.out.println(count);
      

注意:

  • 以后开发很少使用java代码操作DDL语句

3.4 PreparedStatement

PreparedStatement对象的作用是用来执行SQL语句。

3.4.1 优点

  • 预编译SQL
    开启预编译功能 性能更高:
  • 预防SQL注入
    原理:将敏感字符进行转义

3.4.2 SQL注入

SQL注入是通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法。

3.4.3 获取 PreparedStatement 对象

// SQL语句中的参数值,使用?占位符替代
String sql = "select * from user where username = ? and password = ?";
// 通过Connection对象获取,并传入对应的sql语句
PreparedStatement pstmt = conn.prepareStatement(sql);

3.4.4 设置参数值

上面的sql语句中参数使用 ? 进行占位,在使用之前肯定要设置这些 ? 的值。

PreparedStatement对象:setXxx(参数1,参数2):给 ? 赋值

  • Xxx:数据类型 ; 如 setInt (参数1,参数2)
  • 参数:
    • 参数1: ?的位置编号,从1 开始
    • 参数2: ?的值
String name = "...";
String pwd = "...";
pstmt.setString(1, name);
pstmt.setString(2, pwd);

3.4.5 执行SQL语句

executeUpdate(); 执行DDL语句和DML语句

executeQuery(); 执行DQL语句

注意:

  • 调用这两个方法时不需要传递SQL语句,因为获取SQL语句执行对象时已经对SQL语句进行预编译了。
ResultSet rs = pstmt.executeQuery();

3.4.6 PreparedStatement原理

在这里插入图片描述
Java代码操作数据库流程:

  • 将sql语句发送到MySQL服务器端

  • MySQL服务端会对sql语句进行如下操作

    • 检查SQL语句

      检查SQL语句的语法是否正确。

    • 编译SQL语句。将SQL语句编译成可执行的函数。

      检查SQL编译SQL花费的时间比执行SQL的时间还要长。

    • 执行SQL语句

提高性能的原理
开启预编译功能后,检查SQL语句和编译SQL语句对于相同的 sql模板 只执行一次,不需要重复执行。这样就提高了性能。

开启预编译功能

useServerPrepStmts=true
String url = "jdbc:mysql:///db1?useServerPrepStmts=true";

3.4.7 案例代码

		String url = "jdbc:mysql:///db1?useServerPrepStmts=true";
        String username = "root";
        String password = "123123";
        Connection conn = DriverManager.getConnection(url, username, password);


        String name = "zhangsan";
//        String pwd = "' or '1' = '1";
        String pwd = "123";
        String sql = "select * from tb_user where username = ? and password = ?";

        PreparedStatement pstmt = conn.prepareStatement(sql);

        pstmt.setString(1,name);
        pstmt.setString(2,pwd);

        ResultSet rs = pstmt.executeQuery();

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

        rs.close();
        pstmt.close();
        conn.close();

小结:

  • 在获取PreparedStatement对象时,将sql语句发送给mysql服务器进行检查,编译(这些步骤很耗时)
  • 执行时就不用再进行这些步骤了,速度更快
  • 开启预编译功能后。如果sql模板一样,则只需要进行一次检查、编译

3.5 ResultSet - 结果集对象

  • 封装了SQL查询语句的结果。
    而执行了DQL语句后就会返回该对象:
    ResultSet  executeQuery(sql):执行DQL 语句,返回 ResultSet 对象
    
  • ResultSet 对象中获取数据。ResultSet 对象提供了操作查询结果数据的方法,

    • boolean next()
    • 将光标从当前位置向前移动一行
    • 判断当前行是否为有效行

    方法返回值:

    • true : 有效行,当前行有数据
    • false : 无效行,当前行没有数据
    • xxx getXxx(参数):获取数据
    • xxx : 数据类型;如: int getInt(参数) ;String getString(参数)
    • 参数
      • int类型的参数:列的编号,从1开始
      • String类型的参数: 列的名称
  • 案例代码

    String sql = "select * from account";
    Statement stmt = conn.createStatement();
    ResultSet rs = stmt.executeQuery(sql);
    while (rs.next()){
        int id = rs.getInt(1);
        String name = rs.getString(2);
        double money = rs.getDouble(3);
    	System.out.println(id + "--" + name + "--" + money);
    	System.out.println("--------------");
    
    }
    while (rs.next()){
        int id = rs.getInt("id");
        String name = rs.getString("name");
        double money = rs.getDouble("money");
    	System.out.println(id + "--" + name + "--" + money);
        System.out.println("--------------");
    }
    

4. 数据库连接池

4.1数据库连接池概述

  • 数据库连接池是个容器,负责分配、管理数据库连接(Connection)

  • 它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;

  • 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏

  • 好处

    • 资源重用
    • 提升系统响应速度
    • 避免数据库连接遗漏

数据库使用了数据库连接池后,就能达到Connection对象的复用
在这里插入图片描述

连接池是在一开始就创建好了一些连接(Connection)对象存储起来。用户需要连接数据库时,不需要自己创建连接,而只需要从连接池中获取一个连接进行使用,使用完毕后再将连接对象归还给连接池;这样就可以起到资源重用,也节省了频繁创建连接销毁连接所花费的时间,从而提升了系统响应的速度。

4.2 数据库连接池实现

  • 标准接口:DataSource

    官方(SUN) 提供的数据库连接池标准接口,由第三方组织实现此接口。该接口提供了获取连接的功能:

    Connection getConnection()
    

    那么以后就不需要通过 DriverManager 对象获取 Connection 对象,而是通过连接池(DataSource)获取 Connection 对象。

  • 常见的数据库连接池

    • DBCP
    • C3P0
    • Druid

    使用更多的是Druid,它的性能比其他两个会好一些。

  • Druid(德鲁伊)

    • Druid连接池是阿里巴巴开源的数据库连接池项目

    • 功能强大,性能优秀,是Java语言最好的数据库连接池之一

4.3 Driud使用

  • 导入jar包

  • 定义配置文件

    driverClassName=com.mysql.jdbc.Driver
    url=jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true
    username=root
    password=123456
    # 初始化连接数量
    initialSize=5
    # 最大连接数
    maxActive=10
    # 最大等待时间
    maxWait=3000
    
  • 加载配置文件

    Properties prop = new Properties();
    prop.load(new FileInputStream("java_code/src/druid.properties"));
    
  • 获取数据库连接池对象

    DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
    
  • 获取连接

    Connection conn = dataSource.getConnection();
    

案例代码

public static void main(String[] args) throws Exception {
        // 1. 导入jar包
        // 2. 定义配置文件
        // 3. 加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream("java_code/src/druid.properties"));
        
        // 4. 获取连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);

        // 5. 获取数据库链接 Connection
        Connection conn = dataSource.getConnection();
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/620507.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人群聚集监测预警算法 python

人群聚集监测预警系统采用pythonopencv网络模型AI视频智能分析技术,人群聚集监测预警算法对人员聚集情况进行实时监测,当人群聚集过于密集时,系统将自动发出警报。OpenCV基于C实现,同时提供python, Ruby, Matlab等语言的接口。Ope…

R语言 tidyverse系列学习笔记(系列1)

tidyverse 译 “洁净的宇宙” > “极乐净土” 以 iris 鸢尾花数据集为例 ** 查看数据集** ** 查看维度dimention** dim(iris)iris 数据集有150个对象(observation),5列 ( Sepal.Length , Sepal.Width , Petal.Length , Petal.Width , S…

阿里服务器配置服务器自启动

一开始 是在 /etc/rc.local 文件中添加的如下脚本 bash /mnt/cangjie-server/action.sh start bash /usr/local/nginx/sbin/nginx pm2 start npm--name"cangjieWeb"run start 启动服务器,服务并没有执行。 后面把执行脚本的 bash 指令去掉 如下&#xf…

Linux内核中断和Linux内核定时器

目录 Linux内核中断 Linux内核定时器 Linux内核中断 int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev) 功能:注册中断 参数: irq : 软中断号 gpio的软中断号 软中断号 gpio_to_i…

期末复习样卷

期末复习样卷 目录 期末复习样卷选择题简答题1. 画E-R图并将其转换为适当的关系模型2. 规范化模式分解——教学关系(学号,姓名,年龄,性别,系别,系主任,课程名,成绩)3.关系…

重装Windows系统

1.前言 有的时候,面对杂乱的文件系统,整理是十分困难的…… 有的时候,下载软件的时候会附带上某一些病毒、木马…… 有的时候,不满于更新后的系统…… 这些种种都可以使用重装系统解决,接下来我来带您学习重装windows…

煤炭价格学习

大佬发表时间在2022.11.17 神华月线,因为没有送配股,所以肯定是除权看的(前复权看的不要跟我谈技术,因为你不配) 除权,前复权,后复权 理解这三者区别之前,首先我们要简单了解 除权和…

【String字符串之后续】

我们继续上一篇文章为大家讲解,String字符串的相关知识,希望大家有所收获💞💞💞 字符串前篇的链接: link 目录 1.字符串的替换2.字符串的拆分3.字符串截取4.去掉空格5.String的不可变性6. 字符串的修改7.StringBuilde…

STL:string类使用

编码: ASCII unicode–utf-8 utf-16----一个字符2个字符 utf-32----一个字符4个字节 gbk–中文编码表 string: 是一个特殊的容器,对数据(字符数组)和库函数(strlen等)进行封装 STL提供的内容…

OpenStack部署(三)

OpenStack部署 6. Neutron6.1 创建Neutron数据库并授权6.2 获得admin凭证6.3 创建 neutron 用户并设置密码6.4 添加admin角色到neutron 用户6.5 创建neutron服务实体6.6 创建网络服务API端点6.7 安装并配置neutron服务6.8 链接plugin.ini文件6.9 初始化neutron数据库6.10 重启计…

连续两年!PingCAP 入选 Gartner 云数据库“客户之声”,获评“卓越表现者”最高分

近日,全球权威信息技术研究与咨询机构 Gartner 发布了云数据库市场领域 2023 Gartner Peer Insights™“Voice of the Customer” 报告,PingCAP 在报告中获得的客户总体评分达到 4.9 分(满分 5 分),在所有入选企业中位…

CBCGPCaptionBar 使用实例说明

CBCGPCaptionBar的位置如下: 如图区域就是 MainFrame.h中声明: CBCGPCaptionBar m_wndCaptionBar; MainFrame.cpp中创建显示控件: BOOL CMainFrame::CreateCaptionBar () { if (!m_wndCaptionBar.Create (WS_CHILD | WS_V…

力扣第三天 242.有效字母异位词 349 两个数组的交集

目录 1.242. 有效的字母异位词 2.349. 两个数组的交集 - 力扣(LeetCode)​​​​​​ 使用算法笔记: 总结: 1.242. 有效的字母异位词 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 注意…

15. 算法之排序算法

前言 排序是在软件开发中经常遇到的需求。比如基于订单的创建时间倒排,基于金额大小排序等等,那么这些排序底层是怎么写的呢,本节,我们就常用排序算法展开介绍。 1. 冒泡排序 1.1 算法思想 冒泡排序是最基础的排序算法。冒泡排…

HashMap 的底层原理和源码分析

tip:作为程序员一定学习编程之道,一定要对代码的编写有追求,不能实现就完事了。我们应该让自己写的代码更加优雅,即使这会费时费力。 推荐:体系化学习Java(Java面试专题) 文章目录 一、HashMap…

【迷宫】地下迷宫游戏-微信小程序开发流程详解

可曾记得,小时候上学路边买的透明铅笔盒,里面内嵌了一个小球,它用重力可从起点滚动到终点,对小朋友来说是感觉有趣的,在这个游戏的基础上,弄一款微信小程序的迷宫探索游戏试试,在不同关卡的迷宫…

14 【Vuex】

1.理解 Vuex 1.1 Vuex 是什么 概念:专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对Vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用…

基于RK3399+FPGA的地面测试台多参数数据记录仪方案(一)软件设计及测试

完成了测试台软件分析和编程环境搭建后,接下来就是软件的编写。本章主要包括 软件窗口界面设计和功能代码实现。以某型号数据记录仪的工作需求为目标,根据测试 工作流程,以 Linux-Qt 为主要开发手段,设计一款功能完备、界面友…

Java8 Stream详解及结束操作方法使用示例(三)

结束操作是指结束 Stream 该如何处理的操作,并且会触发 Stream 的执行。下面是一些常用的结束操作方法。结束操作会对数据源进行遍历,因此是及早求值的。 Java8 Stream详解及中间操作方法使用示例(一) ​​​​​​​Java8 Strea…

三种经典博弈(取石子问题)

三种经典博弈 巴什博奕威佐夫博奕尼姆博奕 博弈是有一种很有意思的游戏,就是有物体若干堆,可以是火柴棍或是围棋子等等均可。两个人轮流从堆中取物体若干,规定最后取光物体者取胜。这是我国民间很古老的一个游戏,别看这游戏极其简…