1. MyBatis-Plus 的自动驼峰映射


2. @ControllerAdvice 的作用


3. JSR-303


4. 使用 @Validated 指定分组的影响


5. MyBatis resultMap 实现直接映射的详解

5.1 什么是 resultMap

resultMap 是 MyBatis 提供的一个核心功能,用于实现结果集和 Java 对象的自定义映射关系。
它能够解决字段名称和属性名称不一致的问题,比如数据库中的字段为 course_name,而实体类中的字段为 courseName

5.2 直接映射的作用

通过定义 resultMap,可以手动指定数据库字段与实体类属性的映射关系,从而实现精准控制。

特点
  1. 支持 字段名称与属性名称不一致的映射。
  2. 支持嵌套对象的映射。
  3. 支持 association(单对象)和 collection(集合)类型的复杂对象映射。

5.3 resultMap 的基本用法

示例:实现数据库字段和实体类的映射

数据库表结构
CREATE TABLE course (
    id INT PRIMARY KEY,
    course_name VARCHAR(50),
    course_price DECIMAL(10, 2)
);
Java 实体类
public class Course {
    private Integer id;
    private String courseName;
    private BigDecimal coursePrice;

    // Getters and Setters
}
Mapper 配置文件
<mapper namespace="com.example.mapper.CourseMapper">

    <!-- 定义 resultMap -->
    <resultMap id="CourseResultMap" type="com.example.entity.Course">
        <id column="id" property="id"/>
        <result column="course_name" property="courseName"/>
        <result column="course_price" property="coursePrice"/>
    </resultMap>

    <!-- 查询语句直接引用 resultMap -->
    <select id="selectAllCourses" resultMap="CourseResultMap">
        SELECT id, course_name, course_price FROM course
    </select>

</mapper>

5.4 注意点

  1. column 对应数据库字段名:
    • course_name,它是数据库字段名。
  2. property 对应 Java 实体类的属性名:
    • courseName,它是实体类的属性名。
  3. id 标签:
    • 标记主键字段,可以指定主键的映射规则。
  4. result 标签:
    • 映射普通字段。

5.5 如何调用?

Mapper 接口
@Mapper
public interface CourseMapper {
    @Select("SELECT id, course_name, course_price FROM course")
    @ResultMap("CourseResultMap")
    List<Course> selectAllCourses();
}
调用方法
@Autowired
private CourseMapper courseMapper;

public void testResultMap() {
    List<Course> courses = courseMapper.selectAllCourses();
    courses.forEach(course -> System.out.println(course.getCourseName()));
}

5.6 使用 resultMap 的场景

5.7 复杂映射示例:嵌套对象

数据库表结构
CREATE TABLE course (
    id INT PRIMARY KEY,
    course_name VARCHAR(50),
    teacher_id INT
);

CREATE TABLE teacher (
    id INT PRIMARY KEY,
    teacher_name VARCHAR(50)
);
实体类结构
public class Course {
    private Integer id;
    private String courseName;
    private Teacher teacher;
    // Getters and Setters
}

public class Teacher {
    private Integer id;
    private String teacherName;
    // Getters and Setters
}
Mapper 配置文件
<mapper namespace="com.example.mapper.CourseMapper">

    <!-- Teacher 的 resultMap -->
    <resultMap id="TeacherResultMap" type="com.example.entity.Teacher">
        <id column="id" property="id"/>
        <result column="teacher_name" property="teacherName"/>
    </resultMap>

    <!-- Course 的 resultMap,嵌套 Teacher -->
    <resultMap id="CourseResultMap" type="com.example.entity.Course">
        <id column="id" property="id"/>
        <result column="course_name" property="courseName"/>
        <association property="teacher" javaType="com.example.entity.Teacher" resultMap="TeacherResultMap"/>
    </resultMap>

    <!-- 查询语句 -->
    <select id="selectAllCoursesWithTeacher" resultMap="CourseResultMap">
        SELECT c.id, c.course_name, t.id AS teacher_id, t.teacher_name
        FROM course c
        LEFT JOIN teacher t ON c.teacher_id = t.id
    </select>

</mapper>
调用示例
List<Course> courses = courseMapper.selectAllCoursesWithTeacher();
for (Course course : courses) {
    System.out.println("Course: " + course.getCourseName() + ", Teacher: " + course.getTeacher().getTeacherName());
}

5.8 总结

建议:开发中优先尝试自动驼峰映射,遇到复杂场景再考虑手动配置 resultMap