Mybatis之ResultMap一个简短的引论,关联对象

时间:2023-03-08 16:20:49
Mybatis之ResultMap一个简短的引论,关联对象

基础部分能够查看我的还有一篇博客http://blog.csdn.net/elim168/article/details/40622491

MyBatis中在查询进行select映射的时候。返回类型能够用resultType,也能够用resultMap,resultType是直接表示返回类型的,而resultMap则是对外部ResultMap的引用,可是resultType跟resultMap不能同一时候存在。在MyBatis进行查询映射的时候,事实上查询出来的每个属性都是放在一个相应的Map里面的,当中键是属性名,值则是其相应的值。

当提供的返回类型属性是resultType的时候,MyBatis会将Map里面的键值对取出赋给resultType所指定的对象相应的属性。所以事实上MyBatis的每个查询映射的返回类型都是ResultMap,仅仅是当我们提供的返回类型属性是resultType的时候,MyBatis对自己主动的给我们把相应的值赋给resultType所指定对象的属性。而当我们提供的返回类型是resultMap的时候。由于Map不能非常好表示领域模型,我们就须要自己再进一步的把它转化为相应的对象,这经常在复杂查询中非常有作用。

有这样一个Blog.java文件

  1. import java.util.List;
  2. public class Blog {
  3. private int id;
  4. private String title;
  5. private String content;
  6. private String owner;
  7. private List<Comment> comments;
  8. public int getId() {
  9. return id;
  10. }
  11. public void setId(int id) {
  12. this.id = id;
  13. }
  14. public String getTitle() {
  15. return title;
  16. }
  17. public void setTitle(String title) {
  18. this.title = title;
  19. }
  20. public String getContent() {
  21. return content;
  22. }
  23. public void setContent(String content) {
  24. this.content = content;
  25. }
  26. public String getOwner() {
  27. return owner;
  28. }
  29. public void setOwner(String owner) {
  30. this.owner = owner;
  31. }
  32. public List<Comment> getComments() {
  33. return comments;
  34. }
  35. public void setComments(List<Comment> comments) {
  36. this.comments = comments;
  37. }
  38. @Override
  39. public String toString() {
  40. return " ----------------博客-----------------\n id: " + id + "\n title: " + title + "\n content: " + content
  41. + "\n owner: " + owner;
  42. }
  43. }

其所相应的数据库表中存储有id,title。Content,Owner属性,那么当我们进行以下这样一个查询映射的时候

  1. <typeAlias alias="Blog" type="com.tiantian.mybatis.model.Blog"/><!--来自MyBatis的配置文件mybatis_config.xml-->
  2. <select id="selectBlog" parameterType="int" resultType="Blog">
  3. select * from t_blog where id = #{id}
  4. </select><!--来自SQL映射文件BlogMapper.xml-->

MyBatis会自己主动创建一个ResultMap对象,然后基于查找出来的属性名进行键值对封装,然后再看到返回类型是Blog对象,再从ResultMap中取出与Blog对象相应的键值对进行赋值。

当返回类型直接是一个ResultMap的时候也是很实用的,这主要用在进行复杂联合查询上,由于进行简单查询是没有什么必要的。

我们先看看一个返回类型为ResultMap的简单查询。再看看复杂查询的使用方法。

简单查询的写法

  1. <resultMap type="Blog" id="BlogResult">
  2. <id column="id" property="id"/>
  3. <result column="title" property="title"/>
  4. <result column="content" property="content"/>
  5. <result column="owner" property="owner"/>
  6. </resultMap>
  7. <select id="selectBlog" parameterType="int" resultMap="BlogResult">
  8. select * from t_blog where id = #{id}
  9. </select>

select映射中resultMap的值是一个外部resultMap的id。表示返回结果映射到哪一个resultMap上。外部resultMap的type属性表示该resultMap的结果是一个什么样的类型。这里是Blog类型,那么MyBatis就会把它当作一个Blog对象取出。resultMap节点的子节点id是用于标识该对象的id的。而result子节点则是用于标识一些简单属性的,当中的Column属性表示从数据库中查询的属性,Property则表示查询出来的属性相应的值赋给实体对象的哪个属性。

简单查询的resultMap的写法就是这种。

接下来看一个复杂一点的查询。

有一个Comment类,当中有一个Blog的引用,表示是对哪个Blog的Comment,那么我们在查询Comment的时候把其相应的Blog也要查出来赋给其blog属性。

  1. import java.util.Date;
  2. public class Comment {
  3. private int id;
  4. private String content;
  5. private Date commentDate = new Date();
  6. private Blog blog;
  7. public int getId() {
  8. return id;
  9. }
  10. public void setId(int id) {
  11. this.id = id;
  12. }
  13. public String getContent() {
  14. return content;
  15. }
  16. public void setContent(String content) {
  17. this.content = content;
  18. }
  19. public Date getCommentDate() {
  20. return commentDate;
  21. }
  22. public void setCommentDate(Date commentDate) {
  23. this.commentDate = commentDate;
  24. }
  25. public Blog getBlog() {
  26. return blog;
  27. }
  28. public void setBlog(Blog blog) {
  29. this.blog = blog;
  30. }
  31. public String toString() {
  32. return blog + "\n ----------------评论-----------------\n id: " + id + "\n content: " + content + "\n commentDate: " + commentDate;
  33. }
  34. }

