工程搭建思路
1. 导入依赖jar包
2. 创建SqlMapConfig.xml
在项目目录下新建SouceFolder:Config
在这个目录下新建SqlMapConfig.xml
找头部约束
3. 配置log4j.properties
Mybatis sql输出依赖log4j
4. 创建与表一致的pojo
5.配置sql查询的xml文件
与pojo对应,eg:User.xml
6.加载映射文件
将每个pojo的映射文件配置到Mybatis的配置文件
mappers
resource属性配置xml文件的路径
根据ID查询用户信息
1. 编写sql语句
2. 配置user映射文件
select标签
id:语句的唯一标识
parameterType:入参的数据类型
resultType:pojo 返回结果的数据类型
#{}:是占位符,相当与JDBC的问号
3. 编写测试程序
创建sqlsessionFactorybuilder对象
创建核心配置文件的输入流
通过输入流创建sqlsessionFactory对象
创建sqlSession对象
执行查询,参数1:sqlId,入参
输出用户
释放资源
每次写代码都要重复一些步骤,把它们抽取成工具类
为什么抽取sqlsessionFactory而不把sqlSession也放进工具类?
官方文档有说明:sqlsessionFactory不应该被反复创建,应该使用单例。
而sqlSession不同,每个线程应该有自己的sqlSession,不共享,不是线程安全的。
${}字符串拼接指令
如果入参为普通类型,括号内只能写value
Mybatis默认不提交事务,需要手动commit
要操作数据就要记得commit
或者在openSession(true)
selectKey:主键返回
keyProperty:user中的主键属性
resultType:主键的数据类型
order:指定selectKey何时执行
或者用useGeneratedKeys为true,启动自增
用keyproperty指定接受的属性
select last_insert_id();
uuid();
Mybatis基本架构(面试时候让谈谈对Mybatis的理解的时候可以说这个)
- 核心配置文件
- 映射文件:一般一张表一个文件
- sqlsessionFactorybuilder
- sqlsessionFactory
- sqlsession(接口)真正干活的是执行器
- 执行器
- MapperStatement访问数据库,输入输出
dao包装:
传统:
- 接口
- 实现类
- 测试
动态代理包装:
只有接口,没有实现类
动态代理开发规则:
- namespace必须是接口的全路径名
- 接口方法名必须与接口id一致
- 接口入参必须与parameterType类型一致
- 接口的返回值必须与resultType类型一致
获取接口的代理实现类
sqlSession.getMapper(UserMapper.class)
属性加载
DTD模式对标签顺序有要求
properties标签
先加载内部标签,再加载外部文件,名称一致时,会替换内容
别名:
单个别名定义:别名的使用不区分大小写
<typeAlias type = "com.h2j.mybatis.pojo.user"
alias = "user"/>
别名包扫描:别名是类的全称,不区分大小写,推荐
<package name = "com.h2j.mybatis.pojo"
mapper:
传统方式只有一种方式:配mapper标签里的resource属性
映射文件:class扫描器
- 接口文件和映射文件在同一目录下
- 接口文件名称必须与映射文件的名称一致
映射文件包扫描:推荐
- 接口文件和映射文件在同一目录下
- 接口文件名称必须与映射文件的名称一致
包装的pojo
对象里包含了其他对象
vo:值对象
包装的pojo的应用场景:
淘宝商品里的名称,材质,供应商等信息会分成很多个表来保存
这时,如果要提交所有的数据,一个pojo是接收不了的。这时候就要用到包装的pojo
类里的属性名和数据表的字段名不一致的解决方案
- 改表,改pojo
- 为不一致的字段设别名
- resultMap
resultMap
- 用于映射主键
- 用于映射普通属性
resultMap用于处理字段名不一致时,一致的字段名可以不用配置,但是在配置关联查询时,所有的字段都要配置,不然没配置的字段会是null
动态sql
where
自动补全sql语句的where关键字,并且处理多余的and
用了where标签,就不能手动的加where关键字了
sql片段
抽取重复使用的sql片段
抽取:
使用:; refid:引用定义好的sql片段id
foreach循环标签
输入类型只有简单类型和对象类型两种,想要把list传入,就需要把它包装到pojo里
collection:要遍历的集合
open:循环开始之前输出的内容
item:设置循环变量
Seperate:分隔符
close:循环结束后输出的内容
<foreach collection = "ids" open = "id in(" item = "uId" seperate = "," close = ")">
#{uId}
</foreach>
得到了sql语句:id in(1, 25, 29, 30, 35)
trim
trim: 前缀"(",后缀")",分隔符","
帮助处理sql语句里多余的","
一对一关联
1. resultType
2. resultMap:
association用于配置一对一关系:
- property:order里的user属性
- javaType:user的数据类型,支持别名
一对多关联
1. resultType
2. resultMap:(推荐)
collection用于配置一对多关联:
- property:userorder里的orders属性
- ofType:orders属性的数据类型,支持别名