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 queryAll() ;
2. 映射文件
Select * from teacher
五. 封装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命令 , 标签可以动态的根据情况去掉命令后的多余的and或者or
1) 使用where标签
2) 使用trim标签
3. 标签 --- 用在修改上
作用: 在修改时,去掉命令中多余的”,”
1)使用set标签
2) 使用标签
4. 关于标签
1) 案例 : 批量删除
2) 解决
5. 总结 : 针对每个命令的特殊处理方法
1) insert ( 如果插入null值) : #{ xxx , jdbcType=XXXX }
2) update ( 如果更新时有null值 ) : 和
3) delete ( 批量删除 ) : where xxx in(.....)
4) select ( 筛选条件为null的情况 ) : 和
十四. 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标签