mybatis關聯關係對映
1、一對多關係(OneToMany)
在實際專案中,一對多是非常常見的關係。比如:一個班級可以有多個學生,一個學生只能屬於一個班級,班級和學生是一對多關係,而學生和班級是多對一關係。
資料庫中一對多關係通常使用主外來鍵關聯,外來鍵列應該在多方,即由多方維護關係(一對多中多的一方維護)。
(1)建立資料庫
班級表t_clazz:
CREATE TABLE t_clazz(
cid INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID',
code VARCHAR(18) COMMENT '班級號',
name VARCHAR(18) COMMENT '班級名'
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
說明:
ENGINE=InnoDB:MySQL 的資料庫引擎的設定
AUTO_INCREMENT=1:自動遞增列的 初始數值 = 1
DEFAULT CHARSET=utf8:預設字符集 = utf8
學生表t_student:
CREATE TABLE t_student(
sid INT PRIMARY KEY AUTO_INCREMENT COMMENT '學生ID',
name VARCHAR(18) COMMENT '姓名',
sex VARCHAR(18) COMMENT '性別',
age INT COMMENT '年齡',
clazz_cid INT, #外來鍵:班級ID
CONSTRAINT fk_stu FOREIGN KEY(clazz_cid) REFERENCES t_clazz(cid)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
(2)持久化類
建立一個Clazz類和一個Student類,分別對映t_clazz表和t_student表。
// 班級類
public class Clazz implements Serializable {
private Integer cid;
private String code;
private String name;
//班級和學生是一對多的關係,即一個班級可以有多個學生
private List<Student> studentList;
//省略構造方法和set/get方法……
}
// 學生類
public class Student implements Serializable {
private Integer sid;
private String name;
private String sex;
private Integer age;
//學生和班級是多對一的關係,即一個學生只屬於一個班級
private Clazz clazz;
//省略構造方法和set/get方法……
}
(3)介面
在com.zking.dao中建立實體類的介面
// 班級類介面
public interface ClazzService{
// SQL1:新增Clazz物件
public int addClazz(Clazz clazz);
// SQL2:刪除Clazz物件
public int deleteClazzById(Clazz clazz);
// SQL3:修改Clazz物件
public int updateClazz(Clazz clazz);
// SQL4:根據ID查詢Clazz物件
public Clazz selectClazzById(Integer cid);
// SQL5:查詢所有Clazz物件
public List<Clazz> selectAllClazz();
// SQL6:模糊查詢Clazz物件
public List<Clazz> selectClazzWhere(Clazz clazz);
// SQL7:多表聯查:查詢班級資訊及學員資訊
public Clazz selectClazzAndStudent(Integer cid);
// SQL8:包含查詢
public List<Clazz> selectClazzIn(Clazz clazz);
}
// 學生類介面
public interface StudentService{
// SQL1:新增Student物件
public int addStudent(Student student);
// SQL2:根據SID刪除Student物件
public int deleteStudentById(Integer sid);
// SQL3:修改Student物件
public int updateStudent(Clazz clazz);
// SQL4:根據SID查詢Student物件
public Student selectStudentById(Integer cid);
// SQL5:查詢所有Student物件
public List<Student> selectAllStudent();
// SQL6:模糊查詢Student物件
public List<Student> selectStudentWhere(Student student);
// SQL7:多表聯查:查詢班級資訊及學員資訊
public Student selectClazzAndStudent(Integer sid);
// SQL8:包含查詢
public List<Student> selectStudentIn(Student student);
}
(4)物件/關係對映檔案
ClazzMapper.xml程式碼:
<mapper namespace=”com.zking.dao.ClazzService”>
<!--SQL1 :根據cid查詢Clazz,返回Clazz物件-->
<select id=”selectClazzById” parameterType=”Integer” resultMap=”clazzMapper”>
SELECT * FROM t_clazz WHERE cid=#{cid}
</select>
<!--對映Clazz物件的resultMap(結果對映集)-->
<resultMap id=”clazzMapper” type=”com.zking.pojo.Clazz”>
<id property=”cid” column=”CID” />
<result property=”code” column=”CODE” />
<result property=”name” column=”NAME” />
<!--一對多關聯對映:
Collection表示關聯的是集合
Property=”studentList”對應的是Clazz類中List<Student> studentList屬性名
ofType="com.zking.pojo.Student"表示對映的類為List<Student>中的Student
fetchType=”lazy”表示懶載入,即使用時才例項化
-->
<collection property="studentList" ofType="com.zking.pojo.Student" fetchType=”lazy”>
<id property=”sid” column=”SID” />
<!--<result>中出現的屬性、列名不一定全是類中的屬性,如果只查出要sid和name,那麼後面的sex,age都可以不用寫這裡的name,sex,age最好不要和上面<resultMap>中的name,sex,age名字重複property對應com.zking.pojo.Student實體類中的屬性,column對應表中的欄位名-->
<result property="name" column="name" />
<result property="sex" column="sex" />
<result property="age" column="age" />
</collection>
<!--寫法二:
將cid做為引數傳遞給com.zking.dao.StudentService.selectClazzStudent
-->
<collection property=”studentList” ofType=”com.zking.pojo.Student”
column=”cid” Select=”com.zking.dao.StudentService.selectClazzStudent”>
</collection>
</resultMap>
</mapper>
StudentMapper.xml程式碼:
<mapper namespace=”com.zking.dao.StudentService”>
<!--SQL1:根據id查詢Student,返回Student物件-->
<select id=”selectStudentById” parameterType=”Integer” resultMap=”studentMapper”>
SELECT * FROM t_student WHERE sid=#{sid}
</select>
<!--對映Student物件的resultMap(結果對映集)-->
<resultMap id=”studentMapper” type=”com.zking.pojo.Student”>
<id property=”sid” column=”sid” />
<result property=”name” column=”name” />
<result property=”sex” column=”sex” />
<result property=”age” column=”age” />
<!--多對一關聯對映:association
assoclation表示對映一個物件
-->
<association property="clazz" javaType="com.zking.pojo.Clazz">
<id property=”id” column=”id” />
<result property="code" column="code" />
<result property="name" column="name" />
</association>
<!--方式二:
將CLAZZ_CID做為引數傳遞給com.zking.dao.ClassService.selectClazzById
-->
<association property="clazz" javaType="com.zking.pojo.Clazz"
column=”CLAZZ_CID” select=”com.zking.dao.ClazzService.selectClazzById”>
</association>
</resultMap>
<!--SQL2:查詢所有Student物件-->
<select id=”selectAllStudent” resultType=”com.zking.pojo.Student”>
SELECT * FROM t_student
</select>
<!--SQL3:根據班級號查詢所有Student物件-->
<select id=”selectClazzStudent” paramerType=”Integer” resultType=”com.zking.pojo.Student”>
SELECT * FROM t_student WHERE Clazz_cid = #{Clazz.cid}
</select>
</mapper>
(5)測試
public class TestDemo{
private SqlSession sqlSession;
@Before
public void before(){
try {
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = sqlSessionFactory.openSession();
}catch(Exception e){
e.printStackTrace();
}
}
@After
public void after(){
sqlSession.commit();
sqlSession.close();
}
@Test
public void testClazz(){
ClazzDao clazzDao = sqlSession.getMapper(ClazzDao.class);
Clazz clazz = clazzDao.getClazzById(2);
System.out.println(clazz);
System.out.println(clazz.getId());
System.out.println(clazz.getCode());
System.out.println(clazz.getStudentList());
}
@Test
public void testStudent(){
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
Student student = studentDao.getStudentById(2);
System.out.println(student);
System.out.println(student.getName());
System.out.println(student.getSex());
System.out.println(student.getClazz().getCode());
}
}
2、多對多(ManyToMany)
在實際專案中,多對多是非常常見的關係。比如:課程管理中,一個學生對應多個課程,一個課程對應多個學生,他們之間多個一對多組成,就形成了多對多。
對於資料庫中多對多關係建議使用一個中間表來維護關係。
(1)建立資料庫
學生表 t_student:
create table t_student(
student_id INT PRIMARY KEY AUTO_INCREMENT,
student_name VARCHAR(10),
student_sex VARCHAR(10), #性別
student_major VARCHAR(10), #專業
student_grade VARCHAR(10) #年級
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
課程表 t_course:
create table t_course(
course_id INT PRIMARY KEY AUTO_INCREMENT, #課程ID
course_code VARCHAR(30), #課程編號
course_name VARCHAR(30) #課程名
)ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
學生vs課程關係表 t_student_course:
create table t_student_course (
student_id INT, #學生ID,FK
course_id INT, #課程ID,FK
CONSTRAINT fk_student_id FOREIGN KEY(student_id) REFERENCES t_student(student_id),
CONSTRAINT fk_course_id FOREIGN KEY(course_id) REFERENCES t_course(course_id)
)ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
(2)持久化類
學生實體Student:
public class Student {
private Integer studentID;
private String studentName; // 姓名
private String studentSex; // 性別
private String studentMajor; // 專業
private String studentGrade; // 年級
//一對多:即一個學生物件對應多個課程物件
private List<Course> courses; // 所選的課程
//省略getter和setter方法
//構造方法及toString()
}
課程實體Course:
public class Course {
private Integer courseID;
private String courseCode; //課程編號
private String courseName; //課程名稱
//一對多:即一個課程物件對應多個學生物件
private List<Student> students; //選課學生
//省略getter和setter方法
//構造方法及toString()
}
注意:關係表不需要建立實體類。
(3)介面
注意:在學習過程中,我們會為Student類建立StudentService介面,在該介面中指定Student類的CURD操作,會為Course類建立CourseService介面,在該介面中指定Course類的CURD操作。
為操作便捷,這裡我統一寫個介面:Many2ManyService,該介面負責Student類和Course類的CURD操作。
在com.zking.dao中建立實體類的介面:
public interface Many2ManyService {
//SQL1:插入student物件
public int addStudent(Student student);
//SQL2:插入course物件
public int addCourse(Course course);
//SQL3:根據student_id查詢學生
public Student selectStudentById(Integer student_id);
//SQL4:通過course_id查詢課程
public Course selectCourseById(Integer course_id);
//SQL5:學生x選課y
public int studentSelectCourse(Student student, Course course);
//SQL6:查詢比指定student_id值小的學生資訊
public List<Student> getStudentByIdOnCondition(Integer student_id);
//SQL7:查詢student級聯查詢出所選的course並且組裝成完整的物件
public Student getStudentByIdWithCourses(Integer course_id);
}
(4)物件/關係對映檔案
為Many2ManyService介面建立Mapper對映檔案,實現介面中的方法:
<mapper namespace="com.mybatis.mappers.Many2ManyService">
<!-- SQL1:插入student物件 -->
<insert id="addStudent" parameterType="Student">
INSERT INTO
t_student(student_name, student_sex, student_major, student_grade)
VALUES(
#{studentName},#{studentSex},#{studentMajor},#{studentGrade}
)
</insert>
<!-- SQL2:插入course物件 -->
<insert id="addCourse" parameterType="Course">
INSERT INTO
t_course(course_code, course_name)
VALUES(
#{courseCode}, #{courseName}
)
</insert>
<!--SQL: 新增關係表-->
<insert id="studentSelectCourse">
<!-- param1代表方法中第一個引數 以此類推 -->
INSERT INTO
t_student_course(student_id, course_id)
VALUES(
//第一個引數的student_id,第二個引數的course_id
#{param1.studentID}, #{param2.courseID}
)
</insert>
<!--SQL3:根據student_id查詢學生-->
<select id="selectStudentById" parameterType="Integer" resultType="Student">
SELECT
student_id, student_name, student_sex, student_major, student_grade
from
t_student
Where
student_id = #{studentID}
</select>
<!--SQL4:通過course_id查詢課程-->
<select id="selectCourseById" parameterType="Integer" resultType="Course">
SELECT
Course_id AS courseID, course_code AS courseCode, course_name AS courseName
FROM
t_course
Where
Course_Id = #{courseID}
</select>
<!--SQL5:學生x選課y-->
<insert id="studentSelectCourse">
<!-- param1代表方法中第一個引數 以此類推 -->
INSERT INTO
t_student_course(student_id, course_id)
VALUES(
//第一個引數的student_id,第二個引數的course_id
#{param1.studentID}, #{param2.courseID}
)
</insert>
<!-- 如果有特殊符號的話 需要用 <![CDATA[ 特殊符號 ]]> 例如 < & 等等 -->
<select id="getStudentByIdOnCondition" parameterType="Integer" resultType="Student">
<![CDATA[
SELECT
student_id, student_name, student_sex, student_major, student_grade
FROM
t_student
WHERE
student_id < #{studentID}
]]>
</select>
<!-- 這裡使用了巢狀結果ResultMap的方式進行級聯查詢,當然也可以使用巢狀查詢select -->
<!-- 對映一個基本的Student查詢結果 -->
<resultMap id="StudentResult" type="Student">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="gender" column="gender"/>
<result property="major" column="major"/>
<result property="grade" column="grade"/>
</resultMap>
<!-- 繼承上面那個基本的對映,再擴充套件出級聯查詢 -->
<resultMap id="StudentResultWithCourses" type="Student" extends="StudentResult">
<collection property="courses" resultMap="CourseResult"></collection>
</resultMap>
<!-- 這裡特別是column="cid"是和select語句中的 c.id as cid對應的 一定一定一定要對應起來 -->
<resultMap id="CourseResult" type="Course">
<id property="id" column="cid"/>
<result property="courseCode" column="course_code"/>
<result property="courseName" column="course_name"/>
</resultMap>
<!--
注意:查詢語句的中的c.id as cid這個地方,避免名字相同出現查詢結果不正確的情況
同時在id="CourseResult"的resultMap中也有與這裡對應的設定要特別特別注意
-->
<select id="getStudentByIdWithCourses" parameterType="Integer" resultMap="StudentResultWithCourses">
SELECT
s.id, s.name, s.gender, s.major, s.grade, c.id AS cid, c.course_code, c.course_name, sc.id, sc.student_id, sc.course_id
FROM
student s, course c, student_course sc
WHERE
s.id=#{id} AND s.id=sc.student_id AND sc.course_id=c.id
</select>
</mapper>
(5)測試
public class Many2ManyServiceTest {
private SqlSession sqlSession;
Private Many2ManyService mapper;
@Before
public void before(){
try {
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = sqlSessionFactory.openSession();
// 使用sqlsession獲得對映介面的實現類物件,介面的引用指向實現類的物件
mapper = sqlSession.getMapper(Many2ManyService.class);
}catch(Exception e){
e.printStackTrace();
}
}
@After
public void after(){
sqlSession.commit();
sqlSession.close();
}
@Test
public void test_insertStudent() {
Student student = new Student(1,"Suwu150","男","計算機","21");
mapper.addStudent(student);
session.commit();
System.out.println("執行完畢");
}
@Test
public void test_insertCourse(){
SqlSession session=null;
session = MyBatisSqlSessionFactory.openSession();//使用封裝之後的類
// 使用sqlsession獲得對映介面的實現類物件,介面的引用指向實現類的物件
Many2ManyMapper mapper = session.getMapper(Many2ManyMapper.class);
mapper.insertCourse(new Course(1,"001","corejava"));
mapper.insertCourse(new Course(2,"002","oracle"));
session.commit();
System.out.println("執行完畢");
}
@Test
public void test_selectStudentById(){
SqlSession session=null;
session = MyBatisSqlSessionFactory.openSession();//使用封裝之後的類
// 使用sqlsession獲得對映介面的實現類物件,介面的引用指向實現類的物件
Many2ManyMapper mapper = session.getMapper(Many2ManyMapper.class);
Student student = mapper.selectStudentById(2);
System.out.println(student);
System.out.println("執行完畢");
}
@Test
public void test_selectCourseById(){
SqlSession session=null;
session = MyBatisSqlSessionFactory.openSession();//使用封裝之後的類
// 使用sqlsession獲得對映介面的實現類物件,介面的引用指向實現類的物件
Many2ManyMapper mapper = session.getMapper(Many2ManyMapper.class);
Course course = mapper.selectCourseById(2);
System.out.println(course);
System.out.println("執行完畢");
}
@Test
public void test_studentSelectCourse(){
SqlSession session=null;
session = MyBatisSqlSessionFactory.openSession();//使用封裝之後的類
// 使用sqlsession獲得對映介面的實現類物件,介面的引用指向實現類的物件
Many2ManyMapper mapper = session.getMapper(Many2ManyMapper.class);
Student student=new Student();
Course course=new Course();
student.setId(2);
course.setId(1);
mapper.studentSelectCourse(5, student, course);
session.commit();
}
@Test
public void test_getStudentByIdOnCondition(){
SqlSession session=null;
session = MyBatisSqlSessionFactory.openSession();//使用封裝之後的類
// 使用sqlsession獲得對映介面的實現類物件,介面的引用指向實現類的物件
Many2ManyMapper mapper = session.getMapper(Many2ManyMapper.class);
List<Student> list = mapper.getStudentByIdOnCondition(3);
System.out.println(list);
}
@Test
public void test_getStudentByIdWithCourses(){
SqlSession session=null;
session = MyBatisSqlSessionFactory.openSession();//使用封裝之後的類
// 使用sqlsession獲得對映介面的實現類物件,介面的引用指向實現類的物件
Many2ManyMapper mapper = session.getMapper(Many2ManyMapper.class);
Student student = mapper.getStudentByIdWithCourses(2);
System.out.println(student);
}
}
相關文章
- Hibernate 的關聯關係對映
- Mybatis實體關聯對映MyBatis
- JPA關係對映系列四:many-to-many 關聯對映
- MyBatis加強(1)~myBatis物件關係對映(多對一關係、一對多關係)、延遲/懶載入MyBatis物件
- JPA關係對映系列五:many-to-many 關聯表存在額外欄位關係對映
- MyBatis實現一對一關聯對映MyBatis
- python 關係對映Python
- day07-MyBatis的關聯對映01MyBatis
- java物件關係對映ROMJava物件
- JavaEE MyBatis關聯對映之多對多(教材學習筆記)JavaMyBatis筆記
- 淺談Mybatis中是如何實現這種多表關係的對映MyBatis
- Hibernate (開源物件關係對映框架)物件框架
- Spring Boot 入門系列(二十八) JPA 的實體對映關係,一對一,一對多,多對多關係對映!Spring Boot
- CRM和ERP的Sales Organization的對映關係
- 表的關聯關係
- python 類關聯關係Python
- TiDB從關係模型對映到key-value(圖)TiDB模型
- Mybatis【15】-- Mybatis一對一多表關聯查詢MyBatis
- Spring Data JPA 之 一對一,一對多,多對多 關係對映Spring
- ERP的Account group和CRM partner group的對映關係
- Verilog程式碼和FPGA硬體的對映關係(五)FPGA
- Verilog程式碼和FPGA硬體的對映關係(四)FPGA
- JPA(3) 表關聯關係(多對一、一對多、多對多、一對一)
- MyBatis表關聯 一對多 多對一 多對多MyBatis
- C# 資料操作系列 - 6 EF Core 配置對映關係C#
- 【新包】根據 appends 配置的關聯欄位對映關係,自動維護需要的 appends - Laravel Eloquent Append AutomationAPPLaravel
- 體系結構、指令定址、對映關係、系統可靠性
- 【Mybatis之sql複習】多表關係MyBatisSQL
- 物件導向程式設計程式碼詳解(依賴關係,關聯關係,組合關係)物件程式設計
- Mybatis結果對映MyBatis
- Hibernate中實體類對映檔案表與表的關係模版
- Fluent API 配置實體和資料庫之間的對映關係API資料庫
- 8 張圖掌握 Laravel 的 Eloquent 關聯關係Laravel
- Mybatis 基礎xml對映MyBatisXML
- 3分鐘短文:說說Laravel模型關聯關係最單純的“一對一”Laravel模型
- 多對多關係自行維護單項關聯數量,加快分頁查詢
- 物聯網與APP的關係?APP
- MyBatis初級實戰之六:一對多關聯查詢MyBatis