MyBatis使用Map与POJO类实现CRUD操作的步骤详解

 更新时间:2025年12月24日 10:08:51   作者:自在极意功。  
本文将通过实际案例,详细讲解在MyBatis中如何使用Map集合和POJO类两种方式实现数据库的增删改查操作,解决常见映射问题,提高开发效率,需要的朋友可以参考下

一、MyBatis简介与CRUD基础

MyBatis是一款优秀的持久层框架,它支持自定义SQL、存储过程以及高级映射。MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集的工作。

1.1 传统JDBC的问题

在传统JDBC编程中,我们经常遇到以下问题:

// JDBC中繁琐的结果集处理
while(rs.next()) {
    User user = new User();
    user.setId(rs.getString("id"));
    user.setIdCard(rs.getString("idCard"));
    user.setUsername(rs.getString("username"));
    // ... 需要为每个属性手动赋值
    userList.add(user);
}

这种方式存在以下缺点:

  1. 代码冗余,每个字段都需要手动映射
  2. 容易出错,字段名写错会导致运行时错误
  3. 维护困难,表结构变化时需要修改大量代码

二、MyBatis中使用Map实现CRUD

2.1 使用Map进行数据插入

Map集合提供了灵活的键值对存储方式,适合不确定参数数量或临时性的数据操作。

2.1.1 基础Map传参

@Test
public void testInsertCarByMap() {
    SqlSession sqlSession = SqlSessionUtil.openSession();
    
    // 使用Map封装前端传递的数据
    Map<String, Object> map = new HashMap<>();
    map.put("carNum", "11111");
    map.put("brand", "比亚迪汉");
    map.put("guidePrice", 10.0);
    map.put("produceTime", "2020-11-11");
    map.put("carType", "电车");
    
    // 执行SQL插入操作
    int count = sqlSession.insert("insertCar", map);
    System.out.println("插入记录数:" + count);
    
    sqlSession.commit();
    sqlSession.close();
}

2.1.2 Mapper XML配置

<!-- CarMapper.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.CarMapper">
    
    <insert id="insertCar">
        insert into t_car(id, car_num, brand, guide_price, produce_time, car_type) 
        values(null, #{carNum}, #{brand}, #{guidePrice}, #{produceTime}, #{carType})
    </insert>
    
</mapper>

2.1.3 注意事项

  1. 键名匹配原则#{}中的名称必须与Map中的key完全一致
  2. 空值处理:如果key不存在,对应的值将为null
  3. 命名规范:建议使用有意义的key名称,提高代码可读性

2.2 使用Map进行数据查询

@Test
public void testSelectByMap() {
    SqlSession sqlSession = SqlSessionUtil.openSession();
    
    Map<String, Object> paramMap = new HashMap<>();
    paramMap.put("minPrice", 10.0);
    paramMap.put("brand", "宝马");
    
    List<Map<String, Object>> result = sqlSession.selectList("selectCarByCondition", paramMap);
    
    for (Map<String, Object> car : result) {
        System.out.println(car);
    }
    
    sqlSession.close();
}

三、MyBatis中使用POJO类实现CRUD

3.1 POJO类定义

// Car.java
public class Car {
    private Long id;
    private String carNum;
    private String brand;
    private Double guidePrice;
    private String produceTime;
    private String carType;
    
    // 构造方法
    public Car() {}
    
    public Car(Long id, String carNum, String brand, Double guidePrice, 
               String produceTime, String carType) {
        this.id = id;
        this.carNum = carNum;
        this.brand = brand;
        this.guidePrice = guidePrice;
        this.produceTime = produceTime;
        this.carType = carType;
    }
    
    // Getter和Setter方法
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    
    public String getCarNum() { return carNum; }
    public void setCarNum(String carNum) { this.carNum = carNum; }
    
    // ... 其他getter和setter
}

3.2 使用POJO进行数据插入

@Test
public void testInsertCarByPOJO() {
    SqlSession sqlSession = SqlSessionUtil.openSession();
    
    // 使用POJO对象封装数据
    Car car = new Car(null, "3333", "比亚迪秦", 30.0, "2020-11-11", "新能源");
    
    // 执行SQL
    int count = sqlSession.insert("insertCar", car);
    System.out.println("插入记录数:" + count);
    
    sqlSession.commit();
    sqlSession.close();
}

3.3 POJO传参原理

重要规则#{}占位符中的名称对应的是POJO类的getter方法名去掉"get"并将首字母小写后的名称。

例如:

  • getCarNum() → #{carNum}
  • getGuidePrice() → #{guidePrice}
  • getUsername() → #{username}

3.4 使用POJO进行数据查询

3.4.1 查询单个对象

<!-- 根据id查询汽车信息 -->
<select id="selectById" resultType="com.example.pojo.Car">
    select * from t_car where id = #{id}
</select>
@Test
public void testSelectById() {
    SqlSession sqlSession = SqlSessionUtil.openSession();
    
    // 查询单个对象
    Car car = sqlSession.selectOne("selectById", 1);
    System.out.println(car);
    
    sqlSession.close();
}

3.4.2 查询所有记录

<!-- 查询所有汽车信息 -->
<select id="selectAll" resultType="com.example.pojo.Car">
    select
        id,
        car_num as carNum,
        brand,
        guide_price as guidePrice,
        produce_time as produceTime,
        car_type as carType
    from t_car
</select>
@Test
public void testSelectAll() {
    SqlSession sqlSession = SqlSessionUtil.openSession();
    
    // 查询所有记录,返回List集合
    List<Car> carList = sqlSession.selectList("selectAll");
    
    for (Car car : carList) {
        System.out.println(car);
    }
    
    sqlSession.close();
}

四、解决字段名与属性名映射问题

4.1 问题现象

当数据库字段名与Java类属性名不一致时,会出现属性值为null的情况:

-- 数据库表结构
+----+----------+------------+--------------+---------------+----------+
| id | car_num  | brand      | guide_price  | produce_time  | car_type |
+----+----------+------------+--------------+---------------+----------+
|  1 | 1001     | 宝马520Li  |       10.00  | 2020-10-11    | 燃油车   |
+----+----------+------------+--------------+---------------+----------+

-- 直接查询会导致Car对象的carNum、guidePrice等属性为null
-- 因为数据库字段是car_num,而Java属性是carNum

4.2 解决方案

方案一:SQL中使用AS别名(推荐)

<select id="selectById" resultType="com.example.pojo.Car">
    select
        id,
        car_num as carNum,           -- 起别名
        brand,
        guide_price as guidePrice,   -- 起别名
        produce_time as produceTime, -- 起别名
        car_type as carType          -- 起别名
    from t_car
    where id = #{id}
</select>

方案二:配置驼峰命名自动映射

在MyBatis配置文件中开启驼峰命名自动映射:

<!-- mybatis-config.xml -->
<configuration>
    <settings>
        <!-- 开启驼峰命名自动映射 -->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
</configuration>

开启后,MyBatis会自动将下划线命名的数据库字段映射到驼峰命名的Java属性:

  • car_num → carNum
  • guide_price → guidePrice
  • produce_time → produceTime

方案三:使用resultMap自定义映射

<resultMap id="carResultMap" type="com.example.pojo.Car">
    <id property="id" column="id"/>
    <result property="carNum" column="car_num"/>
    <result property="brand" column="brand"/>
    <result property="guidePrice" column="guide_price"/>
    <result property="produceTime" column="produce_time"/>
    <result property="carType" column="car_type"/>
</resultMap>

<select id="selectById" resultMap="carResultMap">
    select * from t_car where id = #{id}
</select>

五、Map与POJO对比与选择

5.1 使用场景对比

特性Map集合POJO类
灵活性高,适合动态参数低,结构固定
类型安全低,运行时才能发现错误高,编译时检查
代码可读性低,需要查看Map键名高,属性明确
IDE支持有限,无法自动提示好,有代码提示
适合场景临时查询、参数不固定业务实体、固定结构

5.2 最佳实践建议

业务实体操作使用POJO

  • 用户、订单、商品等核心业务实体
  • 需要频繁操作和传递的数据
  • 有利于代码维护和重构

临时查询使用Map

  • 动态条件查询,参数不固定
  • 统计报表等临时性数据操作
  • 快速原型开发阶段

混合使用策略

// 示例:使用Map封装查询条件,返回POJO列表
public List<Car> findCars(Map<String, Object> params) {
    return sqlSession.selectList("findCarsByCondition", params);
}

六、完整示例与总结

6.1 完整Mapper示例

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.CarMapper">
    
    <!-- 插入操作 -->
    <insert id="insertCar">
        insert into t_car(id, car_num, brand, guide_price, produce_time, car_type) 
        values(null, #{carNum}, #{brand}, #{guidePrice}, #{produceTime}, #{carType})
    </insert>
    
    <!-- 根据ID查询 -->
    <select id="selectById" resultType="com.example.pojo.Car">
        select
            id,
            car_num as carNum,
            brand,
            guide_price as guidePrice,
            produce_time as produceTime,
            car_type as carType
        from t_car
        where id = #{id}
    </select>
    
    <!-- 查询所有 -->
    <select id="selectAll" resultType="com.example.pojo.Car">
        select
            id,
            car_num as carNum,
            brand,
            guide_price as guidePrice,
            produce_time as produceTime,
            car_type as carType
        from t_car
    </select>
    
    <!-- 更新操作 -->
    <update id="updateCar">
        update t_car
        set car_num = #{carNum},
            brand = #{brand},
            guide_price = #{guidePrice},
            produce_time = #{produceTime},
            car_type = #{carType}
        where id = #{id}
    </update>
    
    <!-- 删除操作 -->
    <delete id="deleteById">
        delete from t_car where id = #{id}
    </delete>
    
</mapper>

6.2 关键点总结

#{}${}的区别

  • #{}是预编译处理,防止SQL注入
  • ${}是字符串替换,有SQL注入风险

resultType与resultMap

  • resultType:自动映射,要求字段名与属性名一致或配置别名
  • resultMap:自定义映射,处理复杂映射关系

占位符命名规则

  • Map传参:#{}中写Map的key
  • POJO传参:#{}中写getter方法对应的属性名

性能优化建议

  • 尽量使用POJO,享受编译时检查的好处
  • 复杂查询考虑使用resultMap提高可读性
  • 批量操作使用批量API提高性能

通过本文的学习,你应该掌握了MyBatis中使用Map和POJO实现CRUD操作的核心技术。在实际开发中,根据具体场景选择合适的方式,既能提高开发效率,又能保证代码质量。

以上就是MyBatis使用Map与POJO类实现CRUD操作的步骤详解的详细内容,更多关于MyBatis Map与POJO类实现CRUD的资料请关注脚本之家其它相关文章!

相关文章

  • Gradle生成Jar的两种方式小结

    Gradle生成Jar的两种方式小结

    本文介绍使用Gradle创建不可执行及可执行的Jar包,包括将依赖Jar放入lib文件夹的方法,以及如何生成包含所有依赖的单一Jar文件,适用于SpringBoot和其他非SpringBoot项目,感兴趣的可以了解一下
    2025-09-09
  • Java实现五子棋网络版

    Java实现五子棋网络版

    这篇文章主要为大家详细介绍了基于Java编写的网络五子棋,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • Spring Security入门demo案例

    Spring Security入门demo案例

    Spring Security是一个高度自定义的安全框架,本文主要介绍了Spring Security入门,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • SpringBoot使用thymeleaf模板过程解析

    SpringBoot使用thymeleaf模板过程解析

    这篇文章主要介绍了SpringBoot使用thymeleaf模板过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • 基于Socket类以及ServerSocket类的实例讲解

    基于Socket类以及ServerSocket类的实例讲解

    下面小编就为大家带来一篇基于Socket类以及ServerSocket类的实例讲解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • Java List集合返回值去掉中括号(''[ ]'')的操作

    Java List集合返回值去掉中括号(''[ ]'')的操作

    这篇文章主要介绍了Java List集合返回值去掉中括号('[ ]')的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • SpringBoot实现异步的八种方法

    SpringBoot实现异步的八种方法

    Spring Boot 的异步处理主要是通过非阻塞I/O和回调机制来实现的,目的是提高应用的并发性能,它支持多种方式来创建异步任务,本文给大家介绍了SpringBoot实现异步的八种方法,需要的朋友可以参考下
    2024-07-07
  • 关于Java两个浮点型数字加减乘除的问题

    关于Java两个浮点型数字加减乘除的问题

    由于浮点数在计算机中是以二进制表示的,直接进行加减乘除运算会出现精度误差,想要得到精确结果,应使用BigDecimal类进行运算
    2024-10-10
  • 详解SpringCloud LoadBalancer 新一代负载均衡器

    详解SpringCloud LoadBalancer 新一代负载均衡器

    这篇文章主要为大家介绍了SpringCloud LoadBalancer新一代负载均衡器详解使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • 解决IDEA中maven导入jar包一直报错问题

    解决IDEA中maven导入jar包一直报错问题

    这篇文章主要介绍了解决IDEA中maven导入jar包一直报错问题,本文通过实例图文的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04

最新评论