07 Mybatis

Mybatis

一.概述

1.现有jdbc代码的不足

   1)代码冗余大(对于不同的表的dao实现类,只有sql命令是不同的)

   2)对于结果实体类对象的封装需要程序员手工完成(o-r mapping)

   3)jdbc代码没有提供“连接池”功能,需要人为的引入外部的连接池软件

   4)jdbc没有提供缓存机制

2.Mybatis框架

    1)Mybatis框架是一个基于java的,做数据持久化操作的框架。是对现有的jdbc代码
      的合理封装,替换jdbc代码完成数据库的访问操作(Dao)。

    2)Mybatis提供一种新的机制完成dao接口的实现

在这里插入图片描述

二.搭建环境

   1) 引入jar包 
       Mybatis-3.2.2.jar   ojdbc5.jar    log4j.jar(不是必须的,做日志输出的)
   2) 引入配置文件 --- src 
       Mybatis-config.xml(文件名随意)   log4j.properties 
   3) 初始化配置 -- 写mybatis-config.xml

在这里插入图片描述

三. 第一个Mybatis程序 — 查询数据

 1. 准备  
	1) 表  2) 实体类   3) dao接口
 2. 写映射文件 TeacherDaoImpl.xml

在这里插入图片描述

 3. 注册映射文件 -- 将自定义的映射文件注册到配置文件里

在这里插入图片描述

 4. 测试代码 --- service层代码
   1)  mybatis里的核心类
      ① SqlSessionFactoryBuilder : 是读取mybatis框架配置文件mybatis-config的工具类(获取框架的运行环境) , 并将读到的内容封装成对象存储下来
      ② SqlSessionFactory : 当前类型的对象里封装了mybatis配置文件的信息
      ③ SqlSession : 将mapper文件翻译成接口的实现类,并创建对象返回 ; session里封装
             了jdbc中的Connection对象 ( 一一对应 ) 

   2) 代码
      ① 创建SqlSessionFactoryBuilder对象
         SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
      ② 获取读文件的io流对象
         Reader  reader = Resources.getResourceAsReader(“文件的路径--从src下开始写”) ;
      ③ 获取SqlSessionFactory对象
         SqlSessionFactory factory = builder.build( reader );  //开始读文件并封装
      ④ 获取SqlSession
         SqlSession session = factory.openSession();
      ⑤ 获取接口的实现类对象
         XxxDao  dao = session.getMapper( XxxDao.class );.其他DML功能 ( insert update  delete )
  
  注意: 功能涉及到增删改任一操作 , 都必须手动显示commit

  1. 删除功能 delete

  2. 更新功能 update
    

在这里插入图片描述

 3. 插入功能 insert

在这里插入图片描述
在这里插入图片描述

四. Dao层的其他功能 — 查所有

 1. 方法声明 --- public List<Teacher> queryAll() ;

 2. 映射文件
      <select id=”queryAll”  resultType=”集合里一个元素的类型 entity.Teacher”>
         Select * from teacher 
      </select>

五. 封装MybatisUtil工具类

1. Mybatis启动时需要读取配置文件(只读取一次即可) , 需要将代码定义在静态代码块
2. SqlSessionFactory对象里封装了配置文件信息 , 是重量级组件(内存占用多, 功能强大,
   运行效率低 , 线程安全) ,一般应用中只会创建一个这样的对象. 
3. SqlSession与Connection一一对应的 , 线程不安全(不能在多个线程间共享,需要为每一
个线程单独分配一个session --- ThreadLocal )

六. 映射文件的特殊写法 — 查询

 1. 多参查询 -- 省略parameterType
     注意:方法的形参名不能长时间保留,在编译过程中丢失,不能在映射文件中使用
     解决:
     1) 通过参数的下标来指定获取哪一个参数的值
     2) 通过注解为参数定义可以长久保留的名字( 至少出现在字节码文件里 )

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  2. 关于特殊符号的处理 ---  <   >

     1) 使用特殊的文字来代替符号  &lt; -- <   &le; --<=  &gt; -- >  &ge; -->= 

在这里插入图片描述

	2) 使用脚本标签来定义 --- 强烈建议
	注意: 大多数脚本语言都用该标签解决代码中的特殊符号

在这里插入图片描述

 3. 模糊查询  like
     1) 可以在映射文件里的sql命令上使用 || 拼接通配符

在这里插入图片描述

    2) 可以在dao方法被调用时, 在实参位置拼接

在这里插入图片描述
在这里插入图片描述

 4. 属性名和列名不一致 ( 尽量避免 )
     1) mybatis封装查询结果时(实体对象) , 会使用”查询结果里的字段名” 去为 实体的”
       同名属性” 赋值 , 如果没有同名属性则该值赋值失败

     2) 当实体类属性名与结果字段名不一致时 , 解决: 可以在查询过程中为字段定义”别
        名” , 要求别名要与实体类的属性名一致

在这里插入图片描述
在这里插入图片描述

5. 关于insert和update过程中的null的处理
  	当插入过程中出现null值时 , 需要使用jdbcType来指定null所代表的类型

在这里插入图片描述
在这里插入图片描述

七. 配置文件的小技巧 — mybatis-config.xml

 1. 关于实体类全类名的简化问题
	1) mybatis允许在配置文件里为实体类entity统一定义”简称”或者”别名” , 可以在映射
  		文件中使用简称
	2)使用标签 <typeAliases>
					1)<typeAlias type="com.wzx.entity.Teacher" alias="Teacher"/>
					<!--  为实体类所有的实体取别名(去掉包名,剩下的类名就是别名) 并且不区分大小写-->
					2)<package name="com.wzx.entity"/>
     		  </typeAliases>
	3) 注意: 接口名不能简化
    4) mybatis开发步骤:  
       ① 准备  ②为实体类定义别名  ③映射文件  ④注册映射文件 

在这里插入图片描述
在这里插入图片描述

2. 关于数据库连接数据的定义
     将数据库的连接信息单独定义在一个配置文件里, 在mybatis配置文件中引入并使用

在这里插入图片描述

3. 总结补充 --- 各种取值
   1) EL里的取值 ---- ${ xxxScope.name }
   2) mybatis映射文件中获取参数的值 --- #{ xxx } ---PreparedStatement
   3) mybatis映射文件中还可以使用 ${xxxx} --- Statement 
   4) mybatis的配置文件中获取”其他配置文件信息” --- ${ xxx }
   5) struts2的dmi技术中 {1} -- 获取第一个通配符所在位置的值
   6) struts2配置文件中可以通过 ${action的实例变量名} -- 获取action的实例变量的值
   7) <s:url value=%{ognl}>  

八. 关联关系数据的处理 [重点]

1. 两个相对独立的数据之间的联系 --- 关联关系
2. 分类 
	1) 一对一 :  学生student ~ 电脑computer   
	2) 一对多( 多对一 ) : 普遍关系[重点] ,  学生student ~ 小组team
	3) 多对多 :  studnet ~ course  ,  product ~ order

九. 多对一关系 student --> team

 1. 在db里将数据描述清楚( 存放在哪一张表里 , 体现表里记录间的关系 )

在这里插入图片描述

  2. 在java程序里通过实体类将数据描述清楚( 数据怎么存 , 体现关系 ) 

在这里插入图片描述

 3. 定义dao接口 --- 两个dao接口 -- 多对一( studnet里有关系属性 , team里没有 )
	1)TeamDao( 基础5个方法 ) -- 与原来的单表操作一致
	2)StudentDao( 基础5个方法) -- 拥有关系属性的实体类对应的dao
      ① 增删改 -- 与原来单表操作一致
      ② 查询特殊 -- 需要查询完整的"学生对象"(学生基本信息,以及所在team的信息)
                    所有数据来自于两张表( 需要表连接查询 -- 左外连接 )
         Select s.id sid , s.name sname , s.age , t.id tid , t.name tname , t.count 
         From student s left join team t on s.tid = t.id where s.id = #{id}

在这里插入图片描述

十. 一对多 team --> student

  1. 在db里描述清楚

在这里插入图片描述

  2. 在java的实体类之间描述关系

在这里插入图片描述

 3. 定义dao接口 --- 两个dao
	1) 没有关系属性的实体类对应的dao ( StudentDao ) --- 单表操作
	2) 有关系属性的实体类对应的dao ( TeamDao ) 
   		① 增删改 --- 单表操作
   		② 查询 -- 查询完整的team对象( id name count 和 list )  

在这里插入图片描述

十一. 一对一关联关系数据的处理 – student 和 computer

1. 在db里如何通过表的形式来存储数据和体现关系
	fk+uk:关系松散,可以独立存在
	Fk+pk:关系紧密,不能独立存在的数据(共享主键  人---户口本)

在这里插入图片描述
在这里插入图片描述

  2. Java类里体现一对一关系

在这里插入图片描述

 3. 写dao (两个dao) 
 4. 给实现 ( 映射文件实现 )
	1) 没有关系属性的类对应的dao( ComputerDao ) --- 单表操作
	2) 有关系属性的dao ( StudentDao ) --- 增删改与单表一致, 查询特殊

在这里插入图片描述

十二. 多对多关系 student ~ course

1. 在db里建表 ( 存储数据本身 , 描述关系 )
	中间表:1)有连个fk分别指向两张表的主键
		   2)联合主键:使用两个字段共同担当主键

