MySQL42

数据库存储引擎:定义如何存储数据、如何为存储的数据建立索引、如何更新、查询数据等技术的具体实现。

MySQL 提供了很多种存储引擎,可以直接查询

MySQL 默认的存储引擎是 InnoDB,支持事务,是其它引擎所不能比拟的

InnoDB 支持事务,支持主键自增,支持外键

XA:表示是否支持分布式事务

SQL:是一种编程语言,专门用来操作数据库的,实现对数据库的增删改查都是通过执行对应 SQL 语句来完成的。

MySQL常用知识点

  • 算术运算符:在查询的过程中对结果的值进行加减乘除、比较、逻辑运算等功能

  • 特殊运算符

    • 判断数据是否为空
    • 判断值是否在某个区间之内
    • 判断值是否在某个特定值的集合内
    • 模糊查询
      • % 可以替换为任意字符
      • _ 表示一位长度
  • 日期函数

    • 获取当前日期

      select curdate();
      
    • 获取当前时间

      select curtime();
      
    • 获取当前日期+时间

      select now();
      
    • 获取两个日期相隔的天数

      select datediff('2022-6-23','2019-05-01');
      
    • 查询某个日期之后多少天的日期是多少

      select adddate('2022-08-22',100);
      
    • 查询某个日期之前多少天的日期是多少

      select subdate('2022-08-22',100);
      
  • 聚合函数

    • 统计记录数

      select count(id) from student;
      
    • 计算字段值之和

      select sum(age) from student;
      
    • 求字段的平均值

      select avg(age) from student;
      
    • 求字段的最大值

      select max(age) from student;
      
    • 求字段的最小值

      select min(age) from student;
      

MySQL 的数据类型

整数类型:tinyint、smallint、mediumint、int、bigint

浮点型:float、double、decimal

日期类型:datetime、date、timestamp、time、year

字符串类型:char、varchar、text

二进制类型:bit、binary、varbinary、tinyblob、blob、mediumblob、longblob

数据库是通过主键去唯一标识某条数据的

外键是建立两张表之间的联系的,进行数据之间的约束

数据表之间的关系

  • 一对一:A 表中的一条记录唯一对应 B 表中的一条记录,B 表中的一条记录唯一对应 A 表中的一条记录。比如人和身份证
  • 一对多:A 表中的一条记录对应 B 表中的一条记录,B 表中的一条记录对应 A 表中的多条记录。比如学生和班级
  • 多对多:A 表中的一条记录对应 B 表中的多条记录,B 表中的一条记录对应 A 表中的多条记录。比如学生和选课

MySQL43

多表关联查询

  • 嵌套查询

  • 连接查询

    • 内连接(默认是笛卡尔积的结果)

    • 外连接

      • 左连接:左表所有数据和右表满足条件的数据组成的结果

      • 右连接:右表所有数据和左表满足条件的数据组成的结果

多对多查询,需要通过中间表将两张业务表进行关联

索引是一种特殊的数据库结构,可以用来快速查询数据表中的特定记录,索引是提升数据库性能的重要方式,主要是提高查询的速度。

索引:

  • 普通索引:不需要任何限制条件的索引,可以在任意数据类型上创建
  • 唯一索引:索引的值必须唯一,比如主键索引
  • 全文索引:只能创建在 text、char、varchar 数据类型上,针对文本类型数据的索引
  • 单列索引:只对应一个字段的索引
  • 多列索引:在一张表的多个字段上添加索引,由多个字段共同构成索引结构
  • 空间索引:只能建立在空间数据类型(经纬度),InnoDB 不支持空间索引

索引的设计原则:

  • 出现在 where 语句中的列可以加索引,select 后面的列不需要加索引
  • 索引的值,尽量唯一,效率更高
  • 不要添加过多的索引,维护成本很高

1、添加索引

create index in_name on student(name);

2、删除索引

drop index in_name on student;

事务的特性:

  • 原子性:多条 SQL 是一个整体,不可再分割
  • 一致性:SQL 执行前后,数据库的数据值保持一致
  • 隔离性:一个事务的执行不能被其他事务所干扰
  • 持久性:一个事务一旦提交,数据库中数据的改变是永久性的

视图:数据库中一张虚拟的表,允许不同用户或应用程序以不同的方式查看同一张表中的数据

创建视图

create view view_common as select id,name from user;
create view view_all as select * from user;

使用视图

select * from view_common;
select * from view_all;

删除视图

