目錄html
<select id="saveRole" resultType="role"> insert into tb_role ( <trim suffixOverrides=","> <if test="roleName!=null"> role_name, </if> <if test="description != null"> description, </if> <if test="status != null"> status, </if> <if test="createTime != null"> create_time, </if> <if test="createUser != null"> create_user, </if> <if test="modifyTime != null"> modify_time, </if> <if test="modifyUser != null"> modify_user </if> </trim> ) VALUES ( <trim suffixOverrides=","> <if test="roleName!=null"> #{roleName}, </if> <if test="description != null"> #{description}, </if> <if test="status != null"> #{status}, </if> <if test="createTime != null"> #{createTime}, </if> <if test="createUser != null"> #{createUser}, </if> <if test="modifyTime != null"> #{modifyTime}, </if> <if test="modifyUser != null"> #{modifyUser} </if> </trim> ) </select>
這個增長方法使用if 進行判斷,因此只是將不爲空的字段添加。java
<!--設置保存的時候須要返回插入時的id--> <insert id="saveUser" useGeneratedKeys="true" keyProperty="id" parameterType="User" > insert into tb_user (user_id, username,password,email,phone,gender,birthday,create_time, create_user,modify_time,modify_user) values ( #{user.userId},#{user.username},#{user.password},#{user.email},#{user.phone},#{user.gender}, #{user.birthday},#{user.createTime},#{user.createUser},#{user.modifyTime},#{user.modifyUser}) </insert>
<delete id="deleteRoleById"> delete from tb_role where id = #{id} </delete>
這是一個很是簡單的刪除語句,這裏不贅述。git
<update id="updateRole"> update tb_role <set> <if test="roleName!=null"> role_name = #{roleName}, </if> <if test="description != null"> description = #{description}, </if> <if test="status != null"> status = #{status}, </if> <if test="createTime != null"> create_time = #{createTime}, </if> <if test="createUser != null"> create_user = #{createUser}, </if> <if test="modifyTime != null"> modify_time = #{modifyTime}, </if> <if test="modifyUser != null"> modify_user = #{modifyUser} </if> </set> where id = #{id} </update>
提示:這裏採用了選擇性更新,即只有字段不爲空的時候,纔會進行更新操做。sql
<select id="selectRolesByStatus" resultType="role"> select * from tb_role where status = #{status} </select>
提示:這裏僅僅介紹一下最簡單的查詢,後面重點介紹與查詢相關的。數據庫
增刪改查標籤相關屬性請參考:編程
https://mybatis.org/mybatis-3/zh/sqlmap-xml.html#insert_update_and_deletejson
屬性 | 描述 |
---|---|
id | 在命名空間中惟一的標識符,能夠被用來引用這條語句。 |
parameterType | 將會傳入這條語句的參數類的徹底限定名或別名。這個屬性是可選的,由於 MyBatis 能夠經過類型處理器(TypeHandler) 推斷出具體傳入語句的參數,默認值爲未設置(unset)。 |
resultType | 從這條語句中返回的指望類型的類的徹底限定名或別名。 注意若是返回的是集合,那應該設置爲集合包含的類型,而不是集合自己。可使用 resultType 或 resultMap,但不能同時使用。 |
resultMap | 外部 resultMap 的命名引用。結果集的映射是 MyBatis 最強大的特性,若是你對其理解透徹,許多複雜映射的情形都能迎刃而解。可使用 resultMap 或 resultType,但不能同時使用。 |
flushCache | 將其設置爲 true 後,只要語句被調用,都會致使本地緩存和二級緩存被清空,默認值:false。 |
useCache | 將其設置爲 true 後,將會致使本條語句的結果被二級緩存緩存起來,默認值:對 select 元素爲 true。 |
timeout | 這個設置是在拋出異常以前,驅動程序等待數據庫返回請求結果的秒數。默認值爲未設置(unset)(依賴驅動)。 |
fetchSize | 這是一個給驅動的提示,嘗試讓驅動程序每次批量返回的結果行數和這個設置值相等。 默認值爲未設置(unset)(依賴驅動)。 |
statementType | STATEMENT,PREPARED 或 CALLABLE 中的一個。這會讓 MyBatis 分別使用 Statement,PreparedStatement 或 CallableStatement,默認值:PREPARED。 |
resultSetType | FORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等價於 unset) 中的一個,默認值爲 unset (依賴驅動)。 |
databaseId | 若是配置了數據庫廠商標識(databaseIdProvider),MyBatis 會加載全部的不帶 databaseId 或匹配當前 databaseId 的語句;若是帶或者不帶的語句都有,則不帶的會被忽略。 |
resultOrdered | 這個設置僅針對嵌套結果 select 語句適用:若是爲 true,就是假設包含了嵌套結果集或是分組,這樣的話當返回一個主結果行的時候,就不會發生有對前面結果集的引用的狀況。 這就使得在獲取嵌套的結果集的時候不至於致使內存不夠用。默認值:false。 |
resultSets | 這個設置僅對多結果集的狀況適用。它將列出語句執行後返回的結果集並給每一個結果集一個名稱,名稱是逗號分隔的。 |
屬性 | 描述 |
---|---|
id | 命名空間中的惟一標識符,可被用來表明這條語句。 |
parameterType | 將要傳入語句的參數的徹底限定類名或別名。這個屬性是可選的,由於 MyBatis 能夠經過類型處理器推斷出具體傳入語句的參數,默認值爲未設置(unset)。 |
parameterMap | 這是引用外部 parameterMap 的已經被廢棄的方法。請使用內聯參數映射和 parameterType 屬性。 |
flushCache | 將其設置爲 true 後,只要語句被調用,都會致使本地緩存和二級緩存被清空,默認值:true(對於 insert、update 和 delete 語句)。 |
timeout | 這個設置是在拋出異常以前,驅動程序等待數據庫返回請求結果的秒數。默認值爲未設置(unset)(依賴驅動)。 |
statementType | STATEMENT,PREPARED 或 CALLABLE 的一個。這會讓 MyBatis 分別使用 Statement,PreparedStatement 或 CallableStatement,默認值:PREPARED。 |
useGeneratedKeys | (僅對 insert 和 update 有用)這會令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法來取出由數據庫內部生成的主鍵(好比:像 MySQL 和 SQL Server 這樣的關係數據庫管理系統的自動遞增字段),默認值:false。 |
keyProperty | (僅對 insert 和 update 有用)惟一標記一個屬性,MyBatis 會經過 getGeneratedKeys 的返回值或者經過 insert 語句的 selectKey 子元素設置它的鍵值,默認值:未設置(unset)。若是但願獲得多個生成的列,也能夠是逗號分隔的屬性名稱列表。 |
keyColumn | (僅對 insert 和 update 有用)經過生成的鍵值設置表中的列名,這個設置僅在某些數據庫(像 PostgreSQL)是必須的,當主鍵列不是表中的第一列的時候須要設置。若是但願使用多個生成的列,也能夠設置爲逗號分隔的屬性名稱列表。 |
databaseId | 若是配置了數據庫廠商標識(databaseIdProvider),MyBatis 會加載全部的不帶 databaseId 或匹配當前 databaseId 的語句;若是帶或者不帶的語句都有,則不帶的會被忽略。 |
屬性 | 描述 |
---|---|
property | 映射到列結果的字段或屬性。若是用來匹配的 JavaBean 存在給定名字的屬性,那麼它將會被使用。不然 MyBatis 將會尋找給定名稱的字段。 不管是哪種情形,你均可以使用一般的點式分隔形式進行復雜屬性導航。 好比,你能夠這樣映射一些簡單的東西:「username」,或者映射到一些複雜的東西上:「address.street.number」。 |
column | 數據庫中的列名,或者是列的別名。通常狀況下,這和傳遞給 resultSet.getString(columnName) 方法的參數同樣。 |
javaType | 一個 Java 類的徹底限定名,或一個類型別名(關於內置的類型別名,能夠參考上面的表格)。 若是你映射到一個 JavaBean,MyBatis 一般能夠推斷類型。然而,若是你映射到的是 HashMap,那麼你應該明確地指定 javaType 來保證行爲與指望的相一致。 |
jdbcType | JDBC 類型,所支持的 JDBC 類型參見這個表格以後的「支持的 JDBC 類型」。 只須要在可能執行插入、更新和刪除的且容許空值的列上指定 JDBC 類型。這是 JDBC 的要求而非 MyBatis 的要求。若是你直接面向 JDBC 編程,你須要對可能存在空值的列指定這個類型。 |
typeHandler | 咱們在前面討論過默認的類型處理器。使用這個屬性,你能夠覆蓋默認的類型處理器。 這個屬性值是一個類型處理器實現類的徹底限定名,或者是類型別名。 |
爲了之後可能的使用場景,MyBatis 經過內置的 jdbcType 枚舉類型支持下面的 JDBC 類型。緩存
BIT | FLOAT | CHAR | TIMESTAMP | OTHER | UNDEFINED |
---|---|---|---|---|---|
TINYINT | REAL | VARCHAR | BINARY | BLOB | NVARCHAR |
SMALLINT | DOUBLE | LONGVARCHAR | VARBINARY | CLOB | NCHAR |
INTEGER | NUMERIC | DATE | LONGVARBINARY | BOOLEAN | NCLOB |
BIGINT | DECIMAL | TIME | NULL | CURSOR | ARRAY |
<resultMap id="base_map" type="role"> <id column="id" jdbcType="INTEGER" property="id" /> <result column="role_name" jdbcType="VARCHAR" property="roleName"/> <result column="description" jdbcType="VARCHAR" property="description"/> <result column="status" jdbcType="INTEGER" property="status"/> <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> <result column="create_user" jdbcType="VARCHAR" property="createUser"/> <result column="modify_time" jdbcType="TIMESTAMP" property="modifyTime"/> <result column="modify_user" jdbcType="VARCHAR" property="modifyUser"/> </resultMap> <select id="selectAllRoles" resultMap="base_map"> select * from tb_role </select>
java實體:mybatis
//空參數,全參數,get,set,toString public class Role implements Serializable { private Integer id; private String roleName; private String description; private Integer status; private Date createTime; private String createUser; private Date modifyTime; private String modifyUser; }
提示:能夠看出,這裏咱們再也不直接使用了user做爲返回類型(resultType),而是使用告終果映射(resultMap)來映射實體。以上方式使用的實體映射是使用的setter進行設置參數的。咱們在setId方法上加一段輸入語句以後,再次運行,結果以下:app
public void setId(Integer id) { System.out.println("setId of role is running"); this.id = id; }
那麼咱們如何使用構造函數來進行屬性設置賦值呢?
<resultMap id="base_map" type="role"> <constructor> <idArg column="id" javaType="Integer"/> <arg column="role_name" javaType="String"/> <arg column="description" javaType="String"/> <arg column="status" javaType="Integer"/> <arg column="create_time" javaType="Date"/> <arg column="create_user" javaType="String"/> <arg column="modify_time" javaType="Date" /> <arg column="modify_user" javaType="String" /> </constructor> </resultMap>
public Role(Integer id, String roleName, String description, Integer status, Date createTime, String createUser, Date modifyTime, String modifyUser) { System.out.println("all args' constructor of role is running "); this.id = id; this.roleName = roleName; this.description = description; this.status = status; this.createTime = createTime; this.createUser = createUser; this.modifyTime = modifyTime; this.modifyUser = modifyUser; }
測試結果:
前面咱們看到了單表操做,咱們經過直接返回對象或是使用resultMap的方式來映射實體。這裏咱們看一下實體一對一的關係如何映射。
一對一關係的映射:association標籤的屬性元素 property CDATA 屬性,必須 column CDATA 數據庫表的字段名 javaType CDATA 屬性的java類型 jdbcType CDATA 數據庫表的字段的類型 select CDATA 嵌套查詢時使用。 resultMap CDATA 關聯外部的手動映射關係時使用 typeHandler CDATA 類型處理器 notNullColumn CDATA columnPrefix CDATA 字段前綴,一對一中有涉及到 resultSet CDATA foreignColumn CDATA autoMapping (true|false) 是否自定映射 fetchType (lazy|eager) 是否懶加載
業務:用戶與身份證是一對一的關係。
User類:
@NoArgsConstructor @AllArgsConstructor @Getter @Setter @ToString public class User implements Serializable { private Integer id; private String userId; private String username; private String password; private String email; private String phone; private Integer gender; private Date birthday; private Integer status; private Date createTime; private String createUser; private Date modifyTime; private String modifyUser; private Card card; }
提示:這裏使用了lombok
簡化實例開發,依賴以下:
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.8</version> </dependency>
Card類:
@NoArgsConstructor @AllArgsConstructor @Getter @Setter @ToString public class Card implements Serializable { private Integer id; private Integer uid; private String cardId; private String address; private Date createTime; private Date modifyTime; }
經過上面的實例類關係咱們能夠發現,card是User類中的一個屬性,可是如何經過Mybatis的自動映射機制將card表中的數據之間填充到User屬性中。咱們能夠在查詢字段上使用別名來映射,以下,uid字段是user的card屬性的屬性,則能夠經過card.uid
來映射到User類的card屬性的uid字段。
<select id="findUserWithCardByUserId" resultType="user"> SELECT a.id,a.user_id,a.username,a.password,a.email,a.phone, a.gender,a.birthday,a.status,a.create_time,a.create_user, a.modify_time,a.modify_user, b.id as "card.id" , b.uid as "card.uid", b.card_id as "card.cardId", b.address as "card.address", b.create_time as "card.createTime" , b.modify_time as "card.modifyTime" FROM tb_user a INNER JOIN tb_card b on a.id = b.uid where a.id = #{id}; </select>
手動映射就是經過結果集的方式列進行映射,以下:
<resultMap id="BaseResultMapWithCard" type="user"> <id column="id" jdbcType="INTEGER" property="id"/> <result column="user_id" jdbcType="VARCHAR" property="userId"/> <result column="username" jdbcType="VARCHAR" property="username"/> <result column="password" jdbcType="VARCHAR" property="password"/> <result column="email" jdbcType="VARCHAR" property="email"/> <result column="phone" jdbcType="VARCHAR" property="phone"/> <result column="gender" jdbcType="INTEGER" property="gender"/> <result column="birthday" jdbcType="DATE" property="birthday"/> <result column="status" jdbcType="INTEGER" property="status"/> <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> <result column="create_user" jdbcType="VARCHAR" property="createUser"/> <result column="modify_time" jdbcType="TIMESTAMP" property="modifyTime"/> <result column="modify_user" jdbcType="VARCHAR" property="modifyUser"/> <association property="card" javaType="card"> <id column="bid" jdbcType="INTEGER" property="id"/> <result column="uid" jdbcType="INTEGER" property="uid"/> <result column="card_id" jdbcType="VARCHAR" property="cardId"/> <result column="address" jdbcType="VARCHAR" property="address"/> <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> <result column="modify_time" jdbcType="TIMESTAMP" property="modifyTime"/> </association> </resultMap> <select id="findUserWithCardByUserId" resultMap="BaseResultMapWithCard"> select a.id,a.user_id,a.username,a.password,a.email,a.phone,a.gender, a.birthday,a.status,a.create_time,a.create_user,a.modify_time,a.modify_user, b.id bid, b.uid, b.card_id, b.address, b.create_time, b.modify_time FROM tb_user a INNER JOIN tb_card b on a.id = b.uid where a.id = #{id} </select>
經過上述的SQL查詢和結果集的手動映射關係,這樣就能夠實現字段和實體的查詢了。
固然,Mybatis還提供下面這種方式來實現:
<resultMap id="BaseResultMapWithCard" type="user"> <id column="id" jdbcType="INTEGER" property="id"/> <result column="user_id" jdbcType="VARCHAR" property="userId"/> <result column="username" jdbcType="VARCHAR" property="username"/> <result column="password" jdbcType="VARCHAR" property="password"/> <result column="email" jdbcType="VARCHAR" property="email"/> <result column="phone" jdbcType="VARCHAR" property="phone"/> <result column="gender" jdbcType="INTEGER" property="gender"/> <result column="birthday" jdbcType="DATE" property="birthday"/> <result column="status" jdbcType="INTEGER" property="status"/> <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> <result column="create_user" jdbcType="VARCHAR" property="createUser"/> <result column="modify_time" jdbcType="TIMESTAMP" property="modifyTime"/> <result column="modify_user" jdbcType="VARCHAR" property="modifyUser"/> <association property="card" javaType="card" column="id" select="selectCard"></association> </resultMap> <select id="findUserWithCardByUserId" resultMap="BaseResultMapWithCard"> select a.id,a.user_id,a.username,a.password,a.email,a.phone,a.gender, a.birthday,a.status,a.create_time,a.create_user,a.modify_time,a.modify_user FROM tb_user a where a.id = #{id} </select> <select id="selectCard" resultType="card"> select * from tb_card where uid = #{id} </select>
這樣的操做其實就是先查詢出User的信息,而後在取user表的id字段來查詢card表的數據,這樣就至關於向MySQL發送了兩條SQL,咱們經過日誌能夠觀察到現象:
兩種方式均可以實現一樣地結果,若是須要控制SQL發送條數的話,可使用關聯方式,若是須要在必定程度上下降SQL的查詢時間,則能夠將其拆分爲多個查詢SQL。
拓展:
下面咱們看一下下面這個SQL如何進行映射,咱們假設,一個User有一個主身份證和一個副身份證,那麼咱們須要如何查詢映射:
User:
@NoArgsConstructor @AllArgsConstructor @Getter @Setter @ToString public class User implements Serializable { private Integer id; private String userId; private String username; private String password; private String email; private String phone; private Integer gender; private Date birthday; private Integer status; private Date createTime; private String createUser; private Date modifyTime; private String modifyUser; private Card card;//主 private Card card1;//副 }
對應的SQL映射以下:
<resultMap id="BaseResultMapWithCard" type="user"> <id column="id" jdbcType="INTEGER" property="id"/> <result column="user_id" jdbcType="VARCHAR" property="userId"/> <result column="username" jdbcType="VARCHAR" property="username"/> <result column="password" jdbcType="VARCHAR" property="password"/> <result column="email" jdbcType="VARCHAR" property="email"/> <result column="phone" jdbcType="VARCHAR" property="phone"/> <result column="gender" jdbcType="INTEGER" property="gender"/> <result column="birthday" jdbcType="DATE" property="birthday"/> <result column="status" jdbcType="INTEGER" property="status"/> <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> <result column="create_user" jdbcType="VARCHAR" property="createUser"/> <result column="modify_time" jdbcType="TIMESTAMP" property="modifyTime"/> <result column="modify_user" jdbcType="VARCHAR" property="modifyUser"/> <association property="card" javaType="card" resultMap="cardResultMap" columnPrefix="b1_" /> <association property="card1" javaType="card" resultMap="cardResultMap" columnPrefix="b2_" /> </resultMap> <resultMap id="cardResultMap" type="card"> <id column="id" jdbcType="INTEGER" property="id"/> <result column="uid" jdbcType="INTEGER" property="uid"/> <result column="card_id" jdbcType="VARCHAR" property="cardId"/> <result column="address" jdbcType="VARCHAR" property="address"/> <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> <result column="modify_time" jdbcType="TIMESTAMP" property="modifyTime"/> </resultMap> <select id="findUserWithCardByUserId" resultMap="BaseResultMapWithCard" > select a.id,a.user_id,a.username,a.password,a.email,a.phone,a.gender, a.birthday,a.status,a.create_time,a.create_user,a.modify_time,a.modify_user, b1.id b1_id, b1.uid b1_uid, b1.card_id b1_card_id, b1.address b1_address, b1.create_time b1_create_time, b1.modify_time b1_modify_time, b2.id b2_id, b2.uid b2_uid, b2.card_id b2_card_id, b2.address b2_address, b2.create_time b2_create_time, b2.modify_time b2_modify_time from tb_user a inner join tb_card b1 on a.id = b1.uid inner join tb_card b2 on a.id = b2.uid where a.id = 1 </select>
當鏈接多個表時,咱們可能會不得不使用列別名來避免在 ResultSet 中產生重複的列名。指定 association標籤的columnPrefix 列名前綴容許你將帶有這些前綴的列映射到一個外部的結果映射中。
// 下面是collection標籤的各個屬性元素 property CDATA #REQUIRED 必須,指定的是java實體類的屬性名 column CDATA 指定的是表的字段名(查詢出來的,有多是字段別名) javaType CDATA 集合通常不使用這個 ofType CDATA 屬性的java類型,例如:string,integer jdbcType CDATA 數據庫的字段類型 select CDATA 當咱們須要進行嵌套查詢的時候,執行另一個查詢語句 resultMap CDATA 返回值的映射關 typeHandler CDATA 類型處理 notNullColumn CDATA columnPrefix CDATA 當咱們須要進行區分的時候,能夠指定前綴,後面有案例 resultSet CDATA foreignColumn CDATA 外鍵 autoMapping (true|false) 是否須要自動映射 fetchType (lazy|eager) 是否進行懶加載
在實際開發中,權限每每是無關業務,可是又是相當重要的一環。在設計權限的時候,咱們每每不會講權限之間與用戶以前關聯,爲了更加好的管理,咱們會在用戶與權限之間引入一個角色,用角色來統一管理具備相同權限的用戶,通常一個用戶存在於多個角色,好比即便CEO又是系統開發人員(哈哈),這裏就是一個一對多的關係,下面咱們看看,在Mybatis中一對多的關係如何映射:
User:
@NoArgsConstructor @AllArgsConstructor @Getter @Setter @ToString public class User implements Serializable { private Integer id; private String userId; private String username; private String password; private String email; private String phone; private Integer gender; private Date birthday; private Integer status; private Date createTime; private String createUser; private Date modifyTime; private String modifyUser; private List<Role> roles; }
Role:
@NoArgsConstructor @AllArgsConstructor @Getter @Setter @ToString public class Role implements Serializable { private Integer id; private String roleName; private String description; private Integer status; private Date createTime; private String createUser; private Date modifyTime; private String modifyUser; }
根據id查詢的SQLxml文件:
這裏與前面的一對多的關聯關係有所不一樣 ,一對多關聯關係使用的是association,java類型使用的是javaType。而多對多關聯關係使用的標籤是collection,java類型屬性使用的是ofType。
<resultMap id="BaseResultWithRole" type="com.ooyhao.mybatis.bean.User"> <id column="id" jdbcType="INTEGER" property="id"/> <result column="user_id" jdbcType="VARCHAR" property="userId"/> <result column="username" jdbcType="VARCHAR" property="username"/> <result column="password" jdbcType="VARCHAR" property="password"/> <result column="email" jdbcType="VARCHAR" property="email"/> <result column="phone" jdbcType="VARCHAR" property="phone"/> <result column="gender" jdbcType="INTEGER" property="gender"/> <result column="birthday" jdbcType="DATE" property="birthday"/> <result column="status" jdbcType="INTEGER" property="status"/> <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> <result column="create_user" jdbcType="VARCHAR" property="createUser"/> <result column="modify_time" jdbcType="TIMESTAMP" property="modifyTime"/> <result column="modify_user" jdbcType="VARCHAR" property="modifyUser"/> <collection property="roles" ofType="role"> <id column="cid" jdbcType="INTEGER" property="id"/> <result column="role_name" jdbcType="VARCHAR" property="roleName"/> <result column="description" jdbcType="VARCHAR" property="description"/> <result column="status" jdbcType="INTEGER" property="status"/> <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> <result column="create_user" jdbcType="VARCHAR" property="createUser"/> <result column="modify_time" jdbcType="TIMESTAMP" property="modifyTime"/> <result column="modify_user" jdbcType="VARCHAR" property="modifyUser"/> </collection> </resultMap> <select id="findUserWithRolesByUserId" resultMap="BaseResultWithRole"> select a.id,a.user_id,a.username,a.password,a.email,a.phone,a.gender, a.birthday,a.status,a.create_time,a.create_user,a.modify_time,a.create_user, c.id cid, c.role_name, c.description, c.status, c.create_time, c.create_user, c.modify_time, c.create_user from tb_user a left join tb_user_role b on a.id = b.user_id left join tb_role c on c.id = b.role_id where a.id = #{id} </select>
測試結果以下:
{ "birthday": 1551369600000, "createTime": 1551433926000, "createUser": "admin", "email": "12345678@qq.com", "gender": 1, "id": 1, "modifyTime": 1551679675000, "password": "admin123456789", "phone": "12345678901", "roles": [{ "createTime": 1551433926000, "createUser": "admin", "description": "超級管理員", "id": 1, "modifyTime": 1551679675000, "roleName": "admin", "status": 0 }, { "createTime": 1551433926000, "createUser": "admin", "description": "開發人員", "id": 2, "modifyTime": 1551679675000, "roleName": "develop", "status": 0 }], "status": 0, "userId": "oms20190001", "username": "admin" }
除了上述方式進行關聯查詢,咱們還能夠將SQL進行拆分:
關聯嵌套查詢:
<resultMap id="BaseResultWithRole" type="com.ooyhao.mybatis.bean.User"> <id column="id" jdbcType="INTEGER" property="id"/> <result column="user_id" jdbcType="VARCHAR" property="userId"/> <result column="username" jdbcType="VARCHAR" property="username"/> <result column="password" jdbcType="VARCHAR" property="password"/> <result column="email" jdbcType="VARCHAR" property="email"/> <result column="phone" jdbcType="VARCHAR" property="phone"/> <result column="gender" jdbcType="INTEGER" property="gender"/> <result column="birthday" jdbcType="DATE" property="birthday"/> <result column="status" jdbcType="INTEGER" property="status"/> <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> <result column="create_user" jdbcType="VARCHAR" property="createUser"/> <result column="modify_time" jdbcType="TIMESTAMP" property="modifyTime"/> <result column="modify_user" jdbcType="VARCHAR" property="modifyUser"/> <collection property="roles" ofType="role" column="id" select="selectRole" /> </resultMap> <resultMap id="selectRole" type="role"> <id column="cid" jdbcType="INTEGER" property="id"/> <result column="role_name" jdbcType="VARCHAR" property="roleName"/> <result column="description" jdbcType="VARCHAR" property="description"/> <result column="status" jdbcType="INTEGER" property="status"/> <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> <result column="create_user" jdbcType="VARCHAR" property="createUser"/> <result column="modify_time" jdbcType="TIMESTAMP" property="modifyTime"/> <result column="modify_user" jdbcType="VARCHAR" property="modifyUser"/> </resultMap> <select id="findUserWithRolesByUserId" resultMap="BaseResultWithRole"> select a.id,a.user_id,a.username,a.password,a.email,a.phone,a.gender, a.birthday,a.status,a.create_time,a.create_user,a.modify_time,a.create_user from tb_user a where a.id = #{id} </select> <select id="selectRole" resultType="role" > select b.* from tb_user_role a left join tb_role b on a.role_id = b.id where a.user_id = #{id} </select>
注:多對多其實就是雙向的一對多關係,再也不贅述。
摘自官網:
有時候,一個數據庫查詢可能會返回多個不一樣的結果集(但整體上仍是有必定的聯繫的)。 鑑別器(discriminator)元素就是被設計來應對這種狀況的,另外也能處理其它狀況,例如類的繼承層次結構。 鑑別器的概念很好理解——它很像 Java 語言中的 switch 語句。
一個鑑別器的定義須要指定 column 和 javaType 屬性。column 指定了 MyBatis 查詢被比較值的地方。 而 javaType 用來確保使用正確的相等測試(雖然不少狀況下字符串的相等測試均可以工做)。例如:
<resultMap id="vehicleResult" type="Vehicle"> <id property="id" column="id" /> <result property="vin" column="vin"/> <result property="year" column="year"/> <result property="make" column="make"/> <result property="model" column="model"/> <result property="color" column="color"/> <discriminator javaType="int" column="vehicle_type"> <case value="1" resultMap="carResult"/> <case value="2" resultMap="truckResult"/> <case value="3" resultMap="vanResult"/> <case value="4" resultMap="suvResult"/> </discriminator> </resultMap> ---------------------------------------也能夠這樣----------------------------------------- <resultMap id="vehicleResult" type="Vehicle"> <id property="id" column="id" /> <result property="vin" column="vin"/> <result property="year" column="year"/> <result property="make" column="make"/> <result property="model" column="model"/> <result property="color" column="color"/> <discriminator javaType="int" column="vehicle_type"> <case value="1" resultType="carResult"> <result property="doorCount" column="door_count" /> </case> <case value="2" resultType="truckResult"> <result property="boxSize" column="box_size" /> <result property="extendedCab" column="extended_cab" /> </case> <case value="3" resultType="vanResult"> <result property="powerSlidingDoor" column="power_sliding_door" /> </case> <case value="4" resultType="suvResult"> <result property="allWheelDrive" column="all_wheel_drive" /> </case> </discriminator> </resultMap>
提示:請注意,這些都是結果映射,若是你徹底不設置任何的 result 元素,MyBatis 將爲你自動匹配列和屬性。因此上面的例子大多都要比實際的更復雜。 這也代表,大多數數據庫的複雜度都比較高,咱們不太可能一直依賴於這種機制。
下面經過一個案例來使用一下鑑別器:
數據以下:
咱們經過接口的方式來使用鑑別器建立不一樣的交通工具實體:
public interface Vehicle {} @NoArgsConstructor @AllArgsConstructor @Getter @Setter @ToString public class Bus implements Vehicle { private Integer id; private String name; } @NoArgsConstructor @AllArgsConstructor @Getter @Setter @ToString public class Car implements Vehicle{ private Integer id; private String name; } @NoArgsConstructor @AllArgsConstructor @Getter @Setter @ToString public class Subway implements Vehicle { private Integer id; private String name; }
Sql.xml文件:
<resultMap id="BaseResultMap" type="com.ooyhao.mybatis.bean.Vehicle"> <id column="id" jdbcType="INTEGER" property="id"/> <discriminator javaType="INTEGER" jdbcType="INTEGER" column="vehicle_type" > <case value="1" resultType="car"> <result property="name" column="vehicle_name" jdbcType="VARCHAR" /> </case> <case value="2" resultType="bus"> <result property="name" column="vehicle_name" jdbcType="VARCHAR"/> </case> <case value="3" resultType="subway"> <result property="name" column="vehicle_name" jdbcType="VARCHAR"/> </case> </discriminator> </resultMap> <select id="findVehicleById" resultMap="BaseResultMap"> select * from tb_vehicle where id = #{id} </select>
在case之外的,就至關於在每個case中都會存在,而在case中的則是根據條件來選擇的。
id爲1時:
id爲3時:
源碼地址:
https://gitee.com/ooyhao/JavaRepo_Public/tree/master/Mybatis
若是以爲不錯的話,那就關注一下小編哦!一塊兒交流,一塊兒學習