一文搞懂——MySQL索引事务JDBC

news2024/11/23 18:28:33

目录

一、索引

1.1 索引是什么?

1.2 怎样创建索引?

 1.3 索引使用的数据结构是什么?

1.4 索引相关的概念

1.5 索引失效的原因

二、事务

2.1 事务是什么?

2.2 为什么要使用事务?

2.3 事务的使用

2.4 事务的特性

 三、Java的数据库编程:JDBC

3.1 JDBC是什么?

3.2 JDBC常用接口和类

3.3 JDBC的使用


❤️ ( ⚫︎ー⚫︎ ) balalala~求一键三连~❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️
 /    \
   /    ○  \
/  /    ヽ \   |
| /      \ |
\Ԏ     Ԏ/
 卜−   ―イ
  \  /\  /
   ︶  ︶

一、索引

1.1 索引是什么?

索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引, 并指定索引的类型,各类索引有各自的数据结构实现。
简单来说,就是为了提高查询效率而使用一种数据结构把数据组织起来,比如实现生活中的字典,在查询某个字的时候就用到了索引。
试想,如果没有索引,要在字典中找一个字,时间复杂度是多少?
答案是 O(n)

1.2 怎样创建索引?

要考虑对数据库表的某列或某几列创建索引,需要考虑以下几点:
a.数据量较大,且经常对这些列进行条件查询。
b.该数据库表的插入操作,及对这些列的修改操作频率较低。
c.索引会占用额外的磁盘空间。
d.满足以上条件时,考虑对表中的这些字段创建索引,以提高查询效率。
反之,如果非条件查询列,或经常做插入、修改操作,或磁盘空间不足时,不考虑创建索引。
索引一般创建在频繁查询的列上,且这个列中的重复值较少。
对于非主键、非唯一约束、非外键的字段,可以创建普通索引
create index 索引名 on 表名(字段名);(字段名可以有多个,用逗号隔开)

 (表中的主键会自动创建索引)

手动创建索引

 

 一张表里至少会有一个索引,如果一张表里没有索引,MySQL会为每一行生成一个唯一的字段,并用这个字段当前做索引。

删除索引

drop index 索引名 on 表名 ;

 1.3 索引使用的数据结构是什么?

 1.HASH:查询的时间复杂度为O(1),但HASH并不支持范围查找,所以MySQL没有使用HASH作为索引的数据结构。

2.二叉搜索树:查询的时间复杂度为O(n),红黑树的时间复杂度log(n),MySQL依旧没有使用。

3.B树:虽然可以降低树高,但还是没有使用。

 4.B+树:对B树做了进一步优化,是索引最终使用的数据结构

 a.叶子节点是相互连接,MySQL中使用的B+树是一个双向循环链表

b.叶子节点中包含了树中所有节点的真实数据,非叶子节点中包含的是主键(id)和叶子节点的引用

c.在一定的的数据量范围内,不论查找的数据是什么,时间效率基本相同

d.最重要的是,叶子节点中的数据是有序的,所以支持范围查找

e.N叉搜索树,有效地降低了树的高度,从而减少了磁盘IO次数

1.4 索引相关的概念

  • 一个索引包含多个字段就叫组合索引;create index 索引名 on 表名(字段名1,字段名2);
  •   在查询时一定要在where条件中按索引顺序写过滤条件,使用索引的最左原则
  •   如果索引中包含要查询的所有列,那么直接从索引中返回结果,叫做索引覆盖
  •   当查询列表为*或索引不能满足查询结果,那么会使用id到主键索引中查询完整的结果,主键索引中包含当前数据行中所有列的值,叫做回表查询

1.5 索引失效的原因

  •   最左原则:类似于字典的⽬录,这就是⼀个典型的复合索引
  •   判断不等:每个都要判断
  •   类型转换:与原类型不符
  •   like '%xxx':第⼀个字符都不能确定,怎么去索引中⽐较呢?
  •   索引列运算 age + 1:改了原来的值
  •   is null 或 is not null : 全表扫描了

二、事务

2.1 事务是什么?

事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败。
在不同的环境中,都可以有事务。对应在数据库中,就是数据库事务。

简而言之,事务就是把一组SQL语句打包运行的机制,要么全都执行,要么全都不执行。

2.2 为什么要使用事务?

准备测试表:

