1. MyBatis中的連接池與事務(wù)控制
連接池 : 在實(shí)際開發(fā)中都會使用連接池,因?yàn)樗梢詼p少獲取連接所消耗的時間。
連接池是用于存儲連接的容器;
容器其實(shí)就是一個集合對象,,該集合必須是線程安全的,不能兩個線程拿到同一個連接;
該集合還必須實(shí)現(xiàn)隊(duì)列的特性:先進(jìn)先出。
1.1 MyBatis中的連接池
1.1.1 MyBatis連接池提供了3種方式的配置
- 配置位置:
主配置文件SqlMapConfig.xml中的dataSource標(biāo)簽,type屬性就是表示采用何種連接池方式。
- dataSource 標(biāo)簽中 type 屬性的取值:
POOLED :采用傳統(tǒng)javax.sql.DataSource規(guī)范中的連接池,MyBatis中有針對規(guī)范的實(shí)現(xiàn)。
UNPOOLED: 采用傳統(tǒng)的獲取連接的方式,雖然也實(shí)現(xiàn)了 javax.sql.DataSource接口,但是沒有池的思想。
JNDI:采用服務(wù)器提供的JNDI技術(shù)實(shí)現(xiàn)來獲取DataSource對象,不同的服務(wù)器所能拿到的DataSource是不一樣的,同時涂如果不是Web或者M(jìn)aven的war工程是不能使用的。我們實(shí)際開發(fā)中使用的是Tomcat服務(wù)器。采用的連接池就是DBCP連接池。
1.2 MyBatis中的事務(wù)
1.2.1 什么是事務(wù)?
如果一個包含多個步驟的業(yè)務(wù)操作被事務(wù)管理,那么這些操作要么同時成功要么同時失敗。
案例 : 張三給李四轉(zhuǎn)錢 。 第一步是查詢張三賬戶余額是否大于 500 。 第二步張三賬戶減 500 。 第三步李四賬戶加500。如果當(dāng)執(zhí)行到第二步的時候出現(xiàn)異常,下面的步驟將不會再執(zhí)行。如果該操作已經(jīng)被事務(wù)管理,這三步操作,要么同時成功要么就同時失敗。如果中間出現(xiàn)異常,將出現(xiàn)回滾操作。如果沒有出現(xiàn)異常將提交事務(wù)。
1.2.2 事務(wù)的四大特性?
原子性: 事務(wù)是原子性的,原子是不可再分割的最小單位。要么同時成功要同時失敗。是不可分割的最小操作單位。
持久性:當(dāng)事務(wù)提交或者回滾之后,數(shù)據(jù)庫會持久化的保存數(shù)據(jù)。
隔離性:多個事務(wù)之間相互獨(dú)立。
一致性:事務(wù)操作前后數(shù)據(jù)總量不變 。
1.2.3 不考慮隔離性會產(chǎn)生的 3個 問題
臟讀:個事務(wù) ,讀取到另一個事務(wù)中沒有提交的數(shù)據(jù) 。
不可重復(fù)讀: 在同一個事務(wù)中兩次讀取到的數(shù)據(jù)不一樣。
幻讀:一個事務(wù)去操作(DML增刪改)數(shù)據(jù)表中所有數(shù)據(jù) , 另一個事務(wù)添加了一條數(shù)據(jù),則第一個事務(wù)查詢不到自己的修改。
1.2.4 解決辦法:四種隔離級別
read uncommitted : 讀未提交 。會產(chǎn)生的問題 是 臟讀 、 不可重復(fù)度 、幻讀 。
read committed(Oracle默認(rèn)的隔離級別) : 讀已提交 。 會產(chǎn)生的問題 是 不可重復(fù)讀 、 幻讀。
repeatable read(Mysql默認(rèn)) :可重復(fù)讀。 會產(chǎn)生的問題是 幻讀。
serializable : 串行化 。 可以解決所有的問題。
1.2.5 MyBatis中的事務(wù)是怎么樣的
- 它是通過SqlSession對象的commit方法和rollback方法實(shí)現(xiàn)事務(wù)的提交和回滾操作。
1.2.6 MyBatis中事務(wù)提交的方式
- 在MyBatis中事務(wù)的提交方式默認(rèn)是手動提交事務(wù)。
按照之前的方式創(chuàng)建一個新的Maven項(xiàng)目進(jìn)行測試。直接復(fù)制使用代理dao方式實(shí)現(xiàn)CRUD項(xiàng)目進(jìn)行修改。
創(chuàng)建好的項(xiàng)目碼云地址 : https://gitee.com/lpzzzz/mybatis_datasource-tx_demo06
通過打印的日志查看MyBatis中事務(wù)的提交方式