在这里插入图片描述

 2. 在java里通过实体类描述数据和关系

在这里插入图片描述

 3. 定义dao接口?
     
     多对多关系的处理原则:分析是否需要增删改操作
   		不需要:按照之前步骤开发(db里三张表,entity有两个)此时需要提供两个dao接口(只会有查询方法),
     		  对查询方法特殊处理(表连接查询--3张表,封装resultMap)
    	需要:推翻之前所有设计,在最初分析阶段直接将多对多拆分成两个一对多处理(添加一组中间的业务数据)
     
     1) 如果直接描述多对多关系会导致 ”数据库里表的个数”与“实体类的个数”不对等 ,
        一般情况下, 开发时只需要程序员提供”查询”业务 , 此时定义两个dao(针对两个
        实体类定义)即可
        ①没有关系属性的dao --- 单表查询操作
        ②有关系属性的dao --- 表连接查询操作(多表连接查询 --- 3)

在这里插入图片描述

	2) 如果业务里需要”增删改”功能 , 建议在业务需求分析时,直接将多对多拆分成两个
        一对多( 通过添加一组中间的业务数据完成 ) 

在这里插入图片描述

十三. 动态sql — 依靠标签在映射文件中动态拼接sql命令

  1. <if test=boolean值”> ... </if>  条件判断标签

在这里插入图片描述

 2. <where> : 代替where命令 , 标签可以动态的根据情况去掉命令后的多余的and或者or
 	 1) 使用where标签
 	 2) 使用trim标签

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. <set> 标签  --- 用在修改上
	作用: 在修改时,去掉命令中多余的”,” 

在这里插入图片描述

1)使用set标签
2) 使用<trim>标签

在这里插入图片描述
在这里插入图片描述

 4. 关于<foreach>标签
     1) 案例 : 批量删除

在这里插入图片描述

2) 解决

在这里插入图片描述

5. 总结 : 针对每个命令的特殊处理方法
    1) insert ( 如果插入null值) :  #{ xxx , jdbcType=XXXX }
    2) update ( 如果更新时有null值 ) : <set> 和 <if> 
    3) delete ( 批量删除 ) :  <foreach>   where xxx in(.....)
    4) select ( 筛选条件为null的情况 ) : <where> 和 <if>    

十四. Mybatis缓存

1. 什么是缓存? 好处

在这里插入图片描述

2. Mybatis里缓存的分类 --- 提供缓存机制
    1) 一级缓存 : SqlSession级别的缓存( 默认提供 ) , sqlSession对象有一块缓存区域 , 
                 只要当前session执行过的sql命令结果会被缓存在自己的空间里, 不同
                 的session互不影响
    2)二级缓存 : mapper级别的缓存( 全局缓存 ) , mybatis为每一个namespace提供了一
                块缓存区 , 不同session执行了同一个namespace里的查询命令, 结果都
                会被缓存在”二级缓存里”

在这里插入图片描述

3. 二级缓存使用步骤
     1) 开启mybatis的二级缓存 

在这里插入图片描述

	2) 在当前的mapper文件里设置

在这里插入图片描述

4. 二级缓存的特点
     1) 当session关闭时, session执行的查询结果会进入二级缓存
     2) 当session调用了接口的增删改方法 并提交 , 则二级缓存会被清空
面试题:如何提高插入的效率?
1)使用JDBC  PrepareStatement
2)控制事物大小(1000-2000条左右)
3)使用批更新(缓存--已空间换时间(存放100-200条))
4)记录日志(记录每条数据的成功与失败设个计数器)

十五. Struts2和mybatis整合

1. 搭建环境 --- web project
    1) 引入jar包 ---  struts的jar包   mybatis的jar包
    2) 引入配置文件 ---  struts.xml  mybatis-config.xml --- src
    3) 初始配置 ---  struts配置核心过滤器(web.xml)  
              		mybatis配置启动环境(mybatis-config.xml)
    4) 设置项目编码
2. 定义sql文件 ( 建表 )
3. 定义实体类 ( 描述关系 )
4. 可选 : 定义实体类的别名 Alias
5. 定义dao接口
6. 写映射文件 
7. 注册映射文件
8. 定义service层程序 (与原来的写法基本一致)
        Public .... Xxxx( ..... ){
            try{
            Dao dao = (Dao)MybatisUtil.getMapper(Dao.class);
            Xxxxxxxx
            MybatisUtil.commit();
            }catch(Exception e){
            	MybatisUtil.rollback();
            	Throw new RuntimeException(e.getMessage());
        	}
        }
9. Action ---> 收参 , 调用service层方法 , 返回String跳转
10. Jsp展示数据 ---> struts标签  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值