mybatis动态SQL

mybatis流程

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注入

动态sql

通过if判断,在sql语句后面加参数

where if

如果使用了where 标签,字段开头的and或者or 会被剔除
set if同理

choose when otherwise 相当于是java当中的if elseif else

其中:choose:父标签(必须用)	
when:if或else	otherwise:else

trim

可以取代and或or set

select * from user
	<trim prefix="where" prefixOverrides="and | or"

foreach

批量添加和批量删除
delete from user where id in(6,7,8)
insert into user(字段们) values(…),(…),(…)

mybatis关联映射

一对一、多对一、一对多

resultMap

特殊情况单独处理 对象: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;//事务回滚 一旦事务提交失败,我们需要将数据回滚到之前的状态

1、2、原子性与持久性

![[DB}216HC(3{1M]}Q2S`OD 1.png]]

3、隔离性

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:一级缓存中存储的是对象,而二级缓存中存储的是数据

你可能感兴趣的:(mybatis,sql,java)