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的资料请关注脚本之家其它相关文章!

相关文章

  • Javaweb实现上传下载文件的多种方法

    Javaweb实现上传下载文件的多种方法

    本篇文章主要介绍了Javaweb实现上传下载文件,有多种实现方式,需要的朋友可以参考下。
    2016-10-10
  • Java并发 结合源码分析AQS原理

    Java并发 结合源码分析AQS原理

    这篇文章主要介绍了Java并发 结合源码分析AQS原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • Java中ResultSetMetaData 元数据的具体使用

    Java中ResultSetMetaData 元数据的具体使用

    本文主要介绍了Java中ResultSetMetaData 元数据的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • SpringBoot项目中resources文件读取实践

    SpringBoot项目中resources文件读取实践

    本文详细介绍了SpringBoot项目中读取resources目录下文件的9种主流方式,并提供了一个完整的控制器Demo示例,帮助开发者快速定位最适合的资源加载方案
    2026-01-01
  • SpringBoot接收form-data和x-www-form-urlencoded数据的方法

    SpringBoot接收form-data和x-www-form-urlencoded数据的方法

    form-data和x-www-form-urlencoded是两种不同的HTTP请求体格式,本文主要介绍了SpringBoot接收form-data和x-www-form-urlencoded数据的方法,具有一定的参考价值,感兴趣的可以了解一下
    2024-05-05
  • Java多态概念、实现机制与实践应用详解

    Java多态概念、实现机制与实践应用详解

    多态是指同一个方法在不同对象上具有不同的行为,通过多态程序可以在运行时决定调用哪个方法,从而提高代码的灵活性和可扩展性,这篇文章主要介绍了Java多态概念、实现机制与实践应用的相关资料,需要的朋友可以参考下
    2026-01-01
  • 浅谈spring ioc的注入方式及注入不同的数据类型

    浅谈spring ioc的注入方式及注入不同的数据类型

    这篇文章主要介绍了浅谈spring ioc的注入方式及注入不同的数据类型,具有一定借鉴价值,需要的朋友可以参考下
    2017-12-12
  • Java并发编程之Semaphore详解

    Java并发编程之Semaphore详解

    这篇文章主要介绍了Java并发编程之concurrent包中的Semaphore详解,信号量Semaphore一般用来表示可用资源的个数,相当于一个计数器,可类比生活中停车场牌子上面显示的停车场剩余车位数量,需要的朋友可以参考下
    2023-12-12
  • Java的validation参数校验代码实例

    Java的validation参数校验代码实例

    这篇文章主要介绍了Java的validation参数校验代码实例,Validation参数校验是指在程序运行中对传进来的参数进行合法性检查,以保证程序的正确性和安全性,需要的朋友可以参考下
    2023-10-10
  • 四个Java常见分布式锁的选型和性能对比

    四个Java常见分布式锁的选型和性能对比

    当涉及到分布式系统中的并发控制和数据一致性时,分布式锁是一种常见的解决方案,本文将对几种常见的分布式锁实现原理、实现示例、应用场景以及优缺点进行详细分析,需要的可以参考一下
    2023-05-05

最新评论