某些實體類之間確定有關鍵關係,好比一對一,一對多等。在hibernate 中用one to one
和one to many
,而mybatis 中就用association
和collection
。
association: 一對一關聯(has one)
collection:一對多關聯(has many)
注意,只有在作select查詢時纔會用到這兩個標籤,都有三種用法,且用法相似。java
先看以下代碼(省略set、get方法):sql
public class User { private Integer userId; private String userName; private Integer age; private Card card;//一我的一張身份證,1對1 }
public class Card { private Integer cardId; private String cardNum;//身份證號 private String address;//地址 }
public interface UserDao { /** * 經過userId查詢user信息 * @param userId * @return */ User queryById(int userId); }
<select id="queryById" parameterType="int" resultMap="userMap"> SELECT u.user_name,u.age,c.card_id,c.card_num,c.address FROM tb_user u,tb_card c WHERE u.card_id=c.card_id AND u.user_id=#{userId} </select>
以上是實體類、dao層的設計以及在UserDao.xml中queryById方法的sql語句的編寫,由於不論用association的哪一種方式,sql語句都是同樣的寫,不一樣的只是userMap的寫法,因此這裏先給出這段代碼。User詢Card是一對一關係,在數據庫中,tb_user表經過外鍵card_id關聯tb_card表。下面分別用association的三種用法來實現queryById方法。數據庫
這種方法須要再定義CardDao.java,以下:mybatis
public interface CardDao { Card queryCardById(int cardId); }
在CardDao.xml中實現該方法:spa
<select id="queryCardById" parameterType="int" resultType="Card"> SELECT * FROM tb_card WHERE card_id=#{cardId} </select>
而後再看UserDao.xml中是如何引用這個方法的:hibernate
<resultMap type="User" id="userMap"> <result property="userName" column="user_name"/> <result property="age" column="age"/> <association property="card" column="card_id" select="com.zhu.ssm.dao. CardDao.queryCardById"> </association> </resultMap>
在這裏直接經過select引用CardDao的queryById方法。我的感受這種方法比較麻煩,由於還要在CardDao裏定義queryCardById方法而且實現再引用纔有用,不過這種方法思路清晰,易於理解。設計
<resultMap type="Card" id="cardMap"> <id property="cardId" column="card_id"/> <result property="cardNum" column="card_num"/> <result property="address" column="address"/> </resultMap> <resultMap type="User" id="userMap"> <result property="userName" column="user_name"/> <result property="age" column="age"/> <association property="card" resultMap="cardMap"> </association> </resultMap>
第二種方法就是在UserDao.xml中先定義一個Card的resultMap,而後在User的resultMap的association標籤中經過resultMap="cardMap"引用。這種方法相比於第一種方法較爲簡單。code
<resultMap type="User" id="userMap"> <result property="userName" column="user_name"/> <result property="age" column="age"/> <association property="card" column="card_id" javaType="Card"> <id property="cardId" column="card_id"/> <result property="cardNum" column="card_num"/> <result property="address" column="address"/> </association> </resultMap>
這種方法就把Card的resultMap定義在了association 標籤裏面,經過javaType來指定是哪一個類的resultMap,我的認爲這種方法最簡單,缺點就是cardMap不能複用。具體用哪一種方法,視狀況而定。xml
一個土豪有多個手機,看以下代碼:
User實體類ci
public class User{ private Integer userId; private String userName; private Integer age; private List<MobilePhone> mobilePhone;//土豪,多個手機,1對多 }
手機類
public class MobilePhone { private Integer mobilePhoneId; private String brand;//品牌 private double price;//價格 private User user;//主人 }
dao層
public interface UserDao { /** * 經過userId查詢user信息 * @param userId * @return */ User queryById(int userId); }
UserDao.xml中的select查詢語句
<select id="queryById" parameterType="int" resultMap="userMap"> SELECT u.user_name,u.age, m.brand,m.price FROM tb_user u,tb_mobile_phone m WHERE m.user_id=u.user_id AND u.user_id=#{userId} </select>
數據庫中,tb_mobile_phone中user_id做爲外鍵。那麼下面來看resultMap如何定義:
先定義 MobilePhoneDao.java
public interface MobilePhoneDao { List<MobilePhone> queryMbByUserId(int userId); }
而後實現該方法 MobilePhoneDao.xml
<resultMap type="MobilePhone" id="mobilePhoneMap"> <id property="mobilePhoneId" column="user_id"/> <result property="brand" column="brand"/> <result property="price" column="price"/> <association property="user" column="user_id" select= "com.zhu.ssm.dao.UserDao.queryById"> </association> </resultMap>
<select id="queryMbByUserId" parameterType="int" resultMap="mobilePhoneMap"> SELECT brand,price FROM tb_mobile_phone WHERE user_id=#{userId} </select>
作好以上準備工做,那就能夠在UserDao.xml中引用了
<resultMap type="User" id="userMap"> <id property="userId" column="user_id"/> <result property="userName" column="user_name"/> <result property="age" column="age"/> <collection property="mobilePhone" column="user_id" select="com.zhu.ssm.dao .MobilePhoneDao.queryMbByUserId"> </collection> </resultMap>
這種方法和association的第一種用法幾乎是同樣的不一樣之處就是mobilePhMap中用到了association ,queryMbByUserId中要使用mobilePhoneMap,而不能直接使用resultType。
<resultMap type="MobilePhone" id="mobilephoneMap"> <id column="mobile_phone_id" property="mobilePhoneId"/> <result column="brand" property="brand" /> <result column="price" property="price" /></resultMap>
<resultMap type="User" id="userMap"> <result property="userName" column="user_name"/> <result property="age" column="age"/> <collection property="mobilePhone" resultMap="mobilephoneMap" > </collection> </resultMap>
定義好這兩個resultMap,再引用UserMap就好了。
<resultMap type="User" id="userMap"> <result property="userName" column="user_name"/> <result property="age" column="age"/> <collection property="mobilePhone" column="user_id" ofType="MobilePhone"> <id column="mobile_phone_id" property="mobilePhoneId" /> <result column="brand" property="brand" /> <result column="price" property="price" /> </collection> </resultMap>
這種方法須要注意,必定要有ofType,collection 裝的元素類型是啥ofType的值就是啥,這個必定不能少。
注意:
全部resultMap中的type、select 標籤中的resultType以及association中的javaType,collection中的ofType,這裏只寫了類名,是由於在mybatis-config.xml中配置了typeAliases,不然就要寫該類的全類名。配置以下:
<typeAliases> <packagename="com.zhu.smm.entity"/> </typeAliases>
一、association表示的是has one的關係,一對一時使用。user has one card,因此在user的resultMap中接收card時應該用association;
二、collection表示的是has many的關係,一對多時使用。user has many mobilePhone,因此在user的resultMap中接收mobilePhone時應該用collection 。
三、都有三種用法,且很是相似,resultMap要複用建議第二種方法,不須要複用建議第三種方法。
四、特別注意表中主鍵字段要有所區分,不能都寫成id,要寫成user_id、card_id,反正要有所區分,否則查詢的時候會查不到完整的數據。