延迟加载:在多表关联的 一对一可以积极加载,一对多可以使用延迟加载,优化功能
延迟加载的核心方法是 createresultObject
jdbc开发的问题:
1、数据库配置加载硬编码,切换到其他加载类不方便(使用配置文件)
2、频繁连接,释放数据库(连接池,c3p0,druid..)
3、sql,设置参数,获取结果集硬编码问题(使用配置文件)
4、手动封装结果集比较繁琐(使用反射)
设计持久层框架:
使用端(项目):引入自定义持久层jar包 提供 数据库配置信息;sql配置信息;参数类型,返回类型
数据库配置 sqlmapconfig.xml sql配置信息 mapper.xml
自定义持久层框架:本质是对jdbc的代码封装
(1)加载配置文件:根据配置文件的路径,加载文件成字节输入流,存储到内存中,创建resource类 方法:inputstream getresourceas stream(String path) 关键类org.apache.ibatis.io.Resources:用于配置文件的流加载
(2)创建两个javabean:(容器对象):存放配置文件解析的内容 configration:核心配置类:存放sqlmapconfig.xml 解析的内容 mapperedStatment:映射配置类:存放mapper解析的文件
关键类:org.apache.ibatis.session.Configuration 存储配置信息
org.apache.ibatis.mapping.MappedStatement 存储执行sql的数据
(3)解析配置文件:dom4j 创建类sqlsessionfactorybiulder 方法 biuld(inputstream in)
第一:使用dom4j解析配置文件,将解析出来的内容封装到Configuration和MappedStatement中,其中Configuration对MappedStatement进行引用,以hashmap的形式存储
第二:创建sqlsessionfactory对象的实现类DefaultSqlSession;生产sqlsession:会话对象(工厂模式)
(4)创建sqlsessionfactory接口及实现类defualsqlsessionfactory 实现类org.apache.ibatis.session.defaults.DefaultSqlSessionFactory
opensession类生产sqlsession, 实现类org.apache.ibatis.session.defaults.DefaultSqlSession
DefaultSqlSession负责与jdbc的执行
org.apache.ibatis.executor.BaseExecutor 对数据的执行
org.apache.ibatis.executor.statement.PreparedStatementHandler 根据传过来的对象,对Statement设置参数
org.apache.ibatis.executor.resultset.ResultSetHandler 对返回的结果集进行封装
mybitis缓存 mybatis存在一级缓存和二级缓存,一级缓存是限制在单个sqlsession中;二级缓存时对一个mapper的缓存,允许对各sqlsession访问,在分布式的环境下,需要整合redis实现分布式的二级缓存
一级缓存的数据时存放在对象中,二级缓存的是数据,不是对象
mybatis的结构:
mybatis加载mapper文件的方式有几种?
mysql的工作流程:
mybatis标签使用:
属性介绍:
定义sql语句的标签
select标签
id :唯一的标识符.
parameterType:传给此语句的参数的全路径名或别名 例:com.test.poso.User或user
resultType :语句返回值类型或别名。注意,如果是集合,那么这里填写的是集合的泛型,而不是集合本身(resultType 与resultMap 不能并用)
select * from student where id=#{id}
1.2 insert标签 属性介绍:
id :唯一的标识符 parameterType:传给此语句的参数的全路径名或别名 例:com.test.poso.User 复制代码
insert into student NAME, #{name},1.3 delete标签 属性同 insert
delete from student where id=#{id}2、java对象属性映射 如果数据库的字段名和java对象的映射不匹配,使用标签可以实现映射(映射文件的顺序在查询的上面或者下面是没有影响的,因为文件扫描的时候,会全文去找)
标签说明: 主标签: id:该resultMap的标志 type:返回值的类名,此例中返回Studnet类
select id,name,hobby,major,birthday,age from student where id=#{id}动态sql的拼接: 3. 动态sql拼接 3.1 if 标签 if标签通常用于WHERE语句、UPDATE语句、INSERT语句中,通过判断参数值来决定是否使用某个查询条件、判断是否更新某一个字段、判断是否插入某个字段的值。
and NAME = #{name}foreach标签主要用于构建in条件,可在sql中对集合进行迭代。也常用到批量删除、添加等操作中。 select name,hobby from student where id in #{item}
属性介绍:
collection:collection属性的值有三个分别是list、array、map三种,分别对应的参数类型为:List、数组、map集合。 item :表示在迭代过程中每一个元素的别名 index :表示在迭代过程中每次迭代到的位置(下标) open :前缀 close :后缀 separator :分隔符,表示迭代时每个元素之间以什么分隔
3.3 choose标签 有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。MyBatis提供了choose 元素,按顺序判断when中的条件出否成立,如果有一个成立,则choose结束。当choose中所有when的条件都不满则时,则执行 otherwise中的sql。类似于Java 的switch 语句,choose为switch,when为case,otherwise则为default。
if是与(and)的关系,而choose是或(or)的关系。
choose标签的功能:
SELECT * from STUDENT WHERE 1=1
AND name LIKE CONCAT(CONCAT('%', #{student}),'%')
AND hobby = #{hobby}
AND AGE = 15
《where标签》
当name值为null时,查询语句会出现 “WHERE AND” 的情况,解决该情况除了将"WHERE"改为“WHERE 1=1”之外,还可以利用where标签。这个“where”标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,(如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉。)
SELECT * from STUDENT
NAME LIKE CONCAT(CONCAT('%', #{name}),'%')
AND hobby = #{hobby}
《set》标签的作用:
没有使用if标签时,如果有一个参数为null,都会导致错误。当在update语句中使用if标签时,如果最后的if没有执行,则或导致逗号多余错误。使用set标签可以将动态的配置set关键字,和剔除追加到条件末尾的任何不相关的逗号。
实战:
使用set+if标签修改后,如果某项为null则不进行更新,而是保持数据库原值。
UPDATE STUDENT
NAME = #{name},
MAJOR = #{major},
HOBBY = #{hobby}
WHERE ID = #{id};
; trim属性主要有以下四个
prefix:前缀覆盖并增加其内容 suffix:后缀覆盖并增加其内容 prefixOverrides:前缀判断的条件 suffixOverrides:后缀判断的条件 www.cnblogs.com/zjfjava/p/8…
关联查询中的一对一,一对多的问题 5.1 collection标签 5.2 association标签 www.cnblogs.com/zjfjava/p/8…
命名空间
当多种类型的查询语句的查询字段或者查询条件相同时,可以将其定义为常量,方便调用。为求结构清晰也可将sql语句分解 定义常量及引用 6.1 sql标签 当多种类型的查询语句的查询字段或者查询条件相同时,可以将其定义为常量,方便调用。为求结构清晰也可将sql语句分解。
复制代码
<sql id="Base_Column_List">
ID,MAJOR,BIRTHDAY,AGE,NAME,HOBBY
</sql>
<sql id="Example_Where_Clause">
where 1=1
<trim suffixOverrides=",">
<if test="id != null and id !=''">
and id = #{id}
</if>
<if test="major != null and major != ''">
and MAJOR = #{major}
</if>
<if test="birthday != null ">
and BIRTHDAY = #{birthday}
</if>
<if test="age != null ">
and AGE = #{age}
</if>
<if test="name != null and name != ''">
and NAME = #{name}
</if>
<if test="hobby != null and hobby != ''">
and HOBBY = #{hobby}
</if>
<if test="sorting != null">
order by #{sorting}
</if>
<if test="sort!= null and sort != '' ">
order by ${sort} ${order}
</if>
</trim>
</sql>
6.2 include标签 用于引用定义的常量
<select id="selectAll" resultMap="BaseResultMap">
SELECT
<include refid="Base_Column_List" />
FROM
student
<include refid="Example_Where_Clause" />
</select>
<select id="select" resultMap="BaseResultMap">
select * from (
select tt.*,rownum as rowno from
(
SELECT
<include refid="Base_Column_List" />
FROM
student
<include refid="Example_Where_Clause" />
) tt
<where>
<if test="pageNum != null and rows != null">
and rownum <![CDATA[<=]]>#{page}*#{rows}
</if>
</where>
) table_alias
where table_alias.rowno>#{pageNum}
</select>
<delete id="deleteByEntity" parameterType="java.util.Map">
DELETE FROM student
<include refid="Example_Where_Clause" />
</delete>
(1)Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。程序员直接编写原生态sql,可以严格控制sql执行性能,灵活度高。
Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具
因此 mybatis 中优先使用 #{};当需要动态传入 表名或列名时,再考虑使用 ${} 。
#{}是预编译处理,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
mybaties懒加载的实现
使用场景:在对应的四种表关系中,一对多、多对多通常情况下采用延迟加载,多对一、一对一通常情况下采用立即加载。
用户的查询,关联账户查询
账户的查询
mybaties配置中设置全局懒加载
懒加载的测试
调用的该对象的关联属性值,才加载数据
缓存机制在集群的环境下,会出现脏读,不建议使用