自動對映
MyBatis 會獲取結果中返回的列名並在 Java 類中查詢相同名字的屬性(忽略大小寫)。 這意味著如果發現了資料庫中的 ID 列和Java類中的 id 屬性,MyBatis 會將列 ID 的值賦給 id 屬性。
通常資料庫列使用大寫字母組成的單詞命名,單詞間用下劃線分隔;而 Java 屬性一般遵循駝峰命名法約定。為了在這兩種命名方式之間啟用自動對映,需要將mapUnderscoreToCamelCase
設定為 true。
<settings>
<!--開啟自動駝峰命名規則對映, 如果資料庫欄位為user_email, MyBatis會自動將其對映到Javabean中的userEmail屬性-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
resultType
透過resultType設定返回結果型別,基本資料型別與POJO類似,下面只演示POJO。
返回單個或者多個
- 透過
username
查詢單個使用者
介面定義如下
public User getUserByUserName(String userName);
介面對應的 Mapper.xml 定義如下所示
<select id="getUserByUserName"
parameterType="String"
resultType="com.example.mybatis.entity.User">
select
id, username, user_email userEmail, user_city userCity, age
from user
where username = #{username}
</select>
- 透過
username
查詢多個使用者
介面定義如下
public List<User> getUserListByUserName(String userName);
介面對應的 Mapper.xml 定義如下所示
<select id="getUserListByUserName"
parameterType="String"
resultType="com.example.mybatis.entity.User">
select
id, username, user_email userEmail, user_city userCity, age
from user
where username = #{username}
</select>
有時候需要將返回的List封裝在一個Map裡面,並使用實體類的某個欄位作為Map的key
介面定義如下
@MapKey("id")
public Map<String, User> getUserListByUserName(String userName);
介面對應的 Mapper.xml 定義如下所示
<select id="getUserListByUserName"
parameterType="String"
resultType="map">
select
id, username, user_email userEmail, user_city userCity, age
from user
where username = #{username}
</select>
resultMap
有時候透過駝峰命名規則並不能對映到我們想要的JavaBean屬性,就可以使用resultMap來實現高階結果集對映。
比如有一張user表裡面有id、user_email、user_city這三個欄位,有一個userVO
實體類有如下幾個屬性
public class UserVO {
private Integer id;
private String email;
private String city;
// 省略get、set方法
}
現在需要使用MyBatis將user資訊查詢出來並對映到userVO
實體類
介面定義如下
public UserVO getUserInfoById(Integer id);
介面對應的 Mapper.xml 定義如下所示
<resultMap id="userVO" type="com.example.mybatis.entity.UserVO">
<!--
指定主鍵類的封裝規則
id定義主鍵,底層會有一些最佳化
column指定資料路的列
property指定對應的JavaBean屬性
-->
<id column="id" property="id" />
<!--定義普通列的封裝-->
<result column="user_email" property="email" />
<result column="user_city" property="city" />
</resultMap>
<select id="getUserInfoById" resultMap="userVO">
select * from user where id = #{id}
</select>
多表關聯查詢
實際開發中不可能只是對單表進行操作,一定會涉及到多表關聯查詢,資料表之間的關係有三種:一對一關係、一對多關係、多對多關係。
一對一
一個學生對應一個班級,而一個班級可以對應多個學生。
CREATE TABLE `t_classes` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(11) DEFAULT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `t_student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(11) DEFAULT NULL,
`cid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `cid` (`cid`),
CONSTRAINT `student_ibfk` FOREIGN KEY (`cid`) REFERENCES `t_classes` (`id`)
);
實體類
public class Classes {
private Integer id;
private String name;
private List<Student> students;
}
public class Student {
private Integer id;
private String name;
private Classes classes;
}
透過學生id查詢學生資訊,並且把學生班級資訊一起查詢出來。
介面定義如下
public Student getStudentById(Integer id);
介面對應的 Mapper.xml 定義如下所示
<resultMap id="studentResultMap" type="Student">
<id column="sid" property="id" />
<result column="sname" property="name" />
<!-- 對映 classes 屬性 -->
<association property="classes" javaType="com.example.mybatis.entity.Classes">
<id column="cid" property="id" />
<result column="cname" property="name" />
</association>
</resultMap>
<select id="getStudentById" resultMap="studentResultMap">
select s.id sid,s.name sname, c.id cid, c.name cname
from t_student s , t_classes c
where s.cid = c.id
and s.id = #{id}
</select>
將上面的查詢語句修改為分步查詢、延遲查詢
<resultMap id="studentResultMap" type="com.example.mybatis.entity.Student">
<id column="id" property="id" />
<result column="name" property="name" />
<!--
對映 classes 屬性
property: 對映到JavaBean中的屬性
column: 指定某個列的值傳遞到 select 中的方法
select: 表名當前屬性是呼叫select指定的方法查出的結果
如果是呼叫當前mapper中的方法, 則直接填寫要呼叫方法的id就行了
如果是呼叫其它mapper中的方法, 則需要這樣填寫com.xxx.mapper.XxxMapper.getClassesById
fetchType: lazy-> 懶載入、eager-> 全部載入,
如果設定了懶載入模式, 那麼當獲取classes屬性時才會從資料庫中載入classes資料出來
javaType: 對映實體類
-->
<association property="classes"
column="cid"
select="getClassesById"
javaType="com.example.mybatis.entity.Classes"
fetchType="lazy">
<id column="id" property="id" />
<result column="name" property="name" />
</association>
</resultMap>
<select id="getStudentById" resultMap="studentResultMap">
select s.id,s.name,s.cid
from t_student s
where s.id = #{id}
</select>
<select id="getClassesById" resultType="com.example.mybatis.entity.Classes">
select c.id,c.name from t_classes c where c.id = #{id}
</select>
一對多
現在反過來查詢 Classes,將級聯的所有 Student 一併查詢。
介面定義如下
public Classes getClassesById(Integer id);
介面對應的 Mapper.xml 定義如下所示
<resultMap id="classesResultMap" type="com.example.mybatis.entity.Classes">
<id column="cid" property="id" />
<result column="cname" property="name" />
<collection property="students" ofType="com.example.mybatis.entity.Student">
<id column="sid" property="id" />
<result column="sname" property="name"/>
</collection>
</resultMap>
<select id="getClassesById" resultMap="classesResultMap">
select s.id sid,s.name sname, c.id cid, c.name cname
from t_student s , t_classes c
where s.cid = c.id
and c.id = #{id}
</select>
需要注意的是 association 標籤,透過設定 javaType 屬性,對映實體類,collection 標籤,透過設定 ofType 屬性對映實體類。
將上面查詢修改成分步查詢、延遲查詢
<resultMap id="classesResultMap" type="com.example.mybatis.entity.Classes">
<id column="cid" property="id" />
<result column="cname" property="name" />
<!--
這裡的column只傳遞了一個欄位,如果想傳入多個欄位可以這樣寫
column="{key1=column1, key2=column2}"
相當於封裝成了一個Map, 當前查詢可以這樣寫column="{id=cid}"
-->
<collection
fetchType="lazy"
property="students"
select="getStudentByClassesId"
column="cid">
</collection>
</resultMap>
<select id="getClassesById" resultMap="classesResultMap">
select c.id cid, c.name cname
from t_classes c
where c.id = #{id}
</select>
<select id="getStudentByClassesId" resultType="com.example.mybatis.entity.Student">
select s.id , s.name from t_student s where s.cid = #{id}
</select>
多對多
多對多其實是雙向的一對多關係,所以雙方都是用 collection 標籤設定級聯,與上面的一對多是類似的。
本作品採用《CC 協議》,轉載必須註明作者和本文連結