Mybatis的一對多(collection)和一對一(association)查詢
1、mybatis支持映射復雜的查詢結果集
2、表之間的關系
3、實體及其對應關系:
@Data @EqualsAndHashCode(callSuper = false) public class TestOne implements Serializable { private static final long serialVersionUID = 1L; private Integer id; // private String nickname; // private List<TestTwo> testTwos; }
@Data @EqualsAndHashCode(callSuper= false) public class TestTwo implements Serializable { private static final long serialVersionUID = 1L; private Integer id; // private String nickname; // private Integer oneId; // private TestOne testOne; }
4、mybatis---------Association: 一對一查詢的方式
<resultMap id="TestTwoAll"type="TestTwo"> <id property="id" column="twoid"/> <result property="nickname" column="twonickname"/> <result property="oneId" column="one_id"/> <association property="testOne" column="one_id" javaType="TestOne"> <id property="id"column="oneid"/> <result property="nickname" column="onenickname"/> </association> </resultMap> <select id="getTotalById" resultMap="TestTwoAll" parameterType="long"> SELECT one.id as oneid, one.nickname as onenickname, two.id as twoid, two.nickname as twonickname, two.one_id FROM test_one one,test_two two where one.id=two.one_id and two.id=#{value} </select>
5、mybatis---------Collection: 一對多查詢的方式
<resultMap id="TestOneAll" type="TestOne"> <result property="id" column="oneid"/> <result property="nickname" column="onenickname"/> <collection property="testTwos" column="one_id" ofType="TestTwo" javaType="ArrayList"> <result property="id" column="twoid"/> <result property="nickname" column="twonickname"/> <result property="oneId" column="one_id"/> </collection> </resultMap> <select id="getTotalById" resultMap="TestOneAll" parameterType="long"> SELECT one.id as oneid, one.nickname as onenickname, two.id as twoid, two.nickname as twonickname, two.one_id FROM test_one one,test_two two where one.id=two.one_id and one.id=#{VALUE } order by twoid desc </select>
附錄:
(1)建表語句:
CREATE TABLE `test_one` ( `id` int(11) NOT NULL AUTO_INCREMENT, `nickname` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; CREATE TABLE `test_two` ( `id` int(11) NOT NULL AUTO_INCREMENT, `nickname` varchar(255) NOT NULL, `one_id` int(11) NOT NULL, PRIMARY KEY (`id`), KEY `test_two_ibfk_1` (`one_id`), CONSTRAINT `test_two_ibfk_1` FOREIGN KEY (`one_id`) REFERENCES `test_one` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
(2)說明:(引自 http://blog.csdn.net/wxwzy738/article/details/24742495)
1》
id, result元素
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
這是最基本的結果集映射。id 和result 將列映射到屬性或簡單的數據類型字段(String, int, double, Date等)。
這兩者唯一不同的是,在比較對象實例時id 作為結果集的標識屬性。這有助於提高總體性能,特別是應用緩存和嵌套結果映射的時候。
2》
Association元素
<association property="author" column="blog_author_id" javaType=" Author">
<id property="id" column="author_id"/>
<result property="username" column="author_username"/>
</association>
Association元素處理“has-one”(一對一)這種類型關系。聯合映射與其它的結果集映射工作方式差不多,指定property、column、javaType(通常MyBatis會自動識別)、jdbcType(如果需要)、typeHandler。
不同的地方是您需要告訴MyBatis 如何加載一個聯合查詢。MyBatis使用兩種方式來加載:
·Nested Select:通過執行另一個返回預期復雜類型的映射SQL語句(即引用外部定義好的SQL語句塊)。
·Nested Results:通過嵌套結果映射(nested result mappings)來處理聯接結果集(joined results)的重復子集。
首先,讓我們檢查一下元素屬性。正如您看到的,它不同於普通只有select和resultMap屬性的結果映射。
Attribute |
Description |
property |
映射數據庫列的字段或屬性。如果JavaBean 的屬性與給定的名稱匹配,就會使用匹配的名字。否則,MyBatis 將搜索給定名稱的字段。兩種情況下您都可以使用逗點的屬性形式。比如,您可以映射到”username”,也可以映射到更復雜點的”address.street.number”。 |
column |
數據庫的列名或者列標簽別名。與傳遞給resultSet.getString(columnName)的參數名稱相同。 註意: 在處理組合鍵時,您可以使用column= “{prop1=col1,prop2=col2}”這樣的語法,設置多個列名傳入到嵌套查詢語句。這就會把prop1和prop2設置到目標嵌套選擇語句的參數對象中。 |
javaType |
完整java類名或別名(參考上面的內置別名列表)。如果映射到一個JavaBean,那MyBatis 通常會自行檢測到。然而,如果映射到一個HashMap,那您應該明確指定javaType 來確保所需行為。 |
jdbcType |
支持的JDBC類型列表中列出的JDBC類型。這個屬性只在insert,update 或delete 的時候針對允許空的列有用。JDBC 需要這項,但MyBatis 不需要。如果您直接編寫JDBC代碼,在允許為空值的情況下需要指定這個類型。 |
typeHandler |
我們已經在文檔中討論過默認類型處理器。使用這個屬性可以重寫默認類型處理器。它的值可以是一個TypeHandler實現的完整類名,也可以是一個類型別名。 |
聯合嵌套選擇(Nested Select for Association)
select |
通過這個屬性,通過ID引用另一個加載復雜類型的映射語句。從指定列屬性中返回的值,將作為參數設置給目標select 語句。表格下方將有一個例子。註意:在處理組合鍵時,您可以使用column=”{prop1=col1,prop2=col2}”這樣的語法,設置多個列名傳入到嵌套語句。這就會把prop1和prop2設置到目標嵌套語句的參數對象中。 |
3》
Collection元素
<collection property="posts" ofType="domain.blog.Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<result property="body" column="post_body"/>
</collection>
collection元素的作用差不多和association元素的作用一樣。事實上,它們非常相似,以至於再對相似點進行描述會顯得冗余,因此我們只關註它們的不同點。
會像下面這樣定義相應屬性:
private List<Post> posts;
映射一個嵌套結果集到一個列表,我們使用collection元素。就像association 元素那樣,我們使用嵌套查詢,或者從連接中嵌套結果集。
<resultMap id=”blogResult” type=”Blog”>
<collection property="posts" javaType=”ArrayList” column="blog_id"
ofType="Post" select=”selectPostsForBlog”/>
</resultMap>
<select id=”selectBlog” parameterType=”int” resultMap=”blogResult”>
SELECT * FROM BLOG WHERE ID = #{id}
</select>
<select id=”selectPostsForBlog” parameterType=”int” resultType="Author">
SELECT * FROM POST WHERE BLOG_ID = #{id}
</select>
* 一看上去這有許多東西需要註意,但大部分看起與我們在association元素中學過的相似。首先,您會註意到我們使用了collection元素,然後會註意到一個新的屬性“ofType”。這個元素是用來區別JavaBean屬性(或者字段)類型和集合所包括的類型。因此您會讀到下面這段代碼。
<collection property="posts" javaType=”ArrayList” column="blog_id"
ofType="Post" select=”selectPostsForBlog”/>
理解為:“一個名為posts,類型為Post的ArrayList集合(A collection of posts in an ArrayList of type Post)” 。
javaType屬性不是必須的,通常MyBatis 會自動識別,所以您通常可以簡略地寫成:
<collection property="posts" column="blog_id" ofType="Post"
select=”selectPostsForBlog”/>
Mybatis的一對多(collection)和一對一(association)查詢