首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Hibernate vs MyBatis 多對多關聯映射:從 XML 配置到 SQL 手寫的思維轉變

     編輯:程式設計疑難解答

核心差異:ORM vs SQL Mapping

維度Hibernate (ORM)MyBatis (SQL Mapping)
映射方式對象關係映射,自動生成 SQL手寫 SQL,結果映射到對象
多對多定義實體類 @ManyToMany + 中間表註解XML 中寫 JOIN 查詢,resultMap 映射
中間表自動管理(可自定義)手寫 SQL 顯式 JOIN 中間表
級聯操作支持 cascade=ALL 等需手寫多條 INSERT/DELETE
學習曲線陡峭(懶加載、會話、代理)平緩(SQL 直觀可控)

Hibernate 多對多標準配置

實體類

 courses = new HashSet<>();
    // getter/setter
}

@Entity
public class Course {
    @Id @GeneratedValue
    private Long id;
    private String name;
    
    @ManyToMany(mappedBy = "courses")
    private Set students = new HashSet<>();
    // getter/setter
}

操作示例

// 保存關聯
Student s = new Student("張三");
Course c1 = new Course("數學");
Course c2 = new Course("英語");
s.getCourses().add(c1);
s.getCourses().add(c2);
session.persist(s); // 自動維護 student_course 表

MyBatis 多對多手寫 SQL 方案

表結構

CREATE TABLE student (id BIGINT PK, name VARCHAR(50));
CREATE TABLE course (id BIGINT PK, name VARCHAR(50));
CREATE TABLE student_course (student_id BIGINT, course_id BIGINT, PK(student_id, course_id));

Mapper XML

<resultMap id="studentDetail" type="Student">
    <id property="id" column="student_id"/>
    <result property="name" column="student_name"/>
    <collection property="courses" ofType="Course">
        <id property="id" column="course_id"/>
        <result property="name" column="course_name"/>
    </collection>
</resultMap>

<select id="selectStudentWithCourses" resultMap="studentDetail">
    SELECT s.id AS student_id, s.name AS student_name,
           c.id AS course_id, c.name AS course_name
    FROM student s
    LEFT JOIN student_course sc ON s.id = sc.student_id
    LEFT JOIN course c ON sc.course_id = c.id
    WHERE s.id = #{id}
</select>

<!-- 插入關聯 -->
<insert id="insertStudentCourse">
    INSERT INTO student_course (student_id, course_id) VALUES
    <foreach collection="courseIds" item="cid" separator=",">
        (#{studentId}, #{cid})
    </foreach>
</insert>

Service 層事務控制

@Transactional
public void enrollStudent(Long studentId, List courseIds) {
    // 1. 刪除舊關聯
    studentCourseMapper.deleteByStudentId(studentId);
    // 2. 批量插入新關聯
    studentCourseMapper.insertStudentCourse(studentId, courseIds);
}

選型建議

選擇 Hibernate 當:
- 領域模型豐富,業務邏輯封裝在實體中
- 需要自動脏檢查、延遲加載、二級緩存
- 團隊擅長 OOP、DDD 設計

選擇 MyBatis 當:
- SQL 性能調優需求高(複雜報表、分頁、分庫分表)
- 團隊偏好 SQL 可見、可控、可調試
- 遺留系統改造、存儲過程多、非標準映射
- 微服務中輕量級數據訪問層

混合使用策略

實際項目常混合使用:

  • 核心業務實體用 Hibernate(訂單、用戶、商品)
  • 複雜查詢、報表、數據同步用 MyBatis
  • 共用 DataSource、TransactionManager,@Transactional 統一事務
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved