Mybatis之Mapper代理开发
创始人
2025-05-28 06:07:37
0
🍎道阻且长,行则将至。🍓

目录

  • 一、Mapper概述
    • 1.Mapper代理开发
    • 2.Mapper开发流程
      • 准备
      • 实现查询
  • 二、Mybatis-CRUD
    • 0.编辑类Brand
    • 1.查询所有数据
    • 2.根据id查询
    • 3.多条件查询
    • 4.动态单个条件查询
    • 5.添加数据
  • 三、注解实现CRUD


一、Mapper概述

通用Mapper都可以极大的方便开发人员。可以随意的按照自己的需要选择通用方法,还可以很方便的开发自己的通用方法。
参考gitee:MyBatis 通用 Mapper4

1.Mapper代理开发

之前我们写的Mybatis代码是基本使用方式,【参考Mybatis快速入门】,它存在硬编码的问题,例如执行sql:sqlSession.selectList("test.selectAll");,传递的字符串参数是映射配置文件中的 namespace.id值,这样写不便于后期的维护。如果使用 Mapper 代理方式则不存在硬编码问题。

2.Mapper开发流程

准备

新建一个Maven项目:
Maven Module
一个module已建立好:
在这里插入图片描述
在main的java里面创建好你的包mybatis,在这个包下面可以再建立2个包,一个存放你的mapper接口,一个创建一个类来存储我们后面用于接收数据。同时在resource里面建立一个和mapper同样结构的文件目录,里面存放SQL映射文件,这个文件名称要和mapper接口一致
在这里插入图片描述
然后在mapper里面新建一个接口,查询所有数据的例子:

package mybatis.mapper;
import mybatis.pojp.Brand;
import java.util.List;
public interface BrandMapper {List selectAll();
}

继续编写我们的mapper xml文件,也就是SQL映射文件。namespace是对应接口相对于source的目录+名称, resultType是对应类的目录名称,当在mybatis的配置文件中设置好给类起别名映射,就也可以直接不区分大小写写类名了。







在这里插入图片描述
至此mapper的前置文件部分准备好了。

如果Mapper接口名称和SQL映射文件名称相同,并在同一目录下,则可以使用包扫描的方式简化SQL映射文件的加载。也就是将核心配置文件的加载映射配置文件的配置修改为:



实现查询

我们可以在test里面建立我们测试项目:mybatis/test/MyBatisTest.java。使用了代理mapper之后我们执行SQL的代码就从字符串参数"test.selectAll"变为UserMapper.class了。
sqlSession.selectList("test.selectAll");—>sqlSession.getMapper(UserMapper.class);

public static void main(String[] args) throws IOException {//1. 加载mybatis的核心配置文件,获取 SqlSessionFactoryString resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象,用它来执行sqlSqlSession sqlSession = sqlSessionFactory.openSession();//3. 执行sql//3.1 获取UserMapper接口的代理对象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);List users = userMapper.selectAll();System.out.println(users);//4. 释放资源sqlSession.close();
}

二、Mybatis-CRUD

这一节我们使用映射配置文件实现CRUD操作,也就是增删改查操作。

create table tb_brand
(id           int primary key auto_increment,brand_name   varchar(20),company_name varchar(20),ordered      int,description  varchar(100),-- 状态:0:禁用  1:启用status       int
);

继续上一节的内容,我们操作一个这样的数据表。

0.编辑类Brand

上一节我们在pojp包下创建了 Brand 实体类。我们根据数据表编辑对应的参数:

public class Brand {private Integer id;private String brandName;private String companyName;private Integer ordered;private String description;private Integer status;
}

1.查询所有数据

  • 编写接口方法:
List selectAll();
  • 编写SQL
    
  • 测试代码
    在测试项目mybatis/test/MyBatisTest.java中开始我们的测试代码。我们可以使用@Test注解。
    @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 brands = brandMapper.selectAll();System.out.println(brands);//5. 释放资源sqlSession.close();}

成功运行测试:
在这里插入图片描述
写到这里,我们会发现使用mapper代理后面只需要操作三个文件内容
在这里插入图片描述
其实在测试方法里面我们需要修改的也只是执行方法,在后面会有具体体现。

但是在这里我们发现一个问题,就是打印出来的内容有一些是null,但是数据库里面的表是存在数据的。还有注意是不是写了tostring。从打印结果可以看到 brandNamecompanyName 这两个属性的数据没有封装成功,查询 实体类 和 表中的字段 发现,是因为他们的名称不一致,这个问题可以通过两种方式进行解决
1.给字段起别名
2.使用resultMap定义字段和属性的映射关系

  • 起别名

写sql语句时给这两个字段起别名,将别名定义成和属性名一致:


SQL语句中一大串的内容很麻烦也不美观,Mybatis提供了sql 片段可以提高sql的复用性。id属性值是唯一标识,后面通过该值进行引用。

id, brand_name as brandName, company_name as companyName, ordered, description, status

原sql语句引用 id="selectAll"


  • 映射

使用resultMap定义字段和属性(不一致)的映射关系。



sql语句的resultType改为resultMap并引用其id。


2.根据id查询

  • 编写接口方法
    Brand selectById(int id);
  • 编写SQL语句
    这里是根据id来查询,所以就有了参数的传入。就需要用到参数占位符,参数占位符在sql中就是?
    在这里插入图片描述
    mybatis提供了两种参数占位符
    1. #{} :执行SQL时,会将 #{} 占位符替换为?,将来自动设置参数值。
    2. ${} :拼接SQL。底层使用的是 Statement,会存在
    SQL注入问题

编写如下的SQL语句:


  • 测试代码
@Test
public void testSelectById() throws IOException {//接收参数idint 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();
}

是不是测试代码就是修改了对应执行方法。

  • 特殊字段处理
    映射配置文件是xml类型的问题,而> < 等字符在xml中有特殊含义,所以这些符号需要转义,有两种方式进行转义:转义字符、CDATA区

3.多条件查询

使用条件查询返回多个结果,所以我们需要使用list来存储。还需要考虑如何实现条件。

  • 编写接口方法
    我们需要传多个参数,所以这里也有多个写法:

1、使用 @Param("参数名称") 标记每一个参数,在编写SQL时使用 #{参数名称} 进行占位

  List selectByCondition(@Param("status") int status, @Param("companyName") String companyName,@Param("brandName") String brandName);

2、将多个参数封装成一个 实体对象 ,将该实体对象作为接口的方法参数。在SQL中使用 #{内容}内容和实体类属性名一致。

  List selectByCondition(Brand brand);

3、将多个参数封装到map集合中,将map集合作为接口的方法参数。在SQL中使用 #{内容}内容和map集合中键的名称一致。

  List selectByCondition(Map map);
  • SQL语句

  • 测试代码

存在一个模糊匹配,所以需要进行参数处理:%

@Testpublic void testSelectByCondition() throws IOException {//接收参数int status = 1;String companyName = "华为";String brandName = "华为";// 处理参数companyName = "%" + companyName + "%";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. 执行方法   3kind//方式一 :接口方法参数使用 @Param 方式调用的方法
//        List brands = brandMapper.selectByCondition(status,companyName,brandName);//方式二 :接口方法参数是 实体类对象 方式调用的方法
/*        Brand brand = new Brand();brand.setStatus(status);brand.setCompanyName(companyName);brand.setBrandName(brandName);List brands = brandMapper.selectByCondition(brand);*///方式三 :接口方法参数是 map集合对象 方式调用的方法Map map = new HashMap();
//        map.put("status" , status);map.put("companyName", companyName);map.put("brandName" , brandName);List brands = brandMapper.selectByCondition(map);System.out.println(brands);//5. 释放资源sqlSession.close();}
  • 动态SQL
    使用动态SQL可以解决输入条件时,不需要填写全部条件,自动根据输入内容进行匹配。
    我们可以利用mybatis提供的if 标签和 where 标签

【if标签】
可以判断是不是存在对于参数,进行sql的拼接。


这样的情况又会出现问题:如果第一个参数没有,那么首位出现and,SQL语句肯定报错。
【where标签】
where标签就是解决这一问题的,会自动去掉非法的and,如果没有参数则不加where关键字。第一个条件也写了and。

and status = #{status}and company_name like #{companyName}and brand_name like #{brandName}

4.动态单个条件查询

  • 编写接口方法
    List selectByConditionSingle(Brand brand);
  • SQL语句

为了实现动态查询我们使用 choose(when,otherwise)标签 , choose 标签相当于Java 的switch。


  • 测试代码
@Test
public 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 brands = brandMapper.selectByConditionSingle(brand);System.out.println(brands);//5. 释放资源sqlSession.close();
}

5.添加数据

  • 编写接口方法
    void add(Brand brand);

  • SQL语句

insert into tb_brand (brand_name, company_name, ordered, description, status)values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});

  • 测试代码
@Test
public void testAdd() throws IOException {//接收参数int status = 1;String companyName = "AA科技";String brandName = "AA";String description = "AA创新生活!";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();//3. 获取Mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);//4. 执行方法brandMapper.add(brand);//提交事务sqlSession.commit();//5. 释放资源sqlSession.close();
}

是不是发现大多是一个套路!都是类似的。

三、注解实现CRUD

使用注解开发会比配置文件开发更加方便。
Mybatis 针对 CURD 操作都提供了对应的注解:

  • 查询 :@Select
  • 添加 :@Insert
  • 修改 :@Update
  • 删除 :@Delete

例如在接口中就可以这样写,不需要处理配置文件了:

@Select(value = "select * from tb_user where id = #{id}")
public User select(int id);

只是注解适用于完成简单功能,配置文件可以处理复杂功能。

1.使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂-点的语句,JAVA注解不仅力不从心,还会让你本就复杂的SQL语句更加混乱不堪。因此,如果你需要做一些很复杂的操作,最好用xml来映射语句。

2.选择何种方式来配置映射,以及认为是否应该要统一映射语句定义的形式,完全取决于你和你的团队.换句话说,永远不要拘泥于种方式,你可以很轻松的在基于注解和xml的语句映射方式间自由移植和切换。


🍇end🍑

☕物有本末,事有终始,知所先后。🍭

🍎☝☝☝☝☝我的CSDN☝☝☝☝☝☝🍓

相关内容

热门资讯

如何挺过创业最初期那段日子? ... 如何挺过创业最初期那段日子?作者:方滔分类:网赚问答发布于:2020-6-次浏览0条评论2013年底...
自媒体是未来最值得创业的行业,...   文|韦彪图|网络今年疫情爆发以来,我踏入了自媒体行业。初入自媒体的我,一股干劲,对写作情有独钟,...
马斯克官宣:将离开特朗普政府 据央视新闻消息,当地时间5月28日,美国政府效率部负责人埃隆·马斯克在其社交媒体平台X上发文表示,在...
化妆品原料参考数据相关问答 转自:中国医药报 问:《〈国际化妆品安全评估数据索引〉收录的部分原料使用信息》的制定背景是什么...
关注|8个中央生态环保督察组全... 第三轮第四批中央生态环保督察全部实现进驻记者28日从生态环境部获悉,到当日下午,第三轮第四批8个中央...
富邦科技:公司多项业务进展及成... 投资者提问:固氮杆菌产品在国内大田作物(如玉米、水稻)的示范田效果如何?用户反馈的核心痛点(如成本、...
内蒙古第十届百县健身气功交流赛... 近日,内蒙古自治区第十届百县健身气功交流比赛在巴彦淖尔市乌拉特前旗启幕,吸引了来自全区12个盟市、1...
券商晨会精华:铝业公司迎来弱供...   炒股就看金麒麟分析师研报,权威,专业,及时,全面,助您挖掘潜力主题机会! 财联社5月29日讯,...
把爱送给小患者 来源:新华网 5月28日,中国红十字基金会的志愿者和来自新疆维吾尔自治区阿克苏地区的先天性心脏病患儿...
理论热点丨准确认识绿色消费升级... 转自:中国经济时报核心观点  绿色消费作为可持续消费模式,是连接消费端与产业端的重要纽带。近年来,我...
西太平洋银行:美国贸易法庭的裁... 格隆汇5月29日|西太平洋银行称,美国贸易法院阻止特朗普全球关税的裁决是一个司法举动,而不是政府的决...
北京警方:诈骗手段发生变化 冒... 转自:千龙网北京市公安局刑侦总队5月28日通报,今年以来,北京警方共破获电诈案件2600余起,同比上...
用对方法才能有效改善黑头 转自:中国医药报 黑头作为常见的皮肤问题,困扰着很多人。任何年龄、肤质的人,都有可能出现黑头。...
【ICH基础知识500问】E1... 转自:中国医药报 问:什么是QT/QTc间期?这个间期延长意味着什么? 答:QT间期是指...
美以插手加沙物资分发 现场混乱... 转自:央视联合国官员28日在日内瓦表示,由美国和以色列支持的私营援助组织“加沙人道主义基金会”27日...
查尔斯三世演讲后,特朗普喊话加... 姜蔼玲 闫佩云针对美国总统特朗普对加拿大产品征税且威胁要让加拿大成为美国“第51个州”等言行,英国国...
时政微观察丨总书记深情寄望“小... 来源:央视新闻客户端“‘六一’国际儿童节快要到了,祝全国的小朋友们节日快乐!”5月27日,习近平总书...
“95后”成为线上购险率最高的... 来源:@经济观察报微博记者 姜鑫以“95后”为代表的20—30岁年轻群体,成为线上购险率最高的客群。...
誓让家乡换新颜——记庆阳市西峰...   原标题:誓让家乡换新颜——记庆阳市西峰区肖金镇左咀村党总支书记兼村委会主任左新郎  新甘肃·甘肃...
新湖期货:PTA延续去库格局 自修复4月初跳空缺口以后,PTA上方压力渐显,价格有所回落。尽管当下PTA供需两端都有弱化,但二季度...