目录
一、索引
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 索引是什么?
1.2 怎样创建索引?
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 = '四十大盗';
2.3 事务的使用
2.4 事务的特性
1.原子性(atomicity)
事务中的SQL要么都执⾏要么都不执⾏,通过commit/rollback控制。
2.⼀致性(Consistency)
官⽹上描述:数据库从⼀个⼀致性状态变换到另外⼀个⼀致性状态。
事务执⾏之前与执⾏之后,要保持的正确的结果,可以⽤转账说明
3.隔离性(Isolation)
多个事务执⾏的过程中不能互相⼲扰
4.持久性(Durability)
事务⼀旦提交就会写⼊磁盘永久保留,即使是数据库服务故障也不会影响数据的内容
多个事务之间是否可以相互影响?
四种情况的详解如下:
三、Java的数据库编程:JDBC
3.1 JDBC是什么?
- Java语言访问数据库操作完全面向抽象接口编程
- 开发数据库应用不用限定在特定数据库厂商的API
- 程序的可移植性大大增强
3.2 JDBC常用接口和类
1.JDBC API
2.数据库连接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对象
实际开发中最常用的是PreparedStatement对象,以下对其的总结:
4.ResultSet对象
- ResultSet对象它被称为结果集,它代表符合SQL语句条件的所有行,并且它通过一套getXXX方法提供了对这些行中数据的访问。
- ResultSet里的数据一行一行排列,每行有多个字段,并且有一个记录指针,指针所指的数据行叫做当前数据行,我们只能来操作当前的数据行。我们如果想要取得某一条记录,就要使用ResultSet的next()方法 ,如果我们想要得到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);
}
}
}
💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫💫