专栏精选
摘要
在这篇文章中,我将介绍Mybatis映射支持的参数形式和映射结果的形式,在这之前我们需要修改一下项目的代码结构使得后续的代码结构更加清晰。准备好开启今天的神奇之旅了吗?
引言
大家好,我是奇迹老李,一个专注于分享开发经验和基础教程的博主。这里是我的其中一个技术分享平台,欢迎广大朋友们点赞评论提出意见,重要的是点击关注喔 🙆。今天要和大家分享的内容是mapper映射的参数和结果。做好准备,Let’s go🚎🚀
正文
一点简单的改造
为了方便后续测试,简单改造一下现有程序
-
构建全局上下文
/** * mybatis全局上下文类,功能是读取配置文件,构建SqlSessionFactory,注册service */ public class MybatisAppContext { private static SqlSessionFactory sqlSessionFactory = null; private Map<String, MybatisService> serviceMap = new ConcurrentHashMap<>(); }
-
构建基础service类
public abstract class MybatisService<T> { private SqlSession session=null; private T defaultMapper; public void registrySession(SqlSession session) { this.session=session; } public void closeSession(){ if (session!=null){ session.commit(); session.close(); } } protected T getMapper(Class<? extends T> mapperClass){ if (this.defaultMapper==null) { this.defaultMapper = this.session.getMapper(mapperClass); } return this.defaultMapper; } abstract void doService(); }
-
将
SqlSessionFactory
添加到全局上下文public class MybatisAppContext { private static SqlSessionFactory sqlSessionFactory = null; private Map<String, MybatisService> serviceMap = new ConcurrentHashMap<>(); /** * 注册SqlSessionFactory */ static { SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); try (InputStream in = MybatisApp.class.getResourceAsStream("/mybatis-config.xml")) { sqlSessionFactory = builder.build(in); } catch (IOException e) { System.out.println("文件路径读取错误"); } } /** * 关闭所有session * * @author Myste * @since 2023/11/3 11:25 */ public void close() { for (Map.Entry<String, MybatisService> entry : this.serviceMap.entrySet()) { entry.getValue().closeSession(); } } }
-
在全局上下文注册service
public class MybatisAppContext { ... /** * 注册service * * @param serviceClass * @return * @throws InstantiationException * @throws IllegalAccessException * @author Myste * @since 2023/11/3 11:04 */ public MybatisService registryService(Class<? extends MybatisService> serviceClass) throws InstantiationException, IllegalAccessException { SqlSession session = sqlSessionFactory.openSession(); MybatisService service = serviceClass.newInstance(); service.registrySession(session); this.serviceMap.put(serviceClass.getName(), service); return service; } /** * 获取service * * @param serviceClass * @return * @author Myste * @since 2023/11/3 11:04 */ public MybatisService getService(Class<? extends MybatisService> serviceClass) throws InstantiationException, IllegalAccessException { String name = serviceClass.getName(); if (this.serviceMap.containsKey(name)) { return this.serviceMap.get(name); } else { return this.registryService(serviceClass); } } }
-
将之前的测试代码,提取到
ApplicationService
类中所有静态方法改为非静态方法
实现
MybatisService#doService
方法package top.sunyog.mybatis.service; import top.sunyog.common.entity.AppSearchVo; import top.sunyog.common.entity.AppTestEntity; import top.sunyog.common.entity.AppTestEntityBuilder; import top.sunyog.mybatis.mapper.ApplicationRepository; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; /** * @author Myste * @since 2023/11/3 10:51 */ public class ApplicationService extends MybatisService<ApplicationRepository>{ private void testUpdateStatus(ApplicationRepository mapper) { int row = mapper.changeStatus(1L, "1"); System.out.println("状态修改成功, 影响行数: "+row); } private void testAddList(ApplicationRepository mapper) { AppTestEntityBuilder builder = new AppTestEntityBuilder(); builder.setCreator("admin3").setAuthType("2"); List<AppTestEntity> list=new ArrayList<>(); list.add(builder.setAppName("名称1").setAppCode("code-1").build()); list.add(builder.setAppName("name2").setAppCode("code-2").build()); list.add(builder.setAppName("jack liu").setAppCode("code-3").build()); int row = mapper.addList(list); System.out.println("数据新增成功,影响行数: "+row); } private void testOne(ApplicationRepository mapper) { AppTestEntity entity = mapper.queryById(1L); System.out.println(entity); } private void testDelete(ApplicationRepository mapper) { int row = mapper.deleteById(4L); System.out.println("删除成功,影响行数: "+row); } private void testUpdate(ApplicationRepository mapper) { AppTestEntity entity = new AppTestEntity(); // entity.setAppName("测试修改3"); entity.setId(4L); // entity.setAppCode("test_update_app"); entity.setAuthType("2"); // entity.setCreateDate(LocalDate.now()); // entity.setCreator("zhangsan"); int row = mapper.updateById(entity); System.out.println("修改成功,影响行数: "+row); } private void testInsert(ApplicationRepository mapper) { AppTestEntity entity = new AppTestEntity(); entity.setAppName("测试新增"); entity.setAppCode("test_add_app"); entity.setAuthType("2"); entity.setCreateDate(LocalDate.now()); entity.setCreator("admin2"); int row = mapper.addApp(entity); System.out.println("新增成功, 影响行数: "+row); } private void testQuery(ApplicationRepository mapper) { AppSearchVo param = new AppSearchVo(); param.setAppName("应用"); param.setAuthType("2"); List<AppTestEntity> list = mapper.queryApp(param); list.forEach(o-> System.out.println(o)); } @Override public void doService() { testQuery(super.getMapper(ApplicationRepository.class)); } }
-
修改main方法
/** * mybatis启动类,,测试数据查询 * * @author Myste * @since 2023/10/31 16:53 */ public class MybatisApp { public static void main(String[] args) throws InstantiationException, IllegalAccessException { MybatisAppContext context = new MybatisAppContext(); MybatisService service = context.registryService(ApplicationService.class); service.doService(); context.close(); } }
mapper映射的参数形式
回顾之前的内容,我们使用过的mapper方法的入参的形式有以下几种方式
- 一个入参,数据库类型,如:基本类型包装类
- 多参数,通过@Param标记
- HashMap作为入参
- 数组或集合类型,并通过
<foreach ...></foreach>
标签包裹
除此之外,mybatis还支持5. 简单JavaBean形式的入参
下面以关键字查询功能为例,介绍简单javaBean作为入参的查询
若将查询条件改为关键字,通过模糊搜索名称和编码。这类业务可以通过以JavaBean作为参数进行查询。
package top.sunyog.common.entity;
public class AppKeywordsVo {
private String keyword;
private String authType;
//省略getter、setter
}
//mapper接口
public interface SimpleQueryMapper {
List<AppTestEntity> queryMap(AppKeywordsVo vo);
}
//映射文件
<mapper namespace="top.sunyog.mybatis.mapper.SimpleQueryMapper">
<select id="queryMap" resultType="appTestEntity">
select id,app_name,app_code,auth_type,create_date,creator from app_test
<where>
<if test="null != keyword and ''.toString() != keyword">
and (app_name like concat('%',#{keyword},'%') or app_code like concat('%',#{keyword},'%'))
</if>
<if test="null != authType and ''.toString() != authType">and auth_type = #{authType}</if>
</where>
</select>
</mapper>
//业务service
public class SimpleQueryService extends MybatisService<SimpleQueryMapper>{
@Override
public void doService() {
SimpleQueryMapper mapper = super.getMapper(SimpleQueryMapper.class);
this.testHashMapParam(mapper);
}
private void testHashMapParam(SimpleQueryMapper mapper) {
AppKeywordsVo params=new AppKeywordsVo;
params.setKeyword("-");
params.setAuthType("2");
List<AppTestEntity> list = mapper.queryMap(params);
list.forEach(o-> System.out.println(o));
}
}
//测试启动
public class MybatisApp {
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
MybatisAppContext context = new MybatisAppContext();
MybatisService service = context.registryService(SimpleQueryService.class);
service.doService();
context.close();
}
}
结果映射的形式
Mybatis支持的结果映射的形式包括
- 基本类型包装类
- 简单JavaBean,或POJO
- Map(这种形式不建议使用)
- 复杂类型
前两种形式在之前的例子中已经出现过,这里先介绍Map类型的结果,复杂类型的映射结果将在后续文章中介绍。
Map类型结果
Map类型的映射结果使用一个HashMap来构建查询结果返回值,这对于很多事先不知道明确的结果字段名称的业务有很大帮助。对于事先已明确结果字段名称时,建议创建一个简单JavaBean来接收查询结果,这样的代码可读性更强,便于应对后续的业务修改。
<!--映射文件-->
<select id="queryMapRes" resultType="java.util.Map">
select id,app_name,app_code,auth_type,create_date,creator from app_test
<where>
<choose>
<when test="id != null and id > 0">id=#{id}</when>
<otherwise>id='1'</otherwise>
</choose>
</where>
</select>
//mapper接口
List<Map<String, Object>> queryMapRes(@Param("id") int id);
//业务service
@Override
public void doService() {
SimpleQueryMapper mapper = super.getMapper(SimpleQueryMapper.class);
this.testHashMapResult(mapper);
}
private void testHashMapResult(SimpleQueryMapper mapper){
List<Map<String,Object>> list=mapper.queryMapRes(null);
list.forEach(o->{
o.entrySet().forEach(entry->{
String str = entry.getKey() + " : " + entry.getValue().toString();
System.out.println(str);
});
});
}
打印结果如下:
app_name : 测试应用
auth_type : 1
creator : admin
id : 1
create_date : 2023-10-31
app_code : ceshi
总结
在这片文章中,介绍了Mybatis的映射参数形式和映射结果形式,这也就回答了上一篇文章最后提出的前两个疑问,其他的几个疑问将在后续的文章中一一解答。
常见的mapper映射参数有
- 基本类型及其包装类
@Param
注解标注的类型- Map类型
- 简单JavaBean
- 数组或集合类型
常见的mapper映射结果类型有
- 基本类型及其包装类
- 简单JavaBean
- Map类型
- 各种复杂类型(包括以上类型的数组或组合)
实际上,任何类型都能够作为Mybatis映射的参数和映射结果,作为参数需要该类型中存在getter方法,而作为结果需要该类型中存在setter或有参数构造函数
📩 联系方式
邮箱:qijilaoli@foxmail.com❗版权声明
本文为原创文章,版权归作者所有。未经许可,禁止转载。更多内容请访问奇迹老李的博客首页