目录
操作前准备
创建实体类 Brand
准备测试用例
安装mybatisx插件
查询
查询所有数据
结果映射
实现查看详情逻辑功能
条件查询
多条件动态条件查询
单条件动态查询
添加
基本添加功能
主键返回
修改数据
修改全部字段
修改动态字段
删除数据
删除一个
批量删除
MyBatis参数封装
*单个参数
*多个参数
mapper接口文件中使用注解开发
操作前准备
mysql数据库中创建表
-- 删除tb_brand表
drop table if exists tb_brand;
-- 创建tb_brand表
create table tb_brand
(
-- id 主键
id int primary key auto_increment,
-- 品牌名称
brand_name varchar(20),
-- 企业名称
company_name varchar(20),
-- 排序字段
ordered int,
-- 描述信息
description varchar(100),
-- 状态:0:禁用 1:启用
status int
);
-- 添加数据
insert into tb_brand (brand_name, company_name, ordered, description, status)
values ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
('华为', '华为技术有限公司', 100, '华为致力于把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界', 1),
('小米', '小米科技有限公司', 50, 'are you ok', 1);
SELECT * FROM tb_brand;
创建实体类 Brand
package com.itheima.pojo;
/**
* 品牌
*
* alt + 鼠标左键:整列编辑
*
* 在实体类中,基本数据类型建议使用其对应的包装类型
*/
public class Brand {
// id 主键
private Integer id;
// 品牌名称
private String brandName;
// 企业名称
private String companyName;
// 排序字段
private Integer ordered;
// 描述信息
private String description;
// 状态:0:禁用 1:启用
private Integer status;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getBrandName() {
return brandName;
}
public void setBrandName(String brandName) {
this.brandName = brandName;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public Integer getOrdered() {
return ordered;
}
public void setOrdered(Integer ordered) {
this.ordered = ordered;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
@Override
public String toString() {
return "Brand{" +
"id=" + id +
", brandName='" + brandName + '\'' +
", companyName='" + companyName + '\'' +
", ordered=" + ordered +
", description='" + description + '\'' +
", status=" + status +
'}';
}
}
准备测试用例
安装mybatisx插件
安装之后可以看到mapper接口的sql映射文件互为跳转的对应文件
点击即可跳转
查询
查询所有数据
创建mapper接口
public List<Brand> selectAll();
创建sql映射文件
在BrandMapper接口中按alt+回车自动生成statement
再写上查询全部的sql
主程序入口测试代码编写
public static void main(String[] args) throws IOException {
//1. 获取SqlSessionFactory 注意此处的代码配置不需要记忆和理解,官方编写好直接复制使用即可
String resource = "mybatis-config.xml"; //写为mybatis-config.xml配置文件的的路径
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 获取Mapper接口的代理对象
BrandMapper brandmapper = sqlSession.getMapper(BrandMapper.class);
//4. 定义对象执行方法
List<Brand> brands = brandmapper.selectAll();
//4.打印输出查看
System.out.println(brands);
//5. 释放资源
sqlSession.close();
}
运行查看
结果映射
以上运行查询时发现brandName和companyName字段名称和实体类的属性名称不一样,则不能自动封装数据
解决操作方法:
1.在sql映射文件中查询字段时对不一样的字段内容使用别名的方式(缺点:每次查询都要定义别名)
查询查看发现数据成功自动封装显示
2.定义sql片段的方式(缺点:不灵活)
提前将查询的字段定义为sql片段,sql查询时使用include标签引入。
3.使用resultMap标签解决(最常用的方法)
其中子标签id表示完成对关键字段的映射,result表示完成一般字段的映射。
<mapper namespace="com.mybatis.mapper.BrandMapper"> <!-- 此处自定义命名空间 -->
<resultMap id="brandResultMap" type="com.mybatis.Brand">
<result column="brand_name" property="brandName"/>
<result column="company_name" property="companyName"/>
</resultMap>
<select id="selectAll" resultMap="brandResultMap">
select * from tb_brand;
</select>
</mapper>
运行查看:
实现查看详情逻辑功能
编写mapper方法
public List<Brand> selectAllById(int id);
alt+回车在sql映射文件中生成statement,然后编写sql
<!-- 根据id查信息 -->
<select id="selectAllById" resultMap="brandResultMap">
select * from tb_brand where id = #{id};
</select>
注意:
1.传参占位符有#{ } 和 ${ }这两种。其中#{ }是以替换为?的的方式,${ }是以拼接的方式。
两者相比#{ }的优势在于能防止sql注入
2.特殊字符的处理 如where条件中出现 < 的条件则不能使用,因为sql映射文件中是是以xml文件的形式编写,而 < 会被当做标签开始符,所以提供的解决方法为:
(1)转义字符:如 < 的转义字符为< 可以直接写上代替为 < 符号
(2)CDATA区:在文件中输入CD自动提示出CDATA区,在里面写需要的符号即可
主程序入口测试代码编写
public static void main(String[] args) throws IOException {
//定义模拟接收参数
int id = 1;
//1. 获取SqlSessionFactory 注意此处的代码配置不需要记忆和理解,官方编写好直接复制使用即可
String resource = "mybatis-config.xml"; //写为mybatis-config.xml配置文件的的路径
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 获取Mapper接口的代理对象
BrandMapper brandmapper = sqlSession.getMapper(BrandMapper.class);
//4. 定义对象执行方法
List<Brand> brands = brandmapper.selectAllById(id);
//4.打印输出查看
System.out.println(brands);
//5. 释放资源
sqlSession.close();
}
运行查看
条件查询
SQL 语句设置多个参数的三种方式
1.散装参数:需要使用 @Param (" SQL 中的参数占位符名称")
List<Brand> selectByCondition(@Param("status") int status, @Param("companyName") String companyName, @Param("brandName") String brandName);
2.实体类封装参数:只需要保证 SQL 中的参数名和实体类属性名对应上,即可设置成功
//mapper接口的抽象方法
List<Brand> selectByCondition(Brand brand);
//测试主程序的代码
//接收参数
int status = 1;
String companyName = "华为";
String brandName = "华为";
// 处理参数
companyName = "%" + companyName + "%";
brandName = "%" + brandName + "%";
//封装对象
Brand brand = new Brand();
brand.setStatus(status);
brand.setCompanyName(companyName);
brand.setBrandName(brandName);
//把对象传入方法
List<Brand> brands = brandMapper.selectByCondition(brand);
3.map 集合:只需要保证 SQL 中的参数名和 map 集合的键的名称对应上,即可设置成功
//mapper接口的抽象方法
List<Brand> selectByConditionSingle(Brand brand);
//测试主程序的代码
//接收参数
int status = 1;
String companyName = "华为";
String brandName = "华为";
// 处理参数
companyName = "%" + companyName + "%";
brandName = "%" + brandName + "%";
//定义map对象
Map map = new HashMap();
map.put("status" , status);
map.put("companyName", companyName);
map.put("brandName" , brandName);
//将map对象传入方法
List<Brand> brands = brandMapper.selectByCondition(map);
在sql映射文件中编写好sql
<!-- 条件查询 -->
<select id="selectByCondition" resultMap="brandResultMap">
select * from tb_brand
where status = #{status} and
company_name like #{companyName} and
brand_name like #{brandName}
</select>
在mapper接口文件中写上对应的方法
public List<Brand> selectByCondition(@Param("status") int status, @Param("companyName") String companyName, @Param("brandName") String brandName);
主程序入口测试代码编写
public static void main(String[] args) throws IOException {
//定义模拟接收参数
int status = 1;
String companyName= "华为";
String brandName = "华为";
//处理参数 因为输入是关键词 sql中写的是like模糊查询 所以需要处理赋值为模糊查询的形式
companyName = "%" + companyName + "%";
brandName = "%" + brandName + "%";
//1. 获取SqlSessionFactory 注意此处的代码配置不需要记忆和理解,官方编写好直接复制使用即可
String resource = "mybatis-config.xml"; //写为mybatis-config.xml配置文件的的路径
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 获取Mapper接口的代理对象
BrandMapper brandmapper = sqlSession.getMapper(BrandMapper.class);
//4. 定义对象执行方法
List<Brand> brands = brandmapper.selectByCondition(status, companyName, brandName);
//4.打印输出查看
System.out.println(brands);
//5. 释放资源
sqlSession.close();
}
运行查看
多条件动态条件查询
SQL语句会随着用户的输入或外部条件的变化而变化,我们称为动态SQL
MyBatis 对动态SQL有很强大的支撑有如下标签:
if
choose (when, otherwise)
trim (where, set)
foreach
在sql映射文件中通过if标签完成动态sql的编写
<!-- 完成动态条件查询 -->
<select id="selectByCondition" resultMap="brandResultMap">
select * from tb_brand
where
<if test="status != null">
status = #{status}
</if>
<if test="companyName != null and companyName != '' ">
and company_name like #{companyName}
</if>
<if test="brandName != null and brandName != '' ">
and brand_name like #{brandName}
</if>
</select>
先输入三种参数条件存在运行查看结果
如果用户只输入status状态参数其他字段参数不输入,查看结果发现满足status条件的都会被查询出来
但是这样写会有个bug,如果不输入status参数只输入后面的参数sql语法不正确会报错
解决方法1:前面新写一个恒等式条件,这样无论输哪个条件都能成功拼接匹配上
解决方法2:替换where关键字,将where关键字换成where标签并把条件sql包裹住
单条件动态查询
从多个条件中选择一个:choose (when, otherwise) 选择,类似于Java 中的switch语句
在mapper接口文件中新建一个单条件方法
public List<Brand> selectByConditionSingle(Brand brand);
选中alt + 回车 在sql映射文件中生成对应的statement并编写动态sql
<!-- 单条件动态查询 -->
<select id="selectByConditionSingle" resultMap="brandResultMap">
select * from tb_brand
where
<choose> <!-- 相当于switch -->
<when test="status != null">
status = #{status}
</when>
<when test="companyName != null and companyName != '' ">
company_name like #{companyName}
</when>
<when test="brandName != null and brandName != '' ">
brand_name like #{brandName}
</when>
</choose>
</select>
主程序入口测试代码编写
public static void main(String[] args) throws IOException {
//定义模拟接收参数
int status = 1;
String companyName= "华为";
String brandName = "";
//处理参数 因为输入是关键词 sql中写的是like模糊查询 所以需要处理赋值为模糊查询的形式
companyName = "%" + companyName + "%";
brandName = "%" + brandName + "%";
//封装对象·
Brand brand = new Brand();
brand.setStatus(status);
//brand.setCompanyName(companyName); 用户单条件只传入一个参数
//brand.setBrandName(brandName);
//1. 获取SqlSessionFactory 注意此处的代码配置不需要记忆和理解,官方编写好直接复制使用即可
String resource = "mybatis-config.xml"; //写为mybatis-config.xml配置文件的的路径
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 获取Mapper接口的代理对象
BrandMapper brandmapper = sqlSession.getMapper(BrandMapper.class);
//4. 定义对象执行方法
List<Brand> brands = brandmapper.selectByConditionSingle(brand);
//4.打印输出查看
System.out.println(brands);
//5. 释放资源
sqlSession.close();
}
运行查看
这样写还是有个bug因为如果用户什么参数都不传入那么sql语句格式错误就会报错
解决方法1:加上一个otherwise标签里面为保底条件,如果什么都不传入那么就执行otherwise标签内的内容。
解决方法2:替换where关键字,将where关键字换成where标签并把条件sql包裹住
把所有参数注释掉不传入参数运行查看
添加
基本添加功能
添加除了id关键字段以外的所有数据
在mapper接口文件中新建一个添加方法
选中alt + 回车 在sql映射文件中生成对应的statement并编写动态sql
<!-- 基本添加 -->
<insert id="add">
insert into tb_brand (brand_name,company_name,ordered,description,status)
values (#{brandName},#{companyName},#{ordered},#{descriptio},#{status})
</insert>
主程序入口测试代码编写
public static void main(String[] args) throws IOException {
//定义模拟接收参数
int status = 1;
String companyName= "菠萝手机";
String brandName = "菠萝手机科技有限公司";
String description ="美国有苹果,中国有菠萝! 菠萝手机~";
int ordered = 100;
//封装对象·
Brand brand = new Brand();
brand.setStatus(status);
brand.setCompanyName(companyName);
brand.setBrandName(brandName);
brand.setDescription(description);
brand.setOrdered(ordered);
//1. 获取SqlSessionFactory 注意此处的代码配置不需要记忆和理解,官方编写好直接复制使用即可
String resource = "mybatis-config.xml"; //写为mybatis-config.xml配置文件的的路径
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 获取Mapper接口的代理对象
BrandMapper brandmapper = sqlSession.getMapper(BrandMapper.class);
//4.使用添加方法
brandmapper.add(brand);
//5. 定义对象查询全部数据
List<Brand> brands = brandmapper.selectAll();
//6.打印输出查看
System.out.println(brands);
//7. 释放资源
sqlSession.close();
}
运行查看数据已显示但是还没有添加到数据库中
这里就需要使用mybatis的事务功能
方法1:openSession() 默认开启事务,进行增删改操作后需要使用sqlSession.commit();来手动提交事
方法2:openSession(true) 可以设置为自动提交事务(关闭事务)
运行之后发现数据已经添加到了数据库中
主键返回
在数据添加成功后,需要获取插入数据库数据的主键的值
比如:添加订单和订单项
1.添加订单
2.添加订单项,订单项中需要设置所属订单的id
在sql映射文件中 useGeneratedKeys设置为true,keyProperty设置成主键关键字
<!-- 主键返回 -->
<insert id="add" useGeneratedKeys="true" keyProperty="id">
insert into tb_brand (brand_name,company_name,ordered,description,status)
values (#{brandName},#{companyName},#{ordered},#{description},#{status})
</insert>
然后运行主程序入口测试代码查看到id主键全都可以获取返回出来
修改数据
修改全部字段
在mapper接口文件中定义修改抽象方法(一般返回结果为void,但也可以返回int查看影响行数)
int updata(Brand brand);
选中alt + 回车 在sql映射文件中生成对应的statement并编写sql
<!-- 全部修改 -->
<update id="updata">
update tb_brand
set brand_name = #{brandName},
company_name = #{companyName},
ordered = #{ordered},
description = #{description},
status = #{status}
where id = #{id}
</update>
主程序入口测试代码编写
public static void main(String[] args) throws IOException {
//定义模拟接收参数
//要修改的内容
int status = 0;
String companyName= "老八手机";
String brandName = "老八手机科技有限公司";
String description ="奥利给了 老铁们";
int ordered = 666;
int id = 6; //设置要修改数据的id
//封装对象·
Brand brand = new Brand();
brand.setStatus(status);
brand.setCompanyName(companyName);
brand.setBrandName(brandName);
brand.setDescription(description);
brand.setOrdered(ordered);
brand.setId(id);
//1. 获取SqlSessionFactory 注意此处的代码配置不需要记忆和理解,官方编写好直接复制使用即可
String resource = "mybatis-config.xml"; //写为mybatis-config.xml配置文件的的路径
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 获取Mapper接口的代理对象
BrandMapper brandmapper = sqlSession.getMapper(BrandMapper.class);
//4.使用修改方法
int count = brandmapper.updata(brand);
System.out.println("受影响的行数:"+count);
//5.手动提交事务
sqlSession.commit();
//6. 定义对象查询全部数据
List<Brand> brands = brandmapper.selectAll();
//7.打印输出查看
System.out.println(brands);
//8. 释放资源
sqlSession.close();
}
运行查看
修改动态字段
不修改完全部数据,只修改部分数据
修改sql映射文件中编写动态条件sql
<!-- 动态修改 -->
<update id="updata">
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>
主程序入口测试代码编写
public static void main(String[] args) throws IOException {
//定义模拟接收参数
//要修改的内容
int status = 0;
String companyName= "老6手机";
String brandName = "老6手机科技有限公司";
String description ="大家好 我是老6~";
int ordered = 666;
int id = 6; //设置要修改数据的id
//封装对象·
Brand brand = new Brand();
//brand.setStatus(status); //注释掉只修改部分数据
brand.setCompanyName(companyName);
brand.setBrandName(brandName);
brand.setDescription(description);
//brand.setOrdered(ordered);
brand.setId(id);
//1. 获取SqlSessionFactory 注意此处的代码配置不需要记忆和理解,官方编写好直接复制使用即可
String resource = "mybatis-config.xml"; //写为mybatis-config.xml配置文件的的路径
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 获取Mapper接口的代理对象
BrandMapper brandmapper = sqlSession.getMapper(BrandMapper.class);
//4.使用修改方法
int count = brandmapper.updata(brand);
System.out.println("受影响的行数:"+count);
//5.手动提交事务
sqlSession.commit();
//6. 定义对象查询全部数据
List<Brand> brands = brandmapper.selectAll();
//7.打印输出查看
System.out.println(brands);
//8. 释放资源
sqlSession.close();
}
运行查看 只修改了3个字段的数据
删除数据
删除一个
在mapper接口文件中定义修改抽象方法
void deleteByIdAfter(int id);
选中alt + 回车 在sql映射文件中生成对应的statement并编写sql
<!-- 删除数据 -->
<delete id="deleteByIdAfter">
delete from tb_brand where id = #{id}
</delete>
主程序入口测试代码编写
public static void main(String[] args) throws IOException {
//定义模拟接收参数
int id = 6;
//1. 获取SqlSessionFactory 注意此处的代码配置不需要记忆和理解,官方编写好直接复制使用即可
String resource = "mybatis-config.xml"; //写为mybatis-config.xml配置文件的的路径
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 获取Mapper接口的代理对象
BrandMapper brandmapper = sqlSession.getMapper(BrandMapper.class);
//4.使用删除方法
brandmapper.deleteByIdAfter(id);
//5.手动提交事务
sqlSession.commit();
//6. 定义对象查询全部数据
List<Brand> brands = brandmapper.selectAll();
//7.打印输出查看
System.out.println(brands);
//8. 释放资源
sqlSession.close();
}
运行查看id为6的记录已被删除
批量删除
在mapper接口文件中定义修改抽象方法
void deleteByIds(@Param("ids") int[] ids); //内部传入数组
选中alt + 回车 在sql映射文件中生成对应的statement并编写sql
内置了foreach标签 collection参数为需要传入的数组
方式1:mybatis会将数组参数,封装为一个Hap集合 默认键为array 值为数组,collection直接写array
方式2:也可以使用@Param注解改变map集合的默认key的名称,collection传入自定义名称
separator参数为分隔符,sql条件中已逗号分隔
open参数为遍历之前在前面拼接什么符号,close为遍历之后拼接什么符号
<delete id="deleteByIds">
delete from tb_brand
where id in (
<foreach collection="ids" item="id" separator=","> <!--mybatis会将数组参数,封装为一个Hap集合 默认键为array 值为数组-->
#{id}
</foreach>
)
</delete>
主程序入口测试代码编写
public static void main(String[] args) throws IOException {
//定义模拟接收参数
int[] ids = {1, 2, 3};
//1. 获取SqlSessionFactory 注意此处的代码配置不需要记忆和理解,官方编写好直接复制使用即可
String resource = "mybatis-config.xml"; //写为mybatis-config.xml配置文件的的路径
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 获取Mapper接口的代理对象
BrandMapper brandmapper = sqlSession.getMapper(BrandMapper.class);
//4.使用删除方法
brandmapper.deleteByIds(ids);
//5.手动提交事务
sqlSession.commit();
//6. 定义对象查询全部数据
List<Brand> brands = brandmapper.selectAll();
//7.打印输出查看
System.out.println(brands);
//8. 释放资源
sqlSession.close();
}
运行查看表中的记录全部删除
MyBatis参数封装
建议:都使用@Param注解来修改Map集合中默认的键名、并使用修改后的名称来获取值,这样可读性更高!
*单个参数
1.POJ0类型:直接使用,属性名和参数占位符名称一致
2. Map集合:直接使用,键名和参数占位符名称一致
3. Collection:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名
map.put( "arg0" , collection集合);
map .put( "collection " , collection集合);
4. List:封装为Map集合,可以使用@Param注解,替换ap集合中默认的arg键名
map. put( "arg0" , list集合);
map .put( "collection" ,ist集合);map .put( "list",list集合);
5. Array:封装为Map集合
map .put( "arg0",数组);map .put ( "array ",数组);
6.其他类型:直接使用
*多个参数
封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名
map.put( "arg0",参数值1)
map.put( "param1",参数值1)
map.put( "param2",参数值2)
map .put( "agr1",参数值2)
-—-—--------——-@Param ( "username")
map.put( "username " ,参数值1)
map . put("param1",参数值1)
map.put( " param2",参数值2)
map. put( "agr1",参数值2)
mapper接口文件中使用注解开发
使用注解比写sql的xml映射文件还会方便许多(注解完成简单功能,配置文件完成复杂功能)
查询:@Select
添加: @Insert
修改:@Update
删除:@Delete
示例:
在sql映射文件中将selectAll方法对应的statement注释掉
在mapper接口文件中对selectAll方法添加上@Select注解,并写上查询全部的sql
运行主程序入口测试代码
运行查看已查询到全部数据