Mybatis01
一.引言
- 现有Jdbc的缺陷
- 代码冗余(相似度90%) , 只有sql命令不同
- 参数的绑定 和 实体类对象的封装(数据封装) 需要手工完成
- jdbc技术没有提供”连接池”功能
- 没有提供”缓存”机制
- Mybatis框架
- 是一种基于java的框架 , 对jdbc代码的封装 , 主要优化数据的持久化操作 , 提出
了一种新的方式完成dao接口的实现
2)实现机制
- 搭建环境
- 引入jar包
Mybatis-3.2.2.jar ojdbc5.jar log4j.jar(不是必须的,做日志输出的) - 引入配置文件 — src
Mybatis-config.xml(文件名随意) log4j.properties - 初始化配置 – 写mybatis-config.xml
二.第一个Mybatis程序 — 查询数据
- 准备
- 表 2) 实体类 3) dao接口
-
写映射文件 TeacherDaoImpl.xml
-
注册映射文件 – 将自定义的映射文件注册到配置文件里
-
测试代码 — service层代码
-
mybatis里的核心类
① SqlSessionFactoryBuilder : 是读取mybatis框架配置文件mybatis-config的工具类
(获取框架的运行环境) , 并将读到的内容封装成对象存储下来
② SqlSessionFactory : 当前类型的对象里封装了mybatis配置文件的信息
③ SqlSession : 将mapper文件翻译成接口的实现类,并创建对象返回 ; session里封装
了jdbc中的Connection对象 ( 一一对应 ) -
代码
① 创建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
-
删除功能 delete
-
更新功能 update
-
插入功能 insert
四.Dao层的其他功能 — 查所有
-
方法声明 — public List queryAll() ;
-
映射文件
<select id=”queryAll” resultType=”集合里一个元素的类型 entity.Teacher”>
Select * from teacher
五.封装MybatisUtil工具类
- Mybatis启动时需要读取配置文件(只读取一次即可) , 需要将代码定义在静态代码块
- SqlSessionFactory对象里封装了配置文件信息 , 是重量级组件(内存占用多, 功能强大,
运行效率低 , 线程安全) ,一般应用中只会创建一个这样的对象. - SqlSession与Connection一一对应的 , 线程不安全(不能在多个线程间共享,需要为每一
个线程单独分配一个session — ThreadLocal )
六.映射文件的特殊写法 — 查询
- 多参查询 – 省略parameterType
注意:方法的形参名不能长时间保留,在编译过程中丢失,不能在映射文件中使用
解决:
1) 通过参数的下标来指定获取哪一个参数的值
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210605112110400.png)
2) 通过注解为参数定义可以长久保留的名字( 至少出现在字节码文件里 )
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210605112117119.png)
Mybatis02
一.复习
- Mybatis框架 : 基于java的框架 , 做数据持久化 , 替换jdbc技术完成dao
- 环境搭建 : 1) jar引入 2) 引入配置文件–src 3) 初始化配置mybatis-config.xml
- 使用mybatis框架
- 准备 : table entity dao接口
- 定义映射文件为接口提供实现 mapper.xml
|--
关于parameterType : 方法没有参数 或者 参数个数多于1个 ,省略该属性
关于resultType: 单个对象写对象的全类名 , 返回值为集合则只需要指定集合
里元素的类型
关于sql命令: 取值#{ 注解为参数定义的名字 or 对象的属性名 or 下标 }
|--
|--
|--
|--
查询一个int值为参数对象的id属性赋值
|-- insert命令 - 注册映射文件 – 配置mybatis-config.xml
|-- <mapper resource=”映射文件路径 — 从src开始写”/> - 核心类
① SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); 工具
② Reader reader = Resources.getResourceAsReader(“mybatis-config.xml”);
③ builder.build(reader) —> SqlSessionFactory对象
④ SqlSession session = factory.openSession();
⑤ session.getMapper( 接口的类对象) --> 接口的对象
4.工具类
二.映射文件的特殊写法 — 主要查询
- 多参查询 – 省略parameterType 重点
注意:方法的形参名不能长时间保留,在编译过程中丢失,不能在映射文件中使用
解决:
1) 通过参数的下标来指定获取哪一个参数的值
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210605112237571.png)
2) 通过注解为参数定义可以长久保留的名字( 至少出现在字节码文件里 )
![在这里插入图片描述](https://img-blog.csdnimg.cn/2021060511225079.png)
- 关于特殊符号的处理 — < >
1) 使用特殊的文字来代替符号 < -- < > -- >
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210605112321517.png)
2) 使用脚本标签来定义 --- 强烈建议
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210605112328861.png)
注意: 大多数脚本语言都用该标签解决代码中的特殊符号
- 模糊查询 like
1) 可以在映射文件里的sql命令上使用 || 拼接通配符
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210605112337493.png)
2) 可以在dao方法被调用时, 在实参位置拼接
- 属性名和列名不一致 ( 尽量避免 )
1) mybatis封装查询结果时(实体对象) , 会使用”查询结果里的字段名” 去为 实体的”
同名属性” 赋值 , 如果没有同名属性则该值赋值失败
2) 当实体类属性名与结果字段名不一致时 , 解决: 可以在查询过程中为字段定义”别
名” , 要求别名要与实体类的属性名一致
- 关于insert和update过程中的null的处理
当插入过程中出现null值时 , 需要使用jdbcType来指定null所代表的类型
三.配置文件的小技巧 — mybatis-config.xml
- 关于实体类全类名的简化问题
-
mybatis允许在配置文件里为实体类entity统一定义”简称”或者”别名” , 可以在映射
文件中使用简称
2)使用标签
- 注意: 接口名不能简化
- mybatis开发步骤:
① 准备 ②为实体类定义别名 ③映射文件 ④注册映射文件
- 关于数据库连接数据的定义
将数据库的连接信息单独定义在一个配置文件里, 在mybatis配置文件中引入并使用
- 总结补充 — 各种取值
- EL里的取值 ---- ${ xxxScope.name }
- mybatis映射文件中获取参数的值 — #{ xxx } —PreparedStatement
- mybatis映射文件中还可以使用 ${xxxx} — Statement
- mybatis的配置文件中获取”其他配置文件信息” — ${ xxx }
- struts2的dmi技术中 {1} – 获取第一个通配符所在位置的值
- struts2配置文件中可以通过 ${action的实例变量名} – 获取action的实例变量的值
- <s:url value=”%{ognl}” >
四.关联关系数据的处理 [重点]
- 两个相对独立的数据之间的联系 — 关联关系
- 分类
- 一对一 : 学生student ~ 电脑computer
- 一对多( 多对一 ) : 普遍关系[重点] , 学生student ~ 小组team
- 多对多 : studnet ~ course , product ~ order
五.多对一关系 student --> team
-
在db里将数据描述清楚( 存放在哪一张表里 , 体现表里记录间的关系 )
-
在java程序里通过实体类将数据描述清楚( 数据怎么存 , 体现关系 )
-
定义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
-
在db里描述清楚
-
在java的实体类之间描述关系
- 定义dao接口 — 两个dao
- 没有关系属性的实体类对应的dao ( StudentDao ) — 单表操作
- 有关系属性的实体类对应的dao ( TeamDao )
① 增删改 — 单表操作
② 查询 – 查询完整的team对象( id name count 和 list )
七.Struts2和mybatis整合
- 搭建环境 — web project
- 引入jar包 — struts的jar包 mybatis的jar包
- 引入配置文件 — struts.xml mybatis-config.xml — src
- 初始配置 — struts配置核心过滤器(web.xml)
mybatis配置启动环境(mybatis-config.xml) - 设置项目编码
- 定义sql文件 ( 建表 )
- 定义实体类 ( 描述关系 )
- 可选 : 定义实体类的别名 Alias
- 定义dao接口
- 写映射文件
- 注册映射文件
- 定义service层程序 (与原来的写法基本一致)
Public … Xxxx( … ){
Try{
Dao dao = (Dao)MybatisUtil.getMapper(Dao.class);
Xxxxxxxx
MybatisUtil.commit();
}catch(Exception e){
MybatisUtil.rollback();
Throw new RuntimeException(e.getMessage());
}
} - Action —> 收参 , 调用service层方法 , 返回String跳转
- Jsp展示数据 —> struts标签
<option value=”did”> dname </option>
一.一对一关联关系数据的处理 – student 和 computer
- 在db里如何通过表的形式来存储数据和体现关系
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210605112802495.png)
-
Java类里体现一对一关系
-
写dao (两个dao)
-
给实现 ( 映射文件实现 )
- 没有关系属性的类对应的dao( ComputerDao ) — 单表操作
- 有关系属性的dao ( StudentDao ) — 增删改与单表一致, 查询特殊
二.多对多关系 student ~ course
- 在db里建表 ( 存储数据本身 , 描述关系 )
-
在java里通过实体类描述数据和关系
-
定义dao接口?
1) 如果直接描述多对多关系会导致 ”数据库里表的个数”与“实体类的个数”不对等 ,
一般情况下, 开发时只需要程序员提供”查询”业务 , 此时定义两个dao(针对两个
实体类定义)即可
①没有关系属性的dao --- 单表查询操作
②有关系属性的dao --- 表连接查询操作(多表连接查询 --- 3张)
2) 如果业务里需要”增删改”功能 , 建议在业务需求分析时,直接将多对多拆分成两个
一对多( 通过添加一组中间的业务数据完成 )
三.动态sql — 依靠标签在映射文件中动态拼接sql命令
-
… 条件判断标签
-
: 代替where命令 , 标签可以动态的根据情况去掉命令后的多余的and或者or
-
使用where标签
-
使用trim标签
- 标签 — 用在修改上
作用: 在修改时,去掉命令中多余的”,”
1)使用set标签
-
使用标签
- 关于标签
-
案例 : 批量删除
-
解决
- 总结 : 针对每个命令的特殊处理方法
- insert ( 如果插入null值) : #{ xxx , jdbcType=XXXX }
- update ( 如果更新时有null值 ) : 和
- delete ( 批量删除 ) : where xxx in(…)
- select ( 筛选条件为null的情况 ) : 和
四.Mybatis缓存
-
什么是缓存? 好处
-
Mybatis里缓存的分类 — 提供缓存机制
-
一级缓存 : SqlSession级别的缓存( 默认提供 ) , sqlSession对象有一块缓存区域 ,
只要当前session执行过的sql命令结果会被缓存在自己的空间里, 不同
的session互不影响
2)二级缓存 : mapper级别的缓存( 全局缓存 ) , mybatis为每一个namespace提供了一
块缓存区 , 不同session执行了同一个namespace里的查询命令, 结果都
会被缓存在”二级缓存里”
- 二级缓存使用步骤
-
开启mybatis的二级缓存
-
在当前的mapper文件里设置
- 二级缓存的特点
- 当session关闭时, session执行的查询结果会进入二级缓存
- 当session调用了接口的增删改方法 并提交 , 则二级缓存会被清空