简介
什么是MyBatis?
- MyBatis是一款优秀的持久层框架,用于简化JDBC开发
- 持久层:
- 负责将数据到保存到数据库的那一层代码
- JavaEE三层架构:表现层、业务层、持久层
- 框架
- 框架就是一个半成品软件,是一套可重用的、通用的、软件基础代码模型
- 在框架的基础之上构建软件编写更加高效、规范、通用、可扩展
MyBatis快速入门
- 创建user表,添加数据(Mysql)
- 创建模块,导入坐标(Maven依赖)
- 编写MyBatis核心配置文件(服务器连接信息,SQL映射文件)
- 编写SQL映射文件(SQL语句)
- 编码
- 定义POJO类
- 加载核心配置文件
- 获取sqlSession对象,执行SQL语句
- 释放资源
Mapper代理开发
使用Mapper代理方式步骤:
- 定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同意目录下
- 设置SQL映射文件的namespace属性为Mapper接口全限定名
- 在Mapper接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致
- 编码
- 通过sqlSession的getMapper方法获取Mapper接口的代理对象
- 调用对应方法完成sql的执行
细节:如果Mapper接口名称和sql映射文件名称相同,并在同一目录下,则可以使用包扫描的方式简化SQL映射文件的加载
<mappers>
<!--包扫描-->
<package name="com.itheima.Mapper"/>
</mappers>
Mybatis核心配置文件
配置标签的顺序顺序必须按照这个顺序来配置
<environments default="development">
可以配置多个environment通过default来切换
类型别名:包搜索方式,减少全限定类名书写,可以直接写类名且不区分大小写
<typeAliases>
<package name="com.itheima.pojo"/>
</typeAliases>
Mybatis实现增删改查
查询
查询-查询所有数据
- 编写接口方法:Mapper接口
- 参数:无
- 结果:List
- 编写SQL语句:sql映射文件
select * from tb_brand - 执行方法,测试
Mybatis无法自动封装数据
原因:数据库表的字段名称和实体类的属性名称不一样,则不能自动封装数据
解决办法:
1.起别名
company_name as companyName
2.sql片段
<sql id="brandcol">
id,brand_name as brandName,company_name,ordered
</sql>
...
select <include refid="brandcol"></include> from tb_brand
3.resultMap
3.1 定义标签
3.2 在select标签中使用resultMap替换resultType
<resultMap id="brandResultMap" type="brand">
<!-- id :完成主键字段的映射
result:完成一般字段的映射
column:表的列名
property:实体类的属性名
-->
<result column="brand_name" property="brandName"/>
<result column="company_name" property="companyName"/>
</resultMap>
...
<select id="selectAll" resultMap="brandResultMap">
select * from tb_brand
</select>
查询-查询详情
- 编写接口方法:Mapper接口
- 参数:id
- 结果:Brand
- 编写SQL语句:SQL映射文件
select * from tb_brand where id = #{id} - 执行方法,测试
一个参数-参数占位符
- 参数占位符
#{}:执行SQL时,会将#{}占位符替换为?,将来自动设置参数值${}:拼SQL,会存在SQL注入问题- 使用时机:
- 传递参数,都使用
#{} - 如果要对表名、列名进行动态设置,只能使用
${}进行sql拼接
- 传递参数,都使用
- parameterType:
- 用于设置参数类型
- SQL语句中特殊字符处理:
- 转义字符 例如:
< - CDATA区
- 转义字符 例如:
查询-多条件查询
- 编写接口方法:Mapper接口
- 参数:所有查询条件
- 结果:
List<brand>
List<Brand> selectByCondition(@Param("status") int status,@Param("brandName") String brandName,@Param("companyName") String companyName);
List<Brand> selectByCondition(Brand brand);
List<Brand> selectByCondition(Map map);
- 编写SQL语句:SQL映射文件
<select id="selectByCondition" resultMap="brandResultMap">
select * from tb_brand
where
status = #{status}
and brand_name like #{brandName}
and company_name like #{companyName}
</select>
- 执行方法,测试
SQL语句设置多个参数
- 散装参数:需要使用
@param("SQL中的参数占位符名称" 参数类型 参数名称) - 实体类封装参数:只需要保证SQL中的参数名和实体类属性名对应上,即可设置成功
- Map集合:只需要保证SQL中参数名和map集合到的键的名称对应上,即可设置成功
查询-多条件-动态条件查询
SQL会随着用户的输入或外部条件的变化而变化,我们称为动态SQL
<select id="selectByCondition" resultMap="brandResultMap">
select *
from tb_brand
<where>
<if test="status != null">
status = #{status}
</if>
<if test="brandName != null and brandName != ''">
and brand_name like #{brandName}
</if>
<if test="companyName != null and companyName != ''">
and company_name like #{companyName}
</if>
</where>
</select>
动态SQL
if:用于判断参数是否有值,使用test属性进行条件判断
存在的问题:第一个条件不需要逻辑运算符
解决方案:
- 使用恒等式让所有条件格式都一样
- 标签替换where关键字
查询-单条件-动态查询
从多个条件中选择一个
choose(when, otherwise):选择,类似于Java中的switch语句
<select id="selectByConditionSingle" resultMap="brandResultMap">
select
* from tb_brand
<where>
<choose>
<when test="status != null">
status = #{status}
</when>
<when test="brandName != null and brandName != ''">
brand_name like #{brandName}
</when>
<when test="companyName != null and companyName != ''">
company_name like #{companyName}
</when>
</choose>
</where>
</select>
添加
添加步骤
- 编写接口方法:Mapper接口
void add(Brand brand)- 参数:除了id之外的所有数据
- 结果:void
- 编写SQL语句:SQL映射文件
<insert id="add">
insert into tb_brand(brand_name, company_name, ordered, description, status)
VALUES (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status})
</insert>
- 执行方法,测试
Mybatis事务
openSession():默认开启事务,进行增删改操作后需要使用sqlSession.commit();手动提交事务openSession(true):可以设置为自动提交事务(关闭事务)
主键返回
在数据添加成功后,需要获取插入数据库数据的主键的值
比如:添加订单和订单项
- 添加订单
- 添加订单项,订单项中需要设置所属订单的id
返回添加数据的主键
<insert useGeneratedKays = "true" keyProperty = "id">
修改
修改步骤
- 编写接口方法:Mapper接口
- 参数:所有数据
- 结果:void 或 int
int update(Brand brand) - 编写SQL语句:SQL映射文件
<update id="update">
update tb_brand
set brand_name = #{brandName},
company_name = #{companyName},
ordered = #{ordered},
description = #{description},
status = #{status}
where id = #{id};
</update>
- 执行方法,测试
修改-修改动态字段
使用set标签和if标签
<update id="update">
update tb_brand
<set>
<if test="brandName != null and brandName != ''">
brand_name = #{brandName},
</if>
<if test="companyName != null and companyName != ''">
company_name = #{companyName},
</if>
<if test="ordered != null">
ordered = #{ordered},
</if>
<if test="description != null and description != ''">
description = #{description},
</if>
<if test="status != null">
status = #{status}
</if>
</set>
where id = #{id};
</update>
删除
删除一个
- 编写接口方法:Mapper接口
- 参数:id
- 结果:void
void deleteById(int id)
- 编写SQL语句:SQL映射文件
<delete id="deleteById">
delete
from tb_brand
where id = #{id};
</delete>
- 执行方法,测试
批量删除
- 编写接口方法:Mapper接口
- 参数:id数组
- 结果 void
void deleteById(@param("ids")int[] ids); - 编写SQL语句:SQL映射文件
<delete id="deleteByIds">
delete
from tb_brand
where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
;
</delete>
- 执行方法,测试
Mybatis完成操作需要几步?
三步:
- 编写接口方法
- 编写SQL
- 执行方法
参数传递
MyBatis提供了 ParamNameResolver 类来进行参数封装
单个参数
- POJO类型:直接使用,实体类属性名和参数占位符名称一致
- Map集合:直接使用,键名和参数占位符名称一致
- Collection:封装为Map集合
map.put("collection",collection集合)
map.put("arg0",collection集合)
- List:封装为Map集合
map.put("collection",List集合)
map.put("list",List集合)
map.put("arg0",List集合)
- Array:封装为Map集合
map.put("array",数组)
map.put("arg0",数组)
- 其他类型:直接使用
多个参数:封装为Map集合
map.put("arg0",参数值1)
map.put("param1",参数值1)
map.put("arg1",参数值2)
map.put("param2",参数值2)
建议:将来都使用@Param注解来修改Map集合中默认的键名,并使用修改后的名称来获取值,这样可读性更高!
修改的是arg0
注解完成增删改查
使用注解开发会比配置文件开发更加方便
@Select("select * from tb_brand;")
List<Brand> selectAll();
查询:@Select
添加:@Insert
修改:@Update
删除:@Delete
提示:
- 注解完成简单功能
- 配置文件完成复杂功能