drop table if exists accout;
create table accout(
 id int primary key auto_increment,
 name varchar(20) comment '账户名称',
 money decimal(11,2) comment '金额'
);
insert into accout(name, money) values
('阿里巴巴', 5000),
('四十大盗', 1000);
-- 比如说,四十大盗从阿里巴巴的账户上偷盗了2000元
-- 阿里巴巴账户减少2000
update accout set money=money-2000 where name = '阿里巴巴';
-- 四十大盗账户增加2000
update accout set money=money+2000 where name = '四十大盗';
假如在执行以上第一句 SQL 时,出现网络错误,或是数据库挂掉了,阿里巴巴的账户会减少 2000,但是四十大盗的账户上就没有了增加的金额。
解决方案:使用事务来控制,保证以上两句SQL要么全部执行成功,要么全部执行失败

2.3 事务的使用

(1)开启事务 start transaction;
(2 执行多条 SQL语句
(3 回滚或提交 rollback/commit;
     说明: rollback 即是全部失败, commit 即是全部成功。
    

 

2.4 事务的特性


  1.原子性(atomicity)

事务中的SQL要么都执⾏要么都不执⾏,通过commit/rollback控制。


  2.⼀致性(Consistency)

官⽹上描述:数据库从⼀个⼀致性状态变换到另外⼀个⼀致性状态。
事务执⾏之前与执⾏之后,要保持的正确的结果,可以⽤转账说明


  3.隔离性(Isolation)

多个事务执⾏的过程中不能互相⼲扰


  4.持久性(Durability)

事务⼀旦提交就会写⼊磁盘永久保留,即使是数据库服务故障也不会影响数据的内容

多个事务之间是否可以相互影响?

四种情况的详解如下:

 

 

 

 三、Java的数据库编程:JDBC

3.1 JDBC是什么?

JDBC ,即 Java Database Connectivity java 数据库连接。是一种用于执行 SQL 语句的 Java API ,它是 Java中的数据库连接规范。这个 API java.sql.*,javax.sql.* 包中的一些类和接口组成,它为 Java 开发人员操作数据库提供了一个标准的API ,可以为多种关系数据库提供统一访问。
JDBC 工作原理
JDBC 为多种关系数据库提供了统一访问方式,作为特定厂商数据库访问 API 的一种高级抽象,它主要包含一些通用的接口类。
在工作中,都是用程序来操作数据库的,所以需要程序和数据建立连接并完成操作。
JDBC访问数据库层次结构:
JDBC优势:
  • Java语言访问数据库操作完全面向抽象接口编程
  • 开发数据库应用不用限定在特定数据库厂商的API
  • 程序的可移植性大大增强

3.2 JDBC常用接口和类

1.JDBC API

Java JDBC 编程中对数据库的操作均使用 JDK 自带的 API 统一处理,通常与特定数据库的驱动类是完全解耦的。所以掌握Java JDBC API (位于 java.sql 包下)即可掌握 Java 数据库编程。

2.数据库连接Connection

Connection 接口实现类由数据库提供,获取 Connection 对象通常有两种方式:
  • 一种是通过DriverManager(驱动管理类)的静态方法获取:
  • // 加载JDBC驱动程序
    Class.forName("com.mysql.jdbc.Driver");
    // 创建数据库连接
    Connectionconnection=DriverManager.getConnection(url);
    • 一种是通过DataSource(数据源)对象获取。实际应用中会使用DataSource对象.
    • DataSourceds=newMysqlDataSource();
      ((MysqlDataSource) ds).setUrl("jdbc:mysql://localhost:3306/test");((MysqlDataSource) ds).setUser("root");
      ((MysqlDataSource) ds).setPassword("root");
      Connectionconnection=ds.getConnection();

      以上两种方式的区别是:

    • DriverManager 类来获取的 Connection连接,是无法重复利用的,每次使用完以后释放资源时,通过 connection.close() 都是关闭物理连接。
  • . DataSource提供连接池的支持。连接池在初始化时将创建一定数量的数据库连接,这些连接是可以复用的,每次使用完数据库连接,释放资源调用connection.close()都是将Conncetion连接对象回收。

 3.Statement对象

Statement 对象主要是将 SQL 语句发送到数据库中。 JDBC API 中主要提供了三种 Statement 对象。

 实际开发中最常用的是PreparedStatement对象,以下对其的总结:

 4.ResultSet对象

  • ResultSet对象它被称为结果集,它代表符合SQL语句条件的所有行,并且它通过一套getXXX方法提供了对这些行中数据的访问。
  • ResultSet里的数据一行一行排列,每行有多个字段,并且有一个记录指针,指针所指的数据行叫做当前数据行,我们只能来操作当前的数据行。我们如果想要取得某一条记录,就要使用ResultSetnext()方法 ,如果我们想要得到ResultSet里的所有记录,就应该使用while循环。

 3.3 JDBC的使用

对于MySQL的JDBC编程:

1.创建一个工程

2.引入mysql依赖

 

 

a.连接数据库

URL(版本5和8)

    //先定义一个数据源对象
    private static DataSource dataSource = null;
 
        //1.初始化数据源
        MysqlDataSource mysqlDataSource = new MysqlDataSource();
        //2.设置连接参数
        mysqlDataSource.setURL(URL);
        mysqlDataSource.setUser(USER);
        mysqlDataSource.setPassword(PASSWORD);
        //3.把构建好的Mysql数据源赋值给JDBC中的datasource
        dataSource = mysqlDataSource;
 
            //1.通过数据源获取一个数据库连接
            connection = dataSource.getConnection();

            //接收用户输入值
            System.out.println("请输入id:");
            Scanner scanner = new Scanner(System.in);
            int id = scanner.nextInt();
            //2.定义SQL语句
//            String sql = "select * from student where id = " + id;
            String sql = "select * from student where id = ?";
            System.out.println("sql-->" + sql);
            //3.获取statement对象
//            statement = connection.createStatement();
            //获取预处理对象
            statement = connection.prepareStatement(sql);
            //处理占位符的值
            statement.setInt(1,id);
            //4.执行SQL
            resultSet = statement.executeQuery();

b.执行sql语句(上方代码)

c.把查询到的结果集转化为Java对象

            //5.解析结果集,resultSet.next()表示结果集中是否有记录
            while (resultSet.next()) {
                //创建表示结果的JAVA对象
                Student student = new Student();
                //依次读取结果集中的数据斌赋值给JAVA对象
                student.setId(resultSet.getInt(1));
                student.setSn(resultSet.getInt(2));
                student.setName(resultSet.getString(3));
                student.setMail(resultSet.getString(4));
                //打印结果
                System.out.println(student);
            }

d.释放资源

            //依次关闭资源
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
            if (statement != null) {
                try {
                    statement.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }

创建的student实例

public class Student {
    private int id;
    private String sn;
    private String name;
    private String mail;
    private int classesId;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getSn() {
        return sn;
    }

    public void setSn(String sn) {
        this.sn = sn;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getMail() {
        return mail;
    }

    public void setMail(String mail) {
        this.mail = mail;
    }

    public int getClassesId() {
        return classesId;
    }

    public void setClassesId(int classesId) {
        this.classesId = classesId;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", sn='" + sn + '\'' +
                ", name='" + name + '\'' +
                ", mail='" + mail + '\'' +
                ", classesId=" + classesId +
                '}';
    }
}

利用封装进行优化,避免重复操作

   // 先定义一个数据源对象
    private static DataSource dataSource = null;
    // 数据库的用户名
    private static final String USER = "root";
    // 数据库的密码
    private static final String PASSWORD = "123456";
    // 数据库连接字符串
    private static final String URL = "jdbc:mysql://127.0.0.1:3306/java78?characterEncoding=utf-8&useSSL=false";
 
    static {
        // 初始化数据源
        MysqlDataSource mysqlDataSource = new MysqlDataSource();
        mysqlDataSource.setURL(URL);
        mysqlDataSource.setUser(USER);
        mysqlDataSource.setPassword(PASSWORD);
        dataSource = mysqlDataSource;
    }
 
    // 用private 修饰构造方法,使外部不能new 这个类的对象
    private DBUtil() {}
 
    /**
     * 获取数据库连接
     * @return
     * @throws SQLException
     */
    public static Connection getConnection () throws SQLException {
        return dataSource.getConnection();
    }
 
    /**
     * 关闭对象并释放资源
     * @param resultSet
     * @param statement
     * @param connection
     */
    public static void close (ResultSet resultSet, PreparedStatement statement, Connection connection) {
        // 依次关闭对象,并释放资源
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
 
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
 
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

调用封装查询student表中的全部信息

public class Demo02_SelectAll {
    public static void main(String[] args) {
        // 查询到的所有学生信息
        List<Student> students = null;
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            // 1. 创建数据源并获取数据库连接
            connection = DBUtil.getConnection();
            // 2. 构造SQL语句
            String sql = "select id, sn, name, mail, classes_id from student";
            // 使用SQL预处理对象处理SQL
            statement = connection.prepareStatement(sql);
            // 3. 执行SQL并获取结果,如果是结果集把结果集转成java对象
            resultSet = statement.executeQuery();
            // 遍历结果集,处理查询到数据
            while (resultSet.next()) {
                // 如果List为空则创建
                if (students == null) {
                    students = new ArrayList<>();
                }
                // 解析结果集并封装成Student对象
                Student student = new Student();
                student.setId(resultSet.getInt(1));
                student.setSn(resultSet.getString(2));
                student.setName(resultSet.getString("name"));
                student.setMail(resultSet.getString("mail"));
                student.setClassesId(resultSet.getInt("classes_id"));
                // 加入到集合中
                students.add(student);
            }
            // 打印结果
            System.out.println(students);

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 4. 释放资源
            DBUtil.close(resultSet, statement, connection);
        }
    }
}

💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫

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

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

相关文章

黑马头条(学习笔记)

​ 目录 一. 项目概述 二、项目初始化 移动端 REM 适配&#xff1a; 关于 PostCSS 配置文件&#xff1a; Autoprefixer 插件的配置 &#xff1a; postcss-pxtorem 插件的配置&#xff1a; 关于字体图标: 配置路由&#xff1a; 封装请求模块: 三&#xff1a;登录注册&…

ChatGPT有话说:虚拟现实 VS 增强现实

以下内容均为ChatGPT根据用户引导和提示作出的阐述和说明。 一、引言 虚拟现实和增强现实是当前最受瞩目的创新技术。虚拟现实是指利用计算机生成的虚拟环境&#xff0c;用户可以通过佩戴VR头戴式显示器等设备完全沉浸在其中&#xff0c;感受到身临其境的感觉。而增强现实则是…

三分钟上手安全渗透系统Kali Linux

kali linux系统集成了常用的安全渗透工具&#xff0c;省去了安装工具的时间&#xff0c;做安全相关的工作是非常推荐使用的。 安装Kalii Linux 安装系统 一般使用虚拟机进行安装&#xff0c;Kali Linux基于Debian内核&#xff0c;虚拟机的操作系统选择Debian 7.x 64 选择系统…

【JAVA】用Java实现简易图书管理系统

【JAVA】用Java实现简易图书管理系统 1. 设计背景和系统功能和设计方法1.1设计背景1.2系统功能1.3设计方法 2. 设计思路3. 设计模块和代码实现3.1 Book类的实现3.2 BookList类的实现(书架)3.3 User类的实现&#xff08;用户类&#xff09;3.3.1 AdminUser&#xff08;管理员类&…

家用洗地机好用吗?值得推荐的家用洗地机

谁说家务苦差事&#xff1f;现在有了洗地机&#xff0c;家庭清洁变得更加简单、快捷、干净&#xff0c;让您轻松应对家庭日常清洁的要求。洗地机采用先进的技术&#xff0c;自动感应地面脏污&#xff0c;智能调节出水量和吸力&#xff0c;不仅能够保持地面清洁&#xff0c;更能…

深入理解MapReduce:使用Java编写MapReduce程序【上进小菜猪】

&#x1f4ec;&#x1f4ec;我是上进小菜猪&#xff0c;沈工大软件工程专业&#xff0c;爱好敲代码&#xff0c;持续输出干货。 MapReduce是一种用于处理大规模数据集的并行编程模型。由于其高效性和可扩展性&#xff0c;MapReduce已成为许多大型互联网公司处理大数据的首选方…

隐语v0.8.2版本更新,首次发布TEEU

隐语v0.8.2版本更新&#x1f31f; 应用层 机器学习&#xff1a; - MPC 纵向 LR &#xff08;SSRegression&#xff09;新增 Policy SGD 优化器和 Early Stopping 支持&#xff0c;减少调参成本&#xff0c;加快收敛速度&#xff1b; - WOE 分箱进行了若干优化&#xff0c;性…

HR SaaS市场竞争火热,肯耐珂萨缘何持续领跑? |爱分析调研

摘要&#xff1a; 中国人力资源数字化市场规模快速增长&#xff0c;各路厂商云集&#xff0c;呈现百花齐放的态势。作为人力资源管理一体化云解决方案的龙头服务商&#xff0c;肯耐珂萨坚定执行价值导向的差异化竞争策略&#xff0c;15年引领行业创新&#xff0c;依托行业领先方…

linux下的Qt打包常见原因分析和雷区,获取一键式打包脚本(能避免各种问题)

目录 一. 大致如下常见问题&#xff1a; &#xff08;1&#xff09;找不到程序所依赖的Qt库 version Qt_5 not found (required by &#xff08;2&#xff09;Could not Load the Qt platform plugin "xcb" in "" even though it was found &#xff0…

64/32位Linux系统的地址空间布局对比分析

Ubuntu从17.10开始不再官方支持32位(i386)架构&#xff08;严格的说是从18.04开始的&#xff0c;因为17.10不支持32位的PC版&#xff0c;但是支持32位的SERVER版&#xff0c;但是偶数稳定版确实是从18.04开始的)&#xff0c;只支持64位(amd64)架构&#xff0c;这是因为随着时间…

为什么ChatGPT用强化学习而非监督学习?

为什么ChatGPT非得用强化学习&#xff0c;而不直接用监督学习&#xff1f;原因不是那么显而易见。在上周发布的《John Schulman&#xff1a;通往TruthGPT之路》一文中&#xff0c;OpenAI联合创始人、ChatGPT主要负责人John Schulman分享了OpenAI在人类反馈的强化学习&#xff0…

去阿里面试,面试前20分钟突然要求候选人展示过去的工作方案,候选人拒绝后,竟被取消面试!...

离职时&#xff0c;你会把自己的工作成果拷贝下来留档吗&#xff1f; 一位网友说&#xff1a; 面试阿里&#xff0c;面试前20分钟&#xff0c;面试官突然要求他展示过去的工作成果&#xff0c;因为之前是用公司电脑&#xff0c;离职时把电脑交上去了&#xff0c;没有任何留档&a…

AE(自动编码器)与VAE(变分自动编码器)的区别和联系?

他们各自的概念看以下链接就可以了&#xff1a;https://blog.csdn.net/weixin_43135178/category_11543123.html 这里主要谈一下他们的区别&#xff1f; 先说结论&#xff1a; VAE是AE的升级版&#xff0c;VAE也可以被看作是一种特殊的AEAE主要用于数据的压缩与还原&#xff0…

redisson中的分布式锁解读

概述 Redisson是一个在Redis的基础上实现的Java驻内存数据网格&#xff08;In-Memory Data Grid&#xff09;。它不仅 提供了一系列的分布式的Java常用对象&#xff0c;还提供了许多分布式服务。其中包括(BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue,…

【电机应用控制】——FOC基础理论针对无刷电机360°无死角磁场矢量控制

目录 前言 一、FOC简介 1、概述 2、框图详解 二、FOC控制核心—坐标变换 1、CLARKE变换 2、PARK变换&反变换 三、FOC闭环回路 四、SVPWM解析 总结 前言 声明&#xff1a;学习笔记来自正点原子B站教程&#xff0c;根据自己理解进行精简总结&#xff0c;仅供学习…

『python爬虫』16. 多线程与多进程(保姆级图文)

目录 多线程1. 什么是多线程&#xff1f;2. 串行模式3. 多线程3.1 多线程方法写法3.2 多线程方法带参数3.3 多线程类写法 多进程1. 什么是多进程 欢迎关注 『python爬虫』 专栏&#xff0c;持续更新中 欢迎关注 『python爬虫』 专栏&#xff0c;持续更新中 多线程 1. 什么是多…

优化Docker Compose日志输出,加速容器化应用的轻松部署

摘要&#xff1a; 在使用 Docker Compose 部署容器化应用程序时&#xff0c;优化日志输出对于提升效率和管理便利性至关重要。本文将介绍如何优化 Docker Compose 日志输出&#xff0c;以加速容器化应用的轻松部署过程。 优化操作 当我们使用 Docker Compose 部署容器化应用程…

【Queue新技法】用双数组实现一个队列 C++

目录 1 常规的队列构建2 加入一些限制2-1形式化说明 附录0 双数组或双链表实现队列1 单链表与循环缓冲区实现队列3 参考资料 1 常规的队列构建 到火车站办理退票&#xff0c;排队的人构成队列。注意到有两个关键动作&#xff1a; 入队&#xff0c;即自觉站到队伍的末尾。出队&…

一篇文章搞定《ViewPage2离屏加载》

------《ViewPage2离屏加载》 前言离屏加载是什么OffscreenPageLimit设置OffscreenPageLimit表现OffscreenPageLimit值为1OffscreenPageLimit值为3 OffscreenPageLimit值取多大比较合适 前言 这里就不讲ViewPage了&#xff0c;买新不买旧&#xff0c;用新不用旧。 但是会将Vie…

Power BI: 表格显示切片器选中时间之前的数据

例如下面的例子&#xff0c;Year List表和Caleadar表是1对多的关联关系。 Caleadar表&#xff1a; Caleadar VAR StartYear YEAR(NOW())-5 VAR EndYear YEAR(NOW())5 RETURN ADDCOLUMNS (CALENDAR (DATE(StartYear,1,1), DATE(EndYear,12,31)),"Year", YEAR ([…