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”/>