1、读取SQLMapConfig中的账户信息,mql地址等(SQL主配置文件);
2、加载xml文件;
3、创建SqlSessionFactory 可以创建多个sqlSession
SqlSessionFactory
连接Executor sql执行器与local catch缓存空间
读取数据库后,数据会放在缓存空间中,如果再次查询相同的内容,不会执行sql语句,而是读取缓存区。此所谓一级缓存
是获取参数值的两种方式
#{} 是占位符赋值
1、无论我们的值是什么,在sql拼接时都是?,等到数据库执行时才会变成值
2、使用占位符的方式进行字符串拼接,如果我们的字段是字符串类型,它会自动加上单引号
#{} 动态解析 预编译 编译 执行
占位符来源于预编译
?是更底层的东西,在mysql中执行比sql更好
${}字符拼接
1、在本地拼接sql语句时,就会拼接好
2、如果我们的字段是字符串类型的数据,我们需要手动添加单引号
#{} 动态解析 编译 执行
sql注入:改变原本sql语句规则的操作,就是sql注入
通过if判断,在sql语句后面加参数
如果使用了where 标签,字段开头的and或者or 会被剔除
set if同理
其中:choose:父标签(必须用)
when:if或else otherwise:else
可以取代and或or set
select * from user
<trim prefix="where" prefixOverrides="and | or"
批量添加和批量删除
delete from user where id in(6,7,8)
insert into user(字段们) values(…),(…),(…)
一对一、多对一、一对多
特殊情况单独处理 对象:association
fetchType:“lazy”和
property:实体类当众特殊字段的名称
javaType:特殊字段类型
select: 调用下一步的方法
column:传输字段
ofType:集合当中泛型的类型
一对多
<select id="TeacherStudent" resultMap="findTeacherStudent">
select student.*,teacher.Tname from student join teacher on teacher.id = student.t_id
select>
<resultMap id="findTeacherStudent" type="com.qcby.entity.Teacher">
<result property="id" column="id"/>
<result property="Tname" column="Tname"/>
<collection property="students" ofType="com.qcby.entity.Student">
<result property="id" column="id"/>
<result property="Sname" column="Sname"/>
<result property="sex" column="sex"/>
<result property="age" column="age"/>
<result property="t_id" column="t_id"/>
collection>
resultMap>
多对一
<select id="StudentTeacher" resultMap="findTeacher">
SELECT student.*,teacher.* from student JOIN teacher on student.t_id = teacher.id
select>
<resultMap id="findTeacher" type="com.qcby.entity.Student">
<result property="id" column="id"/>
<result property="Sname" column="Sname"/>
<result property="sex" column="sex"/>
<result property="age" column="age"/>
<result property="t_id" column="t_id"/>
<association property="teacher" javaType="com.qcby.entity.Teacher">
<result property="id" column="id"/>
<result property="Tname" column="Tname"/>
association>resultMap>
一对多,用collection——用ofType
多对一,用association——用javaType
一对多
<select id="getTeacherStudent" resultMap="get">
select * from teacher;
select>
<resultMap id="get" type="com.qcby.entity.Teacher">
<result property="id" column="id"/>
<result property="Tname" column="Tname"/>
<collection property="students" ofType="com.qcby.entity.Student"
select="getStudent" column="id"/>
resultMap>
<select id="getStudent" resultType="com.qcby.entity.Student">
select * from student where t_id = #{id}
select>
多对一
<select id="getStudentTeacher" resultMap="findStudentTeacher">
select * from student;
select>
<resultMap id="findStudentTeacher" type="com.qcby.entity.Student">
<result property="id" column="id"/>
<result property="Sname" column="Sname"/>
<result property="sex" column="sex"/>
<result property="age" column="age"/>
<result property="t_id" column="t_id"/>
<association property="teacher" javaType="com.qcby.entity.Teacher"
select="com.qcby.dao.TeacherDao.getTeacher" column="t_id" fetchType="lazy"/>
resultMap>
一对多,用collection
一对多,用association
就是所谓的按需加载。如果要全部数据,就依次加载,如果只要主表的数据,就只执行主体。如果查询副表中的数据,就执行副表。
在sqlmapconfig对象中
//懒加载开关,即延迟加载
//只有该值设置为false,才能实现按需加载
//开启会找所以对象属性
优点:方便,不需要编写xml文件,直接在接口中通过注释的形式编写sql代码
缺点:代码的灵活度不如xml
使用时
需要对SqlMapConfig.xml进行配置文件
<mappers>
<mapper class="com.qcby.dao.UserAnnoDao"/>
<package name="com.qcby.dao"/> mappers>
书写形式
public interface StudentDao {
@Select("select * from student")
@Results(id = "userMap" ,value={
@Result(property = "id",column = "id"),
@Result(property = "Sname",column = "Sname"),
@Result(property = "sex",column = "sex"),
@Result(property = "age",column = "age"),
@Result(property = "teacher",column = "t_id",one=@One(select = "com.qcby.dao.TeacherDao.getTeacher",fetchType = FetchType.LAZY))
})
public List<Student> getStudent();
}
是一种理念或者技术
为了保障两条sql同时成功或同时失败,引出事务
事务代码:
#开启事务
start transaction;
sql命令
#提交事务
commit;
rollback
事务回滚,一旦事务提交失败,将数据回滚到之前状态
1、原子性
事务是一个不可分割的单位,要么同时成功,要么同时失败
先更改undo log 这是一个重要的日志 是一个用于撤销回退的日志
增删改命令,都是先写到日志中。然后表反复读取日志
2、持久性
一旦事务提交,他对数据库的改变是永久的
undo log日志与缓冲池连接,表刷脏缓冲池
如果因停电,刷脏失败,redo log记录数组操作(我的理解,提前填好,如果成功就删除,失败就保留)
来电后,表立马读取redo log
3、隔离性
多个事务之间是相互隔离的,互不干扰
多个事务并发执行,事务之间不能产生干扰
没有隔离性会导致脏读,见2022.6.4图
锁:1、读未提交 脏读
2、读已提交 读到的都是已提交的。不可重
3、可重复读 会导致幻读,B已经把数据删了,A还可以读取到数据
4、串行化 A的数据插入提交之前,B的查询只能等待 吞吐量太低,用户体验太差
复读
4、一致性
是指事务执行结束之后,数据库完整性不会被破坏
start transaction#开启事务
sql巴拉巴拉
commit; //数据提交
rollback;//事务回滚 一旦事务提交失败,我们需要将数据回滚到之前的状态
![[DB}216HC(3{1M]}Q2S`OD 1.png]]
1、脏读 读未提交
![[脏读.png]]
![[脏读 1.png]]
2、不可重复读 读已提交
![[不可重复读.png]]![[读已提交代码.png]]
3、可重复读 幻读
![[幻读.png]]![[幻读-可重复读.png]]
4、串行化
![[串行化.png]]
1、创建数据库,随意添加部分数据
create table t_user(id int primary key auto_increment,username varchar(255));
2、设置事务等级
读未提交
set global transaction isolation level read uncommitted;
#查看当前隔离级别
select @@global.tx_isolation,@@tx_isolation;
#读已提交
set global transaction isolation level read committed;
#查看当前隔离级别
select @@global.tx_isolation,@@tx_isolation;
#幻读
set global transaction isolation level repeatable read;
查看当前隔离级别
select @@global.tx_isolation,@@tx_isolation;
#串行化
set global transaction isolation level serializable;
#查看当前隔离级别
select @@global.tx_isolation,@@tx_isolation;
2、cmd 转入到sql的bin目录下
3、sql -u root -p回车 密码
//转入到特定数据库下
use test
//开启事务
start transaction;
//sql命令
//提交
commit;
见有道笔记
1、什么是缓存
用户常使用的数据放在缓存中,用户查询数据就不需要从磁盘中查询
缓存是内存中的一块
3、什么样的数据能使用缓存
经常查询并不常改变的数据
本地缓存又叫一级缓存,一级缓存默认开启,一级缓存是在session中
二级缓存在SqlSessionFactory中
1、两次查询不同
2、两次查询执行的是增删改查等
3、手动清楚一级缓存
4、SqlSession不同
SqlSession内部的缓存二级缓存默认关闭
开启二级缓存的
1、重要参数eviction
LRU(清除最近最少使用的)
FIFO(先进先出)
2、flushinterval(刷新间隔:为了让sql与缓存中的数据一致性)
3、size,默认1024
4、readonly=“true”/“false” 默认是false
只读缓存,true只能读缓存里的,无法与sql交互
在Dao.xml中,仅当前dao有效
开启二级缓存必须关闭一级缓存——session1.close()
0.5是表示缓存命中:缓存中有要查询的数据
false:一级缓存中存储的是对象,而二级缓存中存储的是数据