其写法是这种

  1. <!--来自CommentMapper.xml文件    -->
  2. <resultMap type="Comment" id="CommentResult">
  3. <association property="blog" select="selectBlog" column="blog" javaType="Blog"/>
  4. </resultMap>
  5. <select id="selectComment" parameterType="int" resultMap="CommentResult">
  6. select * from t_Comment where id = #{id}
  7. </select>
  8. <select id="selectBlog" parameterType="int" resultType="Blog">
  9. select * from t_Blog where id = #{id}
  10. </select>

其訪问情况是这种,先是请求id为selectComment的select映射,然后得到一个id为CommentResult的ResultMap对象,我们能够看到在相应的resultMap的返回类型是一个Comment对象。当中仅仅有一个association节点,而没有像前面说的简单查询所相应的id,result子节点,可是其仍会把相应的id等属性赋给Comment对象。这就是前面所说的MyBatis拥有自己主动封装功能。仅仅要你提供了返回类型。MyBatis会依据自己的推断来利用查询结果封装相应的对象,所曾经面的简单查询中。假设你不在resultMap中明白的指出id相应哪个字段,title相应哪个字段,MyBatis也会依据自身的推断来帮你封装,MyBatis的自身推断是把查询的field或其相应的别名与返回对象的属性进行比較,假设相匹配且类型也相匹配,MyBatis则会对其进行赋值。在上面相应的resultMap中关联了一个blog属性,其相应的JAVA类型为Blog,在上述的写法中,关联对象是通过子查询来进行关联的,当然也能够直接通过关联查询来进行关联。上面的association子节点中,Property属性表示是resultMap返回类型的哪个关联属性,对于上面的样例就是Comment管理的blog属性;select表示进行哪个select映射来映射相应的关联属性,即会去请求id为select所相应的值的select映射
来查询出其所关联的属性对象;Column表示当前关联对象在id为CommentResult的resultMap中所相应的键值对。该键值对将作为对关联对象子查询的參数,即将把在selectComment中查询出来的blog属性的值作为參数传给进行关联对象blog的子查询selectBlog的參数。javaType表示当前关联对象在JAVA中是什么类型。

上述介绍的是一对一或一对多的情况下。对一的一方的关联的查询。在实际应用中另一个用的比較多的应用是通过一的一方查出相应的多的一方。在拿出多的一方的时候也相同要把一的一方关联上,即在上述样例中,在拿出Blog对象的时候,就把其相应的Comment所有拿出来,在拿出Comment的时候也还是须要把其相应的Blog拿出来。这是在JAVA中通过一次请求就拿出来的。写法例如以下:

  1. <!-- 来自BlogMapper.xml文件 -->
  2. <resultMap type="Blog" id="BlogResult">
  3. <id column="id" property="id"/>
  4. <collection property="comments" select="selectCommentsByBlog" column="id" ofType="Comment"></collection>
  5. </resultMap>
  6. <resultMap type="Comment" id="CommentResult">
  7. <association property="blog" javaType="Blog" column="blog" select="selectBlog"/>
  8. </resultMap>
  9. <select id="selectBlog" parameterType="int" resultMap="BlogResult">
  10. select * from t_blog where id = #{id}
  11. </select>
  12. <!--  通过Blog来查找Comment   -->
  13. <select id="selectCommentsByBlog" parameterType="int" resultMap="CommentResult">
  14. select * from t_Comment where blog = #{blogId}
  15. </select>

上述请求的入口是id为selectBlog的select映射。返回结果为id为BlogResult的resultMap。id为BlogResult的类型为Blog,当中指定了id的属性和字段,指定id将对MyBatis内部的构造作用非常大。当中关联了一个comments对象,由于一个Blog能够有非常多Comment,该comments为一个集合。所以用集合collection进行映射,当中的select还是表示进行哪个子查询来查询相应的comments。column表示把上述查出来的哪个字段值当作參数传给子查询,ofType也是表示返回类型,这里的返回类型是集合内部的类型,之所以用ofType而不是用type是MyBatis内部为了和关联association进行差别。

測试代码:

  1. @Test
  2. public void selectCommentsByBlogTest() {
  3. SqlSession session = Util.getSqlSessionFactory().openSession();
  4. CommentMapper commentMapper = session.getMapper(CommentMapper.class);
  5. );
  6. for (Comment comment : comments)
  7. System.out.println(comment);
  8. session.close();
  9. }
  10. /**
  11. * 查询单条记录
  12. */
  13. @Test
  14. public void testSelectOne() {
  15. SqlSession session = Util.getSqlSessionFactory().openSession();
  16. BlogMapper blogMapper = session.getMapper(BlogMapper.class);
  17. );
  18. List<Comment> comments = blog.getComments();
  19. if (comments != null) {
  20. System.out.println("--------------Comments Size------------" + comments.size());
  21. for (Comment comment : comments)
  22. System.out.println(comment);
  23. }
  24. session.close();
  25. }

版权声明:本文博主原创文章,博客,未经同意不得转载。