文章目录
- 前言
- 五、配置文件完成增删改查
- 1.学习目标
- 2.入门案例环境准备
- 3.查询–查询所有
- 4.查询–根据id查询
- 5. 查询–条件查询
- 6.查询–多条件动态查询
- 7.条件查询–单条件动态查询
- 8.添加(增)
- 9.修改–改所有参数
- 10.修改–动态修改
- 11.删除–删除单条记录
- 12.删除–删除多条记录
- 13.mybatis注解开发
- 总结
前言
为了巩固所学的知识,作者尝试着开始发布一些学习笔记类的博客,方便日后回顾。当然,如果能帮到一些萌新进行新技术的学习那也是极好的。作者菜菜一枚,文章中如果有记录错误,欢迎读者朋友们批评指正。
(博客的参考源码可以在我主页的资源里找到,如果在学习的过程中有什么疑问欢迎大家在评论区向我提出)
五、配置文件完成增删改查
1.学习目标
2.入门案例环境准备
(详细代码可以在作者主页的mybatisy源码re_crud_demo模块里找到)
- 在数据库创建实体类表tb_brand
- 代码
-- 删除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),-- 排序字段orderedint,-- 描述信息descriptionvarchar(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 org.example.pojo;//此处省略getter、setter和toString方法public class Brand {// id 主键private Integer id;// 品牌名称private String brandName;// 企业名称private String companyName;// 排序字段private Integer ordered;// 描述信息private String description;// 状态:0:禁用1:启用private Integer status;
- 在test包下的test文件下创建测试样例MybatisTest
- 安装MybatisX插件
- 文件结构预览
3.查询–查询所有
- 操作步骤
- 编写接口方法:Mapper接口
public interface BrandMapper {/** * 查询所有 */List<Brand> selectAll();}
- 编写SQL语句:SQL映射文件
<" />="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace:名称空间--><mapper namespace="org.example.mapper.BrandMapper"><select id="selectAll" resultMap="brandResultMap">select *from tb_brand;</select></mapper>
- 编写测试样例
public class MyBatisTest {@Testpublic void testSelectAll() throws IOException {//1. 获取SqlSessionFactoryString resource = "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();System.out.println(brands);//5. 释放资源sqlSession.close();}}
- 运行结果
- 小结
- 问题
- 问题描述: 查询出来的brandName和companyName为空
- 原因: 数据库表的字段名称 和 实体类的属性名称 不一样,则不能自动封装数据
(实体类属性名)
(数据库名称)
解决方案一
起别名:对不一样的列名起别名,让别名和实体类的属性名一样 * 缺点:每次查询都要定义一次别名 * sql片段* 缺点:不灵活
(sql片段):
<!--sql片段--><sql id="brand_column"> id, brand_name as brandName, company_name as companyName, ordered, description, status </sql> <select id="selectAll" resultType="brand"> select <include refid="brand_column" /> from tb_brand; </select>
运行结果:
解决方案二:resultMap
resultMap: 1. 定义标签 2. 在标签中,使用resultMap属性替换 resultType属性
对应的xml配置文件:
<" />="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace:名称空间--><mapper namespace="org.example.mapper.BrandMapper"><!--id属性 ,resultMap标签的标识。--><!--type属性 ,返回值的全限定类名,或类型别名。--><resultMap id="brandResultMap" type="brand"><!--id:完成主键字段的映射column:表的列名property:实体类的属性名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>
运行结果:
4.查询–根据id查询
- 操作步骤
2. 编写接口方法:Mapper接口
package org.example.mapper;import org.example.pojo.Brand;import java.util.List;public interface BrandMapper {/** * 查询所有 */List<Brand> selectAll();/** * 查看详情:根据Id查询 */Brand selectById(int id);}package org.example.mapper;import org.example.pojo.Brand;import java.util.List;public interface BrandMapper {/** * 查看详情:根据Id查询 */Brand selectById(int id);}
- 编写SQL语句:SQL映射文件
<" />="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace:名称空间--><mapper namespace="org.example.mapper.BrandMapper"><resultMap id="brandResultMap" type="brand"><result column="brand_name" property="brandName"/><result column="company_name" property="companyName"/></resultMap><select id="selectById" resultMap="brandResultMap">select *from tb_brand where id = #{id};</select></mapper>
- 编写测试样例
public class MyBatisTest {@Testpublic void testSelectById() throws IOException {//接收参数int id = 1;//1. 获取SqlSessionFactoryString resource = "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. 执行方法Brand brand = brandMapper.selectById(id);System.out.println(brand);//5. 释放资源sqlSession.close();}}
- 运行结果
- BrandMapper.xml中的sql语句的参数占位符
1. #{}:会将其替换为 " /> 2. ${}:拼sql。会存在SQL注入问题
3. 使用时机:* 参数传递的时候:#{}* 表名或者列名不固定的情况下:${} 会存在SQL注入问题
- BrandMapper.xml配置文件中sql语句select标签中的参数类型
* 参数类型:parameterType:可以省略
- sql语句中的特殊字符处理
* 特殊字符处理:1. 转义字符:
2. CDATA区:
5. 查询–条件查询
- 操作步骤
- 编写接口方法:Mapper接口
public interface BrandMapper {/** * 条件查询 ** 参数接收 *1. 散装参数:如果方法中有多个参数,需要使用@Param("SQL参数占位符名称") *2. 对象参数:对象的属性名称要和参数占位符名称一致 *3. map集合参数:map集合的键值要和参数占位符名称一致 * */ //方式一:接收散装参数List<Brand> selectByCondition(@Param("status") int status, @Param("companyName") String companyName, @Param("brandName") String brandName);//放肆二:接收对象参数//List selectByCondition(Brand brand);//方式三:接收map集合参数//List selectByCondition(Map map);}
- 编写SQL语句:SQL映射文件
<" />="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace:名称空间--><mapper namespace="org.example.mapper.BrandMapper"><resultMap id="brandResultMap" type="brand"><result column="brand_name" property="brandName"/><result column="company_name" property="companyName"/></resultMap><!--条件查询--><select id="selectByCondition" resultMap="brandResultMap">select *from tb_brandwhere status = #{status}and company_name like #{companyName}and brand_name like #{brandName}</select></mapper>
- 编写测试样例
public class MyBatisTest {@Testpublic void testSelectByCondition() throws IOException {//方式一: 接收散装参数//接收参数int status = 1;String companyName = "华为";String brandName = "华为";// 处理参数companyName = "%" + companyName + "%";brandName = "%" + brandName + "%";//方式二:接收对象参数//封装对象//Brand brand = new Brand();//brand.setStatus(status);//brand.setCompanyName(companyName);//brand.setBrandName(brandName);//方式三:接收散装参数//Map map = new HashMap();//map.put("status" , status);//map.put("companyName", companyName);//map.put("brandName" , brandName);//1. 获取SqlSessionFactoryString resource = "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);//方式二:接收对象参数//List brands = brandMapper.selectByCondition(brand);//方式三:接收集合参数//List brands = brandMapper.selectByCondition(map);System.out.println(brands);//5. 释放资源sqlSession.close();}}
- 运行结果
- 小结
6.查询–多条件动态查询
(在多条件查询的基础上修改BrandMapper.xml中的SQL语句的书写部分)
- 情景导入
在多条件查询的基础案例中我们发现,查询多条件的sql语句需要获取当前状态status,企业名称companyname,品牌名称brandname三个参数,缺一不可。如果只输入品牌名称,该查询无法完成,不符合实际需求,报错实例(在传参代码书写时将status和companyname的部分注释掉)如下:
因此,我们需要动态SQL来辅助我们解决类似的问题。动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
- 操作步骤
- 编写SQL语句:SQL映射文件
<select id="selectByCondition" resultMap="brandResultMap">select *from tb_brandwhere<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>
- 编写测试样例
- 运行结果
- 存在问题
当我们把where后面的第一个参数也注释掉我们发现程序就会报错,原因查看运行结果中的sql语句就一目了然了,如下:
(sql语句)
(测试样例)
(运行结果)
- 改进方式一
(sql语句书写改进)
(运行结果)
- 改进方式二
(sql语句书写改进)
(运行结果)
- 小结
7.条件查询–单条件动态查询
- 操作步骤
- 编写接口方法:Mapper接口
List<Brand> selectByConditionSingle(Brand brand);
- 编写SQL语句:SQL映射文件(注意区分,没用and连接)
otherwrise:不传参搜索的情况,相当于switch语句中的default
<select id="selectByConditionSingle" resultType="org.example.pojo.Brand">select *from tb_brand<where><choose><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><otherwise>1 = 1</otherwise></choose></where></select>
- 编写测试样例
@Testpublic void testSelectByConditionSingle() throws IOException {//接收参数int status = 1;String companyName = "华为";String brandName = "华为";// 处理参数companyName = "%" + companyName + "%";brandName = "%" + brandName + "%";//封装对象Brand brand = new Brand();//brand.setStatus(status);brand.setCompanyName(companyName);//brand.setBrandName(brandName);//1. 获取SqlSessionFactoryString resource = "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);System.out.println(brands);//5. 释放资源sqlSession.close();}}
- 运行结果
8.添加(增)
- 操作步骤
- 编写接口方法:Mapper接口
/** * 添加 */void add(Brand brand);
- 编写SQL语句:SQL映射文件
<insert id="add">insert into tb_brand (brand_name, company_name, ordered, description, status)values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});</insert>
- 编写测试样例
(默认需要手动提交事务: sqlSession.commit();)
@Testpublic void testAdd() 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. 获取SqlSessionFactoryString resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象SqlSession sqlSession = sqlSessionFactory.openSession();//SqlSession sqlSession = sqlSessionFactory.openSession(true);//3. 获取Mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);//4. 执行方法brandMapper.add(brand);//提交事务sqlSession.commit();//5. 释放资源sqlSession.close();}
- 运行结果
- 添加–主键返回
(无法通过brand对象直接获取id值)
- 获取brand对象的id
9.修改–改所有参数
- 操作步骤
- 编写接口方法:Mapper接口
/** * 修改 */int update(Brand brand);
- 编写SQL语句:SQL映射文件
<update id="update">update tb_brandset brand_name = #{brandName},company_name = #{companyName},ordered = #{ordered},description = #{description},status = #{status}where id = #{id};</update>
- 编写测试样例
@Testpublic void testUpdate() throws IOException {//接收参数int status = 0;String companyName = "波导手机";String brandName = "波导";String description = "波导手机,手机中的战斗机666";int ordered = 200;int id = 4;//封装对象Brand brand = new Brand();brand.setStatus(status);brand.setCompanyName(companyName);brand.setBrandName(brandName);brand.setDescription(description);brand.setOrdered(ordered);brand.setId(id);//1. 获取SqlSessionFactoryString resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象SqlSession sqlSession = sqlSessionFactory.openSession();//SqlSession sqlSession = sqlSessionFactory.openSession(true);//3. 获取Mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);//4. 执行方法int count = brandMapper.update(brand);System.out.println(count);//提交事务sqlSession.commit();//5. 释放资源sqlSession.close();}
- 运行结果
10.修改–动态修改
- 操作步骤
(在修改的代码基础的基础上编码)
如果只传了密码,其他值不传,执行完其他值会变成null,这时需要动态字段解决该类问题
- 编写SQL语句:SQL映射文件
<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>
- 编写测试样例
- 运行结果
11.删除–删除单条记录
- 操作步骤
- 编写接口方法:Mapper接口
/** * 根据id删除 */void deleteById(int id);
- 编写SQL语句:SQL映射文件
<delete id="deleteById">delete from tb_brand where id = #{id};</delete>
- 编写测试样例
@Testpublic void testDeleteByIds() throws IOException {//接收参数int id = 4;//1. 获取SqlSessionFactoryString resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象SqlSession sqlSession = sqlSessionFactory.openSession();//SqlSession sqlSession = sqlSessionFactory.openSession(true);//3. 获取Mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);//4. 执行方法brandMapper.deleteById(id);//提交事务sqlSession.commit();//5. 释放资源sqlSession.close();}
- 运行结果
12.删除–删除多条记录
- 操作步骤
2. 编写接口方法:Mapper接口
/** * 批量删除 */void deleteByIds(int[] ids);
- 编写SQL语句:SQL映射文件
<!--mybatis会将数组参数,封装为一个Map集合。* 默认:array = 数组* 使用@Param注解改变map集合的默认key的名称--><delete id="deleteByIds">delete from tb_brand where idin<foreach collection="array" item="id" separator="," open="(" close=")">#{id}</foreach>;</delete>
- 编写测试样例
@Testpublic void testDeleteByIds() throws IOException {//接收参数int[] ids = {1,2};//1. 获取SqlSessionFactoryString resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象SqlSession sqlSession = sqlSessionFactory.openSession();//SqlSession sqlSession = sqlSessionFactory.openSession(true);//3. 获取Mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);//4. 执行方法brandMapper.deleteByIds(ids);//提交事务sqlSession.commit();//5. 释放资源sqlSession.close();}
- 运行结果
13.mybatis注解开发
总结
欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下。
(博客的参考源码可以在我主页的资源里找到,如果在学习的过程中有什么疑问欢迎大家在评论区向我提出)