- 設(shè)置MyBatis事務(wù)提交的方式為自動提交


2. MyBatis的動態(tài)SQL語句
- 創(chuàng)建一個新的項(xiàng)目,復(fù)制上面數(shù)據(jù)庫連接池和事務(wù)的項(xiàng)目。進(jìn)行修改。刪除不相關(guān)的增刪改方法。
2.1 if 標(biāo)簽
- 創(chuàng)建一個根據(jù)用戶條件進(jìn)行查詢的接口方法。
/**
* 根據(jù)指定的查詢條件進(jìn)行查詢
* @param user
* @return
*/
List<User> selectUserByCondition(User user);
- 在映射配置文件中編寫sql實(shí)現(xiàn)查詢,使用 if 標(biāo)簽拼接滿足條件的查詢條件 。需要使用 where 1 = 1 這個恒成立條件進(jìn)行拼接操作。
<!--根據(jù)查詢條件進(jìn)行查詢-->
<select id="selectUserByCondition" parameterType="user" resultMap="userMap">
select * from user where 1 = 1
<if test="userName != null">
and username = #{userName}
</if>
</select>
- 編寫測試類進(jìn)行測試 :
/**
* 根據(jù)條件查詢 User
*/
@Test
public void selectUserByCondition() {
User u = new User();
u.setUserName("老王");
List<User> users = userDao.selectUserByCondition(u);
for (User user : users) {
System.out.println(user);
}
}
2.2 Where 標(biāo)簽
where 標(biāo)簽的作用 : 就是不需要再加上 一個where 1 =1 恒成立的條件。
修改如下 :
<!--使用where標(biāo)簽之后不需要再加上 where 1 = 1 的恒成立條件-->
<select id="selectUserByCondition" resultMap="userMap" parameterType="user">
select * from user
<where>
<if test="userName != null">
and username = #{userName}
</if>
<if test="userSex != null">
and sex = #{userSex}
</if>
</where>
</select>
2.3 foreach 標(biāo)簽
- 需求:使用 in 進(jìn)行子查詢
- 在QueryVo 中添加一個 ids 屬性,并重新生成 getter和 setter方法 :
/**
* 實(shí)體包裝類對象
*/
public class QueryVo {
private User user;
private List<Integer> ids;
// 省略 getter 和 setter 方法
}
- 編寫根據(jù)ids 查詢user的 接口方法
/**
* 根據(jù)ids 查詢用戶信息
* @param queryVo
* @return
*/
List<User> selectUserByIds(QueryVo queryVo);
- 在UserDao.xml映射配置文件中編寫sql如下 :
<!--使用foreach標(biāo)簽實(shí)現(xiàn)子查詢 注意這里的參數(shù)類型 需要實(shí)體類在domain包下 這樣package 標(biāo)簽才能掃描到 否則就需要重新再加一個package包掃描。指定實(shí)體所在包 -->
<select id="selectUserByIds" resultMap="userMap" parameterType="queryvo">
select * from user
<where>
<if test="ids != null and ids.size() > 0">
<foreach collection="ids" open="and id in (" close=")" item="uid" separator=",">
#{uid}
</foreach>
</if>
</where>
</select>
由于我的QueryVo 實(shí)體不是在domain下 ,所以需要在全局配置文件中加上 package標(biāo)簽 配置條件實(shí)體所在的包路徑。掃描該實(shí)體 :
<typeAliases> <package name="com.lyp.vo"/> </typeAliases>
- 編寫測試類進(jìn)行測試 :
/**
* 根據(jù) ids 進(jìn)行查詢
*/
@Test
public void selectUserByIds() {
QueryVo vo = new QueryVo();
List<Integer> ids = new ArrayList<Integer>();
ids.add(41);
ids.add(42);
ids.add(43);
vo.setIds(ids);
List<User> users = userDao.selectUserByIds(vo);
for (User user : users) {
System.out.println(user);
}
}
- foreach標(biāo)簽屬性 :
collection:代表要遍歷的集合元素,注意編寫時不要寫#{}
open:代表語句的開始部分
close:代表結(jié)束部分
item:代表遍歷集合的每個元素,生成的變量名
sperator:代表分隔符
2.4 使用 sql 標(biāo)簽抽取重復(fù)的 sql
- 可以抽取經(jīng)常使用的 字段片段、使用頻繁的sql語句 。
<!--對文件中常使用的sql片段和使用頻繁的sql抽取出來-->
<sql id="sqlFields">
id, username,birthday,sex,address
</sql>
<!---使用include根據(jù)id進(jìn)行引用-->
<select id="findAll" resultMap="userMap">
<!-- select id as userId , username as userName , birthday as userBirthday ,sex as userSex , address as userAddress from user;-->
select <include refid="sqlFields"/> from user;
</select>

2.5 項(xiàng)目地址
- 碼云項(xiàng)目地址 : MyBatis中if 、where、 foreach、sql標(biāo)簽的使用
3. MyBatis中的多表操作
3.1 表之間的關(guān)系有幾種 ?
3.1.1 一對一
- 一個人只能有一個身份證號。一個身份證號只能屬于一個人。
3.1.2 一對多
- 用戶和訂單是一對多。
3.1.3 多對一
- 訂單和用戶是多對一的關(guān)系。
3.1.4 多對多
- 老師和學(xué)生就是多對多的關(guān)系。
3.1.5 特例
- 如果拿出每一個訂單,它只屬于一個用戶。所以MyBatis就將多對一看成是 一對一。
3.2 MyBatis中的多表查詢操作
3.2.1 步驟
首先,建立兩張表。用戶表、賬戶表。
建立兩個實(shí)體類,用戶實(shí)體類和賬戶實(shí)體類。
建立兩個配置文件:用戶配置文件、賬戶配置文件。
實(shí)現(xiàn)配置:當(dāng)我們查詢用戶時,可以同時得到用戶下包含的賬戶信息。當(dāng)我們查詢賬戶時,可以同時得到賬戶所屬的用戶信息。
3.2.2 創(chuàng)建Account 和 User 表
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL auto_increment,
`username` varchar(32) NOT NULL COMMENT '用戶名稱',
`birthday` datetime default NULL COMMENT '生日',
`sex` char(1) default NULL COMMENT '性別',
`address` varchar(256) default NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `user`(`id`,`username`,`birthday`,`sex`,`address`) values (41,'老王','2018-02-27 17:47:08','男','北京'),(42,'小二王','2018-03-02 15:09:37','女','北京金燕龍'),(43,'小二王','2018-03-04 11:34:34','女','北京金燕龍'),(45,'傳智播客','2018-03-04 12:04:06','男','北京金燕龍'),(46,'老王','2018-03-07 17:37:26','男','北京'),(48,'小馬寶莉','2018-03-08 11:44:00','女','北京修正');
DROP TABLE IF EXISTS `account`;
CREATE TABLE `account` (
`ID` INT(11) NOT NULL COMMENT '編號',
`UID` INT(11) DEFAULT NULL COMMENT '用戶編號',
`MONEY` DOUBLE DEFAULT NULL COMMENT '金額',
PRIMARY KEY (`ID`),
KEY `FK_Reference_8` (`UID`),
CONSTRAINT `FK_Reference_8` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `account`(`ID`,`UID`,`MONEY`) VALUES (1,46,1000),(2,45,1000),(3,46,2000);
3.2.3 創(chuàng)建項(xiàng)目
重新創(chuàng)建一個項(xiàng)目進(jìn)行一對多查詢。
復(fù)制之前項(xiàng)目的依賴到 pom.xml文件中 。
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
</dependencies>
3.2.4 創(chuàng)建實(shí)體類和接口
- 創(chuàng)建User實(shí)體類 和 UserDao接口 。創(chuàng)建Account賬戶實(shí)體類和AccountDao接口。

3.2.5 在resources 類路徑下創(chuàng)建全局配置文件 SqlMapConfig.xml文件
- 在resources 類路徑下創(chuàng)建一個名為SqlMapConfig.xml的配置文件 :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties
url="file:///D:/work/idea-core/2020_08_29_Mybatis/mybatis_demo_CRUD_04/src/main/resources/jdbcConfiguration.properties"/>
<typeAliases>
<!--使用typeAlias 標(biāo)簽指定實(shí)體類的別名 簡化書寫-->
<!--<typeAlias type="com.lyp.domain.User" alias="user"/>-->
<!--使用package標(biāo)簽指定實(shí)體類的包名-->
<package name="com.lyp.domain"/>
<package name="com.lyp.vo"/>
</typeAliases>
<!--配置環(huán)境-->
<environments default="mysql">
<!--配置MySQL-->
<environment id="mysql">
<!--配置數(shù)據(jù)庫的事務(wù)-->
<transactionManager type="JDBC"></transactionManager>
<!--配置連接池-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--<mapper resource="com/lyp/dao/UserDao.xml"/>-->
<!--使用package標(biāo)簽指定持久層接口所在包-->
<package name="com.lyp.dao"/>
</mappers>
</configuration>
3.2.6 創(chuàng)建UserDao.xml 和AccountDao.xml配置文件。
- 在resources下創(chuàng)建 與 持久層接口包對應(yīng)目錄的 UserDao.xml 和AccountDao.xml配置文件。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lyp.dao.UserDao">
<!--對文件中常使用的sql片段和使用頻繁的sql抽取出來-->
<sql id="sqlFields">
id, username,birthday,sex,address
</sql>
<select id="findAll" resultType="user">
<!-- select id as userId , username as userName , birthday as userBirthday ,sex as userSex , address as userAddress from user;-->
select <include refid="sqlFields"/> from user;
</select>
<!--根據(jù)id查詢用戶信息-->
<select id="findById" parameterType="int" resultType="user">
select <include refid="sqlFields"/> from user where id = #{uid}
</select>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lyp.dao.AccountDao">
<!--對文件中常使用的sql片段和使用頻繁的sql抽取出來-->
<sql id="sqlFields">
id,uid,money
</sql>
<select id="findAll" resultType="account">
<!-- select id as userId , username as userName , birthday as userBirthday ,sex as userSex , address as userAddress from user;-->
select
<include refid="sqlFields"/>
from account;
</select>
</mapper>
3.2.7 創(chuàng)建測試類進(jìn)行測試
private InputStream in;
private UserDao userDao;
private SqlSession session;
/**
* 初始化 會在測試方法執(zhí)行之前執(zhí)行
*
* @throws IOException
*/
@Before
public void init() throws IOException {
in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
session = factory.openSession();
userDao = session.getMapper(UserDao.class);
}
/**
* 銷毀 會在測試方法執(zhí)行之后執(zhí)行
*
* @throws IOException
*/
@After
public void destroy() throws IOException {
session.commit();
if (session != null) {
session.close();
}
if (in != null) {
in.close();
}
}
3.3 查詢賬戶的同時查詢到用戶信息(一對一 實(shí)體類繼承的方式)
- 需求 : 在查詢賬戶信息的同時查詢到所屬用戶的名字和地址。
-- 在查詢賬戶信息的同時查詢到所屬用戶的名稱和地址
SELECT a.* , u.`username` , u.`address`
FROM user u , account a
WHERE u.id = a.`UID`;
- 編寫實(shí)體類 AccountUser 繼承Account。
public class AccountUser extends Account {
private String username;
private String address;
// 省略 setter 和 getter 方法
/**
注意這里的toString方法使用super調(diào)用了父類的toString方法
*/
@Override
public String toString() {
return super.toString() + " ====> AccountUser{" +
"username='" + username + '\'' +
", address='" + address + '\'' +
'}';
}
}
- 編寫AccountDao接口方法
/**
*在查詢賬戶信息的同時查詢用戶名稱和地址
* @return
*/
List<AccountUser> findAllAccountUser();
- 在AccountDao.xml配置文件編寫配置sql進(jìn)行查詢。
<select id="findAllAccountUser" resultType="AccountUser">
select a.* , u.username , u.address
from account a,user u
where a.uid = u.id
</select>
3.4 查詢賬戶的同時查詢到用戶信息(一對一 : 賬戶對應(yīng)用戶在Mybatis中的 多對一 算 一對一)
- 一對一 或者 多對一 中,從表的實(shí)體類和主表的實(shí)體類需要體現(xiàn)它們之間的關(guān)系。從表實(shí)體應(yīng)該包含一個主表實(shí)體的對象引用。
- 修改Account實(shí)體類,添加一個對User的對象引用。
/**
* 賬戶實(shí)體類
* @author lyp
*/
public class Account {
private Integer id;
private Integer uid;
private Double money;
private User user;
// 省略 setter 和 getter 方法
}
- 在Account中配置查詢:
<resultMap id="accountUserMap" type="account">
<!---這里id column 是起別名之后的-->
<id property="id" column="aid"/>
<result property="uid" column="uid"/>
<result property="money" column="money"/>
<!--
一對一的關(guān)系映射:配置封裝user的內(nèi)容
property : 實(shí)體類中的類名
column : 關(guān)聯(lián)的字段
javaType : 封裝的類型
-->
<association property="user" column="uid" javaType="user">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
</association>
</resultMap>
- 修改findAll查詢:
<!--使用關(guān)聯(lián)查詢-->
<select id="findAll" resultMap="accountUserMap">
select u.* , a.id as aid ,a.uid,a.money
from user u , account a
where a.uid = u.id
</select>
3.5 一對多查詢
- 一對多關(guān)系映射:主表實(shí)體包含對從表實(shí)體的集合引用。
-- 一對多查詢 使用左外連接查詢 ,查詢左表所有數(shù)據(jù) ,和右表和左表有關(guān)聯(lián)的數(shù)據(jù)
SELECT u.* , a.id AS aid ,a.uid ,a.`MONEY`
FROM USER u LEFT JOIN account a ON u.id = a.`UID`;
- 修改User實(shí)體,在其中添加User實(shí)體對Account實(shí)體的集合引用。
/***
* 用戶實(shí)體類
* @author lyp
*/
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
private List<Account> accounts;
// 省略 setter 和 getter toString 方法
}
- 修改UserDao.xml文件,創(chuàng)建一個resultMap。
<resultMap id="userAccountMap" type="user">
<id column="id" property="id"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
<!--
property : 實(shí)體類中屬性的名稱
ofType : 集合中的類型
javaType: 返回值封裝為什么類型
-->
<collection property="accounts" ofType="account">
<!--從表id字段與主表id字段沖突,使用了別名這里 的 column 需要與別名對應(yīng)-->
<id property="id" column="aid"/>
<result property="uid" column="uid"/>
<result property="money" column="money"/>
</collection>
</resultMap>
3.5.1 一對多 和 一對一 項(xiàng)目地址
- 項(xiàng)目地址 : 一對多 和 一對一 項(xiàng)目地址
3.6 多對多查詢
3.6.1 用戶和角色
- 建立兩張表 用戶表 、 角色表。讓用戶表和角色表具有多對多的關(guān)系。需要一張中間表,中間表中包含各自的主鍵。在中間表中是外鍵。
創(chuàng)建用戶實(shí)體和角色實(shí)體。讓用戶實(shí)體和角色實(shí)體體現(xiàn)多對多的關(guān)系。各自包含對方的集合引用。
創(chuàng)建UserDao.xml 和 RoleDao.xml配置文件。
實(shí)現(xiàn)需求 :
- 當(dāng)我們查詢用戶時,可以同時查詢到用戶所包含的角色信息。
- 當(dāng)我們查詢角色時,可以同時查詢到角色所賦予的用戶信息。
3.6.2 創(chuàng)建一個新項(xiàng)目
- 復(fù)制一對多查詢項(xiàng)目,刪除有關(guān)Account的內(nèi)容,剩余User的單表查詢操作。
3.6.3 創(chuàng)建role 表 和 user_role表
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
`ID` int(11) NOT NULL COMMENT '編號',
`ROLE_NAME` varchar(30) default NULL COMMENT '角色名稱',
`ROLE_DESC` varchar(60) default NULL COMMENT '角色描述',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `role`(`ID`,`ROLE_NAME`,`ROLE_DESC`) values (1,'院長','管理整個學(xué)院'),(2,'總裁','管理整個公司'),(3,'校長','管理整個學(xué)校');
DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role` (
`UID` int(11) NOT NULL COMMENT '用戶編號',
`RID` int(11) NOT NULL COMMENT '角色編號',
PRIMARY KEY (`UID`,`RID`),
KEY `FK_Reference_10` (`RID`),
CONSTRAINT `FK_Reference_10` FOREIGN KEY (`RID`) REFERENCES `role` (`ID`),
CONSTRAINT `FK_Reference_9` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `user_role`(`UID`,`RID`) values (41,1),(45,1),(41,2);
3.6.4 創(chuàng)建Role實(shí)體類 + 持久層接口 + 配置文件 實(shí)現(xiàn)查詢所有角色的操作
- 創(chuàng)建Role 實(shí)體類:注意這里實(shí)體類屬性名稱使用駝峰的命名方式。之后配置文件中就需要使用resultMap重新定義返回類型。
/**
* @author lyp
*/
public class Role implements Serializable {
private Integer id;
private String roleName;
private String roleDesc;
// 省略setter 和 getter 方法 toString 方法
}
- 創(chuàng)建RoleDao持久層接口 。編寫查詢所有的方法 。
/**
* Role持久層接口
*
* @author lyp
*/
public interface RoleDao {
/**
* 查詢所有角色
* @return
*/
List<Role> findAll();
}
- 創(chuàng)建RoleDao.xml配置文件:由于實(shí)體類屬性名稱和數(shù)據(jù)庫字段名稱不是一一對應(yīng)的所以需要使用resultMap標(biāo)簽配置映射配置。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lyp.dao.RoleDao">
<resultMap id="roleMap" type="role">
<id property="id" column="id"/>
<result property="roleDesc" column="role_desc"/>
<result property="roleName" column="role_name"/>
</resultMap>
<sql id="roleFields">
id,role_desc , role_name
</sql>
<select id="findAll" resultMap="roleMap">
select
<include refid="roleFields"/>
from role;
</select>
</mapper>
3.6.5 查詢角色的時候同時獲取到用戶的信息 (多對多)
- 在 角色實(shí)體 中添加多對多映射集合引用,一個角色可以賦予多個角色。
/**
* @author lyp
*/
public class Role implements Serializable {
private Integer id;
private String roleName;
private String roleDesc;
private List<User> users;
// 省略 setter 和 getter toString 方法
}
- 編寫多表查詢語句 :
-- 編寫多表查詢語句
SELECT r.id AS rid , r.`ROLE_DESC` , r.`ROLE_NAME` ,u.*
FROM role r
LEFT JOIN user_role ur
ON r.id = ur.`RID`
LEFT JOIN USER u
ON ur.uid = u.`id`;
3.配置RoleDao.xml :
<resultMap id="roleMap" type="role">
<!--由于在查詢語句中重名名了 role 表的id為rid 所以column 屬性需要修改為rid-->
<id property="id" column="rid"/>
<result property="roleDesc" column="role_desc"/>
<result property="roleName" column="role_name"/>
<!--
role 關(guān)聯(lián)查詢
ofType為集合的類型
-->
<collection property="users" ofType="user">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="address" column="address"/>
<result property="sex" column="sex"/>
</collection>
</resultMap>
<sql id="roleFields">
id,role_desc , role_name
</sql>
<select id="findAll" resultMap="roleMap">
SELECT r.id AS rid , r.`ROLE_DESC` , r.`ROLE_NAME` ,u.*
FROM role r
LEFT JOIN user_role ur
ON r.id = ur.`RID`
LEFT JOIN USER u
ON ur.uid = u.`id`;
</select>
3.6.6 查詢用戶信息的時候同時查詢到相應(yīng)的角色信息 (多對多)
- 在User實(shí)體類中添加一個多對多的關(guān)系映射。對Role的集合引用。
/***
* 用戶實(shí)體類
* @author lyp
*/
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
private List<Role> roles;
// 省略setter 和 getter toString方法
}
- 編寫多對多查詢的sql語句 : 左連接查詢是查詢左表所有數(shù)據(jù) 和 左表與 右表的交集
-- 編寫 查詢用戶信息的同時查詢其角色信息的多對多查詢語句
SELECT u.* , r.id AS rid , r.`ROLE_NAME` , r.`ROLE_DESC`
FROM USER u
LEFT JOIN user_role ur
ON u.id = ur.`UID`
LEFT JOIN role r
ON ur.`RID` = r.`ID` ;
- 配置UserDao.xml文件 :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lyp.dao.UserDao">
<resultMap id="userAccountMap" type="user">
<id column="id" property="id"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
<!--
配置user與role的關(guān)聯(lián)映射
ofType為集合中值的類型
-->
<collection property="roles" ofType="role">
<id property="id" column="rid"/>
<result property="roleName" column="role_name"/>
<result property="roleDesc" column="role_desc"/>
</collection>
</resultMap>
<!--對文件中常使用的sql片段和使用頻繁的sql抽取出來-->
<sql id="sqlFields">
id, username,birthday,sex,address
</sql>
<!--一對多查詢,主表需要有一個對從表的引用-->
<select id="findAll" resultMap="userAccountMap">
SELECT u.* , r.id AS rid , r.`ROLE_NAME` , r.`ROLE_DESC`
FROM USER u
LEFT JOIN user_role ur
ON u.id = ur.`UID`
LEFT JOIN role r
ON ur.`RID` = r.`ID` ;
</select>
</mapper>
3.6.7 項(xiàng)目地址
- 項(xiàng)目地址:Mybatis多對多查詢demo地址