drop view view_common;
drop view view_all;

触发器:提前定义好一系列的操作,可以在对指定表进行插入、更新、删除的同时自动执行这些操作

use db01;create table tab1(tab1_id varchar(11)
);
create table tab2(tab2_id varchar(11)
);# 创建触发器
create trigger t_afterinsert_on_tab1after insert on tab1 # 给tab1表添加后去执行触发器for each row # 针对每一行都有效begin insert into tab2(tab2_id) values(new.tab1_id); # 这里是要执行的操作end;# 创建触发器
create trigger t_afterdelete_on_tab1after delete on tab1for each rowbegindelete from tab2 where tab2_id = old.tab1_id;end;# 删除触发器
drop trigger t_afterdelete_on_tab1;
drop trigger t_afterinsert_on_tab1;

存储过程:存储过程是提前定义好了一组 SQL 语句的集合,存储在数据库中,用户可以直接调用这些存储过程,类似于 Java 的方法调用。

use db01;
# 创建一个存储过程
create procedure add_name(in target int) # in表示传入的参数,target是参数名,int是参数类型
begindeclare name varchar(20); # 声明一个nameif target = 1 thenset name = 'MySQL';elseset name = 'Java';end if;insert into user(name) values(name);
end;
# 调用存储过程
call add_name(1);# 创建一个存储过程
create procedure count_of_user(out count_num int) # out表示返回值,count_num表示返回值名字
beginselect count(id) into count_num from user; # 把查出的结果赋给返回值count_num
end;
# 调用存储过程
call count_of_user(@count_num);
select @count_num;# 删除存储过程
drop procedure add_name;
drop procedure count_of_user;

MySQL44

JDBC:用 Java 语言来操作数据库的一种技术,具有通用性,无论底层数据库是什么,都可以使用 JDBC 来进行操作,而不需要修改接口,JDBC本身就是接口

Java —> JDBC —> 数据库

JDBC基本的使用:

import java.sql.*;public class Test {public static void main(String[] args) throws Exception {String url = "jdbc:mysql://localhost:3306/db01?useSSL=true";String user = "root";String password = "123456";Connection connection = DriverManager.getConnection(url, user, password);// 获取连接对象String sql = "select * from student";Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery(sql);// 将执行结果返回给结果集while (resultSet.next()) {ResultSetMetaData metaData = resultSet.getMetaData();// 获取结果集的字段属性int columnCount = metaData.getColumnCount();// 获取字段属性的个数for (int i = 1; i <= columnCount; i++) {String columnName = metaData.getColumnName(i);// 获取第i个字段属性的名字System.out.println("字段["+columnName+"]的值是:"+resultSet.getObject(columnName));}System.out.println("*****************************************");}}
}

MySQL45

数据库连接池:预先创建好一定数量的数据库连接对象,放到缓冲池中,当开发者需要连接的时候直接从缓冲池中取出使用,用完再还回到缓冲池中,这样就做到了对于资源的重复利用,提高效率。

和线程池、字符串常量池、包装类常量池都是一样的原理,只是缓冲池中存放的资源不同。

下面是使用c3p0线程池的例子

import com.mchange.v2.c3p0.ComboPooledDataSource;import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;public class JDBCUtil {private static ComboPooledDataSource dataSource;static {try {//创建连接池对象dataSource = new ComboPooledDataSource();dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");// 不同版本的驱动这里也会有所不同dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/db01?useSSL=true");dataSource.setUser("root");dataSource.setPassword("123456");dataSource.setInitialPoolSize(20);dataSource.setMaxPoolSize(40);dataSource.setMinPoolSize(2);dataSource.setAcquireIncrement(5);} catch (PropertyVetoException e) {e.printStackTrace();}}// 通过线程池获取连接对象public static Connection getConnection(){try {Connection connection = dataSource.getConnection();return connection;} catch (SQLException throwables) {throwables.printStackTrace();}return null;}}
import java.sql.*;public class Test {public static void main(String[] args) throws Exception {Connection connection = JDBCUtil.getConnection();String sql = "select * from student";Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery(sql);while (resultSet.next()) {ResultSetMetaData metaData = resultSet.getMetaData();int columnCount = metaData.getColumnCount();for (int i = 1; i <= columnCount; i++) {String columnName = metaData.getColumnName(i);System.out.println("字段["+columnName+"]的值是:"+resultSet.getObject(columnName));}System.out.println("*****************************************");}}
}

上面的示例中:数据源的参数直接写到 Java 程序中,如果数据源参数有变动,则需要重新修改Java代码,此时Java文件就要重新编译,导致效率低下。所以我们一般把数据源的参数内容写到配置文件中。

DBUtils:是对 JDBC 的一套封装,可以简化 CRUD 的操作,是一个轻量级小工具。能够帮助我们把数据库得到的结果集映射成对应的实体类。

我们可以尝试手写一个DBUtils,底层实现主要使用到了反射的机制。我们可以体会一下框架背后实现的原理

关键代码如下:

package com.util;public class Test2 {public static void main(String[] args) throws Exception{MyQueryRunner<User> myQueryRunner = new MyQueryRunner<>();String sql = "select * from user where id=1";User user = myQueryRunner.query(JDBCUtil.getConnection(),sql,new MyBeanHandler(User.class));System.out.println(user);}
}
package com.util;import org.apache.commons.dbutils.ResultSetHandler;import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;public class MyQueryRunner<T> {public T query(Connection connection, String sql, ResultSetHandler<T> rsh) throws SQLException {//非空校验if (connection == null) throw new SQLException("Null connection");if (sql == null) throw new SQLException("Null SQL statement");if (rsh == null) throw new SQLException("Null ResultSetHandler");//创建statementStatement stmt = connection.createStatement();//执行sqlResultSet rs = stmt.executeQuery(sql);//将结果集转为目标对象/*主要思路就三步:1、获取实体类的结构2、获取结果集的结构3、完成映射即可*/Object result = rsh.handle(rs);//返回目标对象return (T)result;}}
package com.util;import org.apache.commons.dbutils.ResultSetHandler;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.*;public class MyBeanHandler implements ResultSetHandler {private Class type;public MyBeanHandler(Class type) {this.type = type;}@Overridepublic Object handle(ResultSet resultSet) throws SQLException {//resultSet转为type对象//获取实体类的结构Map<String, Class> properties = getProperties();//获取结果集的结构List<String> colums = getColums(resultSet);//完成映射并且返回即可!return toBean(properties, colums,resultSet);}public Object toBean(Map<String, Class> properties,List<String> colums,ResultSet resultSet){Object result = null;try {//创建对象Constructor constructor = type.getConstructor(null);result = constructor.newInstance(null);//属性赋值if(resultSet.next()){for (String colum : colums) {Class aClass = properties.get(colum);String name = aClass.getName();Object value = null;switch (name){case "java.lang.Integer":value = resultSet.getInt(colum);break;case "java.lang.String":value = resultSet.getString(colum);break;}colum = "set"+colum.substring(0, 1).toUpperCase()+colum.substring(1);Method declaredMethod = type.getDeclaredMethod(colum, aClass);declaredMethod.invoke(result, value);}}} catch (Exception e) {e.printStackTrace();}return result;}public List<String> getColums(ResultSet resultSet){List<String> list = new ArrayList<>();try {ResultSetMetaData metaData = resultSet.getMetaData();int columnCount = metaData.getColumnCount();for (int i = 1; i <= columnCount; i++) {list.add(metaData.getColumnName(i));}} catch (SQLException throwables) {throwables.printStackTrace();}return list;}public Map<String,Class> getProperties(){Field[] declaredFields = type.getDeclaredFields();Map<String,Class> map = new HashMap<>();for (Field declaredField : declaredFields) {String fieldName = declaredField.getName();Class<?> fieldType = declaredField.getType();map.put(fieldName, fieldType);}return map;}
}

MySQL46

Maven 提供了一种服务,可以通过配置文件的方式从远程仓库下载相应的 jar 到本地仓库,自动从本地仓库将 jar 导入工程中。

配置文件中添加我们需要的 jar,Maven 会自动进行下载导入

MyBatis中一对多的关键代码如下:

package com.southwind.entity;import lombok.Data;@Data
public class Student {private Integer id;private String name;private Class clazz;
}
package com.southwind.entity;import lombok.Data;import java.util.List;@Data
public class Class {private Integer id;private String name;private List<Student> students;
}

下面是查询学生

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.southwind.mapper.StudentMapper"><resultMap id="studentMap" type="com.southwind.entity.Student"><id property="id" column="sid"></id><!--结果集的字段为主键的用id标签--><result property="name" column="sname"></result><!--相当于把Class类中的id和name属性封装成Class类对象传给Student类中的clazz属性--><association property="clazz" javaType="com.southwind.entity.Class"><id property="id" column="cid"></id><!--结果集的字段为主键的用id标签--><result property="name" column="cname"></result></association></resultMap><!--结果集映射成上面的studentMap--><select id="findById" resultMap="studentMap">select s.id sid,s.name sname,c.id cid,c.name cname from student s,class c where s.cid = c.id and s.id = #{id}</select></mapper>

下面是查询班级

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.southwind.mapper.ClassMapper"><resultMap id="classMap" type="com.southwind.entity.Class"><id property="id" column="cid"></id><result property="name" column="cname"></result><collection property="students" ofType="com.southwind.entity.Student"><id property="id" column="sid"></id><result property="name" column="sname"></result></collection></resultMap><select id="findById" resultMap="classMap" parameterType="java.lang.Integer"><!--parameterType这是参数类型,可以省略不写-->select s.id sid,s.name sname,c.id cid,c.name cname from student s,class c where s.cid = c.id and c.id = #{id}</select></mapper>

关键思路就是:如何把结果集映射为对应的实体类

MySQL47

MyBatis的延迟加载:多表关联查询的时候,一种优化机制。(本质上就是把级联查询转换成多个单表的查询。根据需要决定执行的sql语句次数)

MyBatis的延迟加载关键实现代码如下:(相当于嵌套查询)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.southwind.mapper.StudentMapper"><resultMap id="studetnMap" type="com.southwind.entity.Student"><id property="id" column="id"></id><result property="name" column="name"></result><association property="clazz" javaType="com.southwind.entity.Class" select="com.southwind.mapper.ClassMapper.findById" column="cid"></association></resultMap><select id="findById" resultMap="studetnMap">select * from student where id = #{id}</select></mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.southwind.mapper.ClassMapper"><select id="findById" resultType="com.southwind.entity.Class">select * from class where id = #{id}</select></mapper>

在MyBatis核心配置文件中添加如下配置开启MyBatis的延迟加载

<settings><setting name="logImpl" value="STDOUT_LOGGING" /><!--开启打印日志--><setting name="lazyLoadingEnabled" value="true"/><!--开启MyBatis的延迟加载-->
</settings>

一级缓存:自带,必须使用同一个 SqlSession

二级缓存:需要手动开启的

1、在MyBatis核心配置文件中开启二级缓存

<settings><setting name="logImpl" value="STDOUT_LOGGING" /><setting name="lazyLoadingEnabled" value="true"/><setting name="cacheEnabled" value="true"/><!--开启二级缓存-->
</settings>

2、在对应的 Mapper.xml 中配置二级缓存

<cache></cache>

3、实体类需要实现序列化接口

package com.southwind.entity;import lombok.Data;import java.io.Serializable;
import java.util.List;@Data
public class Class implements Serializable {private Integer id;private String name;private List<Student> students;
}

4、必须关闭 sqlsession,重新赋值

import com.southwind.entity.Class;
import com.southwind.entity.Course;
import com.southwind.entity.Student;
import com.southwind.mapper.AccountMapper;
import com.southwind.mapper.ClassMapper;
import com.southwind.mapper.CourseMapper;
import com.southwind.mapper.StudentMapper;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.InputStream;public class Test {public static void main(String[] args) {//加载MyBatis环境InputStream inputStream = Test.class.getClassLoader().getResourceAsStream("mybatis-config.xml");SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();SqlSessionFactory factory = builder.build(inputStream);SqlSession sqlSession = factory.openSession();//调用接口ClassMapper classMapper = sqlSession.getMapper(ClassMapper.class);Class aClass = classMapper.findById(1);System.out.println(aClass);sqlSession.close();sqlSession = factory.openSession();classMapper = sqlSession.getMapper(ClassMapper.class);Class aClass1 = classMapper.findById(1);System.out.println(aClass1);}
}

MySQL(查缺补漏)相关推荐

  1. MySQL查缺补漏 从无到有

    MySQL查缺补漏 从无到有 有这一篇就够了 数据库概述 SQL概述 什么是数据库 MySQL概述 SQL的分类 DOS命令窗口使用MySQL的基本命令 查看MySQL的版本 进入MySQL 导入数据 ...

  2. mysql查缺补漏(一) and or优先级和多表join

    1. and 和 or 的优先级问题 在where字句中出现多个and or ,and的优先级 先于or的优先级, select * from table1 where id = 1 or id =2 ...

  3. 2020年最新最全的Java面试经历整理(一次性查缺补漏个够)

    前言 现在已经是2020年了,相信很多人都在准备面试,,如何拿到心仪的 Offer,进入梦寐以求的大厂,实现自己的职业理想,达到程序员的小康水平. 这篇文章主要介绍了刘哥一月份的几次面经,(一次性查缺 ...

  4. JAVA核心,200例,查缺补漏

    适用于想要查缺补漏的人:本已经掌握的技术,但是不知道如何表达的人:不断完善技自己,顺带梳理下答案. 主要包括以下模块:Java基础.容器.多线程.反射.对象拷贝.Java Web模块,异常.网络.设计 ...

  5. 查缺补漏系统学习 EF Core 6 - 批量操作

    推荐关注「码侠江湖」加星标,时刻不忘江湖事 这是 EF Core 系列的第七篇文章,上一篇文章讲述了 EF Core 中的实体数据修改. 这篇文章讲一讲 EF Core 如何进行批量操作. 在众多的 ...

  6. EFCore查缺补漏(二):查询

    相关文章: EFCore查缺补漏 第 20 轮 TechEmpower 评测结果出炉了,ASP.NET Core 的 Plaintext 成绩名列前茅,带着 EFCore 的测试却在 Single q ...

  7. I2C总线学习—查缺补漏—S3C2440的I2C控制器

    I2C总线学习-查缺补漏-S3C2440的I2C控制器                  学习了IIC总线协议的理论部分,觉得应该学习具体操作2440的IIC控制器,毕竟最终都是为了学习S3C2440 ...

  8. I2C总线学习—查缺补漏—应答信号ACK

    I2C总线学习-查缺补漏-应答信号ACK           IIC协议规定,当主机作为接收设备时,主机对最后一个字节不应答,以向发送设备(从设备)标识数据传送结束.这是因为每次传输都应得到应答信号后 ...

  9. I2C总线学习—查缺补漏—对数据有效性的思考

    I2C总线学习-查缺补漏-对数据有效性的思考 IIC协议规定:SDA上传输的数据必须在SCL为高电平期间保持稳定,SDA上的数据只能在SCL为低电平期间变化.IIC期间在脉冲上升沿把数据放到SDA上, ...

  10. 查缺补漏:集和与非平凡属性

    查缺补漏:集和与非平凡属性 前面的习题和知识点补充 Conjunctive normal form(CNF)是布尔逻辑的一种方法,它将公式表示为带有AND或or的子句的连词.由连词or AND连接的每 ...

最新文章

  1. Windows10家庭版安装Hyper-V虚拟机
  2. React 组件学习
  3. java中写入文件的方法
  4. windows中如何设置开机自启tomcat,nginx,jdk等应用服务的解决办法
  5. ConcurrentHashMap的源码分析-initTable
  6. 使用POI 读取 Excel 文件,读取手机号码 变成 1.3471022771E10
  7. spark学习-33-Spark安全机制SecurityManager
  8. jsonobject修改key的值_JSONObject(org.json)的一点修改
  9. leetcode 61 Rotate List ----- java
  10. 图神经网络(二)--GNNs
  11. oracle11g64位怎么用sql,PLSQL Developer连接不上Oracle11g64位的解决办法
  12. vue中过滤器大全(一)【两位小数、银行卡号】
  13. bigworld源码分析(2)—— loginApp分析
  14. Win10 Outlook打不开,无法启动Microsoft Outlook。无法打开Outlook窗口。无法打开此文件夹集合。客户端操作失败
  15. unity调用高德地图
  16. tm4驱动外接模块系列(一)--------有dmp库的mpu6050
  17. Java实验3 第十一题:游戏:双骰儿赌博
  18. 干净利落的消除网页全局事件监听,匿名函数也可以搞定,一文让你掌握同步CSDN文章到公众号的技巧,从此远离繁重的编辑工作
  19. 简单的数值 variant
  20. 大电流导电滑环用途的介绍

热门文章

  1. 四:建立一个ipv4/ipv6的信息库
  2. Junit单元测试(白盒测试)
  3. java康纳塔评测_CANNONATA康纳塔 JAVA发布2016款终极赛车
  4. 探索贝叶斯-多项式/伯努力/补集朴素贝叶斯
  5. Java学习分享---数组排序方法
  6. html404页面怎么添加,404怎么办-页面自适应html源码
  7. python len_python中len
  8. 短信CMPP通信协议
  9. 游记-NOIP2018
  10. EMC一站式解决方案商