【場景】在實際開發中,實體類之間有一對1、一對多、多對多的關係,因此須要正確配置它們對應關係,Mybatis經過配置文件可以從數據庫中獲取列數據後自動封裝成對象。html
以每一個學生有一個地址爲例:java
public class Address
{
private Integer addrId;
private String street;
private String city;
private String state;
private String zip;
private String country;
// setters & getters
}sqlpublic class Student
{
private Integer studId;
private String name;
private String email;
private PhoneNumber phone;
private Address address;
//setters & getters
}數據庫
須要在對應的maper.xml文件裏定義它們的映射關係。經常使用的幾種方式以下: app
這種方式就是定義一個繼承自Student類型的ResultMap,而後將對應須要包含的address信息給映射進去。原有Student的映射定義以下:性能
<resultMap type="Student" id="StudentResult"> spa
<id property="studId" column="stud_id"/> xml
<result property="name" column="name" /> htm
<result property="email" column="email"/> 對象
<result property="phone" column="phone"/>
</resultMap>
繼承Student的定義以下:
<resultMap type="Student" id="StudentWithAddressExtResult" extends="StudentResult">
<result property="address.addrId" column="addr_id"/>
<result property="address.street" column="street"/>
<result property="address.city" column="city"/>
<result property="address.state" column="state"/>
<result property="address.zip" column="zip"/>
<result property="address.country" column="country"/>
</resultMap>
至關於把address的對應屬性和表裏的字段映射給單獨定義在一個地方映射起來。查找語句能夠根據以下定義:
<select id="selectStudentWithAddress" parameterType="int" resultMap="StudentWithAddressExtResult">
select stud_id, name, email,phone, a.addr_id, street, city, state, zip, country
FROM STUDENTS s left outer join ADDRESSES a on s.addr_id=a.addr_id
where stud_id=#{studId}
</select>
對應的mapper接口定義以下:
public interface StudentMapper {
Student selectStudentWithAddress(int id);
}
StudentService裏定義相關的方法以下:
public Student findStudentWithAddressById(int id) {
SqlSession sqlSession = MyBatisUtil.getSqlSessionFactory().openSession();
try {
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
return studentMapper.selectStudentWithAddress(id);
} finally {
sqlSession.close();
}
}
驗證:
public static void main( String[] args ) {
StudentService studService = new StudentService();
Student student1 = studService.findStudentWithAddressById(1);
System.out.println(student1);
}
輸出結果:
Student [studId=1, name=Timothy, email=timothy@gmail.com, phone=123-123-1234, address=Address [addrId=3, street=710 N Cable Rd, city=Lima, state=OH, zip=45825, country=Allen]]
在一些狀況下,咱們已經定義了Address的映射ResultMap,若是再在這裏從新定義一遍,就顯得比較冗餘了。
若是咱們已經定義好了Address的映射,假設它的定義以下:
<mapper namespace="com.yunzero.map.mappers.AddressMapper">
<resultMap type="Address" id="AddressResult">
<id property="addrId" column="addr_id"/>
<result property="street" column="street"/>
<result property="city" column="city"/>
<result property="state" column="state"/>
<result property="zip" column="zip"/>
<result property="country" column="country"/>
</resultMap>
<select id="selectAddressById" parameterType="int" resultMap="AddressResult">
select * from ADDRESSES where addr_id=#{addrId}
</select>
</mapper>
對應的Student ResultMap就須要修改以下:
<resultMap type="Student" id="StudentWithAddressResult">
<id property="studId" column="stud_id"/>
<result property="name" column="name"/>
<result property="email" column="email"/>
<result property="phone" column="phone"/>
<association property="address" resultMap="com.yunzero.map.mappers.AddressMapper.AddressResult"/>
</resultMap>
定義了一個association的屬性,而後將對應的resultMap指向對應的AddressResult。這裏定義的AddressResult是定義在另一個文件以及命名空間裏,因此須要引用它的全名。
<resultMap type="Student" id="StudentWithAddressNestedSelect">
<id property="studId" column="stud_id"/>
<result property="name" column="name"/>
<result property="email" column="email"/>
<result property="phone" column="phone"/>
<association property="address" column="addr_id" select="com.yunzero.map.mappers.AddressMapper.selectAddressById"/>
</resultMap>
在association裏指定column字段,它做爲嵌入select語句裏對應的參數。
<resultMap type="Student" id="StudentWithAddressNestedResultMap">
<id property="studId" column="stud_id"/>
<result property="name" column="name"/>
<result property="email" column="email"/>
<association property="address" javaType="Address">
<id property="addrId" column="addr_id"/>
<result property="street" column="street"/>
<result property="city" column="city"/>
<result property="state" column="state"/>
<result property="zip" column="zip"/>
<result property="country" column="country"/>
</association>
</resultMap>
以一個教師有多門課程爲例:
public class Course
{
private Integer courseId;
private String name;
private String description;
private Date startDate;
private Date endDate;
private Integer tutorId;
//setters & getters
}
public class Tutor
{
private Integer tutorId;
private String name;
private String email;
private Address address;
private List<Course> courses;
// setters & getters
}
須要在對應的maper.xml文件裏定義它們的映射關係。經常使用的幾種方式以下:
關於課程的配置以下:
<mapper namespace="com.yunzero.map.mappers.CourseMapper">
<resultMap type="Course" id="CourseResult">
<id column="course_id" property="courseId"/>
<result column="name" property="name"/>
<result column="description" property="description"/>
<result column="start_date" property="startDate"/>
<result column="end_date" property="endDate"/>
</resultMap>
<select id="selectCoursesByTutor" parameterType="int" resultMap="CourseResult">
select * from COURSES where tutor_id=#{tutorId}
</select>
</mapper>
關於教師的配置以下:
<resultMap type="Tutor" id="TutorWithCoursesNestedResult">
<id column="tutor_id" property="tutorId"/>
<result column="tutor_name" property="name"/>
<result column="email" property="email"/>
<association property="address" resultMap="com.yunzero.map.mappers.AddressMapper.AddressResult"/>
<collection property="courses" resultMap="com.yunzero.map.mappers.CourseMapper.CourseResult" />
</resultMap>
對於多個course,它須要使用collection屬性,並指定對應的CourseResult。
對應的查詢語句以下:
<select id="selectTutorById" parameterType="int" resultMap="TutorWithCoursesNestedResult">
SELECT t.tutor_id, t.name as tutor_name, email, a.addr_id, street, city, state, zip, country,
course_id, c.name, description, start_date, end_date
FROM TUTORS t left outer join ADDRESSES a on t.addr_id=a.addr_id
left outer join COURSES c on t.tutor_id=c.tutor_id
where t.tutor_id=#{tutorId}
</select>
對應的mapper接口和TutorService的實現以下:
public interface TutorMapper {
Tutor selectTutorById(int tutorId);
}
public Tutor findTutorById(int tutorId) {
SqlSession sqlSession = MyBatisUtil.getSqlSessionFactory().openSession();
try {
TutorMapper mapper = sqlSession.getMapper(TutorMapper.class);
return mapper.selectTutorById(tutorId);
}
finally {
sqlSession.close();
}
}
<resultMap type="Tutor" id="TutorWithCoursesNestedSelect">
<id column="tutor_id" property="tutorId"/>
<result column="tutor_name" property="name"/>
<result column="email" property="email"/>
<association property="address" resultMap="com.yunzero.map.mappers.AddressMapper.AddressResult"/>
<collection property="courses" column="tutor_id" select="com.yunzero.map.mappers.CourseMapper.selectCoursesByTutor"/>
</resultMap>
<select id="selectTutorWithCourses" parameterType="int" resultMap="TutorWithCoursesNestedSelect">
SELECT t.tutor_id, t.name as tutor_name, email, a.addr_id, street, city, state, zip, country
FROM TUTORS t left outer join ADDRESSES a on t.addr_id=a.addr_id
where t.tutor_id=#{tutorId}
</select>
這種方式和前面那種方式的差異在於它將查找對應course的方法委派給對應course的映射定義裏,因此這裏值須要考慮它和address的映射就能夠了。而前面經過兩個鏈接操做至關於將全部結果都返回來了,就不須要再去利用別的查詢。固然,由於是一對多的映射牽涉到返回多個結果,這種方式可能須要執行屢次查詢,有可能致使性能的問題。
https://www.cnblogs.com/zhaopengcheng/p/7094880.html
http://shmilyaw-hotmail-com.iteye.com/blog/2357862