MyBatis使用Map与POJO类实现CRUD操作的步骤详解
作者:自在极意功。
本文将通过实际案例,详细讲解在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);
}这种方式存在以下缺点:
- 代码冗余,每个字段都需要手动映射
- 容易出错,字段名写错会导致运行时错误
- 维护困难,表结构变化时需要修改大量代码

二、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 注意事项
- 键名匹配原则:
#{}中的名称必须与Map中的key完全一致 - 空值处理:如果key不存在,对应的值将为null
- 命名规范:建议使用有意义的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→carNumguide_price→guidePriceproduce_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的资料请关注脚本之家其它相关文章!
