您的位置:首页 > 其它

Mybatis关联查询(嵌套查询)

2015-07-03 10:46 302 查看



三张表:user article blog

表的存储sql文件:



/*
Navicat MySQL Data Transfer

Source Server         : localhost
Source Server Version : 50620
Source Host           : localhost:3306
Source Database       : mybatis

Target Server Type    : MYSQL
Target Server Version : 50620
File Encoding         : 65001

Date: 2014-10-19 18:27:31
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `user`
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`userName` varchar(50) DEFAULT NULL,
`userAge` int(11) DEFAULT NULL,
`userAddress` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'summer', '30', 'shanghai');
INSERT INTO `user` VALUES ('2', 'test1', '22', 'suzhou');
INSERT INTO `user` VALUES ('3', 'test1', '29', 'some place');
INSERT INTO `user` VALUES ('4', 'lu', '28', 'some place');
INSERT INTO `user` VALUES ('5', 'xiaoxun', '27', 'nanjing');

-- ----------------------------
-- Table structure for `article`
-- ----------------------------
DROP TABLE IF EXISTS `article`;
CREATE TABLE `article` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`userid` int(11) NOT NULL,
`title` varchar(100) DEFAULT NULL,
`content` text,
`blogid` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of article
-- ----------------------------
INSERT INTO `article` VALUES ('1', '1', 'test_title_1', 'test_content_1', '1');
INSERT INTO `article` VALUES ('2', '1', 'test_title_2', 'test_content_2', '1');
INSERT INTO `article` VALUES ('3', '1', 'test_title_3', 'test_content_3', '2');
INSERT INTO `article` VALUES ('4', '1', 'test_title_4', 'test_content_4', '2');
INSERT INTO `article` VALUES ('5', '2', 'test_title_5', 'test_content_5', '2');

-- ----------------------------
-- Table structure for `blog`
-- ----------------------------
DROP TABLE IF EXISTS `blog`;
CREATE TABLE `blog` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of blog
-- ----------------------------
INSERT INTO `blog` VALUES ('1', 'xiaoxun_blog');
INSERT INTO `blog` VALUES ('2', 'zhang_blog');


配置文件Configuration.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- mybatis别名定义 -->
<typeAliases>
<typeAlias alias="User" type="com.mybatis.test.User"/>
<typeAlias alias="Article" type="com.mybatis.test.Article"/>
<typeAlias alias="Blog" type="com.mybatis.test.Blog"/>
</typeAliases>

<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis" />
<property name="username" value="root"/>
<property name="password" value="admin"/>
</dataSource>
</environment>
</environments>

<!-- mybatis的mapper文件,每个xml配置文件对应一个接口 -->
<mappers>
<mapper resource="com/mybatis/test/User.xml"/>
<mapper resource="com/mybatis/test/Article.xml"/>
<mapper resource="com/mybatis/test/Blog.xml"/>
</mappers>
</configuration>


User类的定义和User.xml的配置见上一文章。

Article类定义:


View
Code

Article类中有一个User类。

Article.xml的配置:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.mybatis.test.IArticleOperation">

<resultMap type="User" id="userResultMap">
<!-- 属性名和数据库列名映射 -->
<id property="id" column="user_id"  />
<result property="userName" column="user_userName"  />
<result property="userAge" column="user_userAge"  />
<result property="userAddress" column="user_userAddress"  />
</resultMap>

<!-- User join Article进行联合查询  (一对一)-->
<resultMap id="articleResultMap" type="Article">
<id property="id" column="article_id" />
<result property="title" column="article_title" />
<result property="content" column="article_content" />
<!-- 将article的user属性映射到userResultMap -->
<association property="user" javaType="User" resultMap="userResultMap"/>
</resultMap>

<!-- 使用别名来映射匹配 -->
<select id="getUserArticles" parameterType="int" resultMap="articleResultMap">
select user.id user_id,user.userName user_userName,user.userAddress user_userAddress,
article.id article_id,article.title article_title,article.content article_content
from user,article
where user.id=article.userid and user.id=#{id}
</select>

<!-- 另一种联合查询  (一对一)的实现,但是这种方式有“N+1”的问题 -->
<!--  <resultMap id="articleResultMap" type="Article">
<id property="id" column="article_id" />
<result property="title" column="article_title" />
<result property="content" column="article_content" />
<association property="user" javaType="User" column="userid" select="selectUser"/>
</resultMap>

<select id="selectUser" parameterType="int" resultType="User">
select * from user where id = #{id}
</select> -->

</mapper>


Blog类定义:


View
Code

Blog类中有一个List<Article>。

Blog.xml配置:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.mybatis.test.IBlogOperation">

<resultMap id="userResultMap" type="User">
<id property="id" column="user_id"  />
<result property="userName" column="user_userName"  />
<result property="userAge" column="user_userAge"  />
<result property="userAddress" column="user_userAddress"  />
</resultMap>

<resultMap id="articleResultMap" type="Article">
<id property="id" column="article_id" />
<result property="title" column="article_title" />
<result property="content" column="article_content" />
<association property="user" javaType="User" resultMap="userResultMap"/>
</resultMap>

<resultMap id="blogResultMap" type="Blog">
<id property="id" column="blog_id" />
<result property="title" column="blog_title" />
<!-- 将article list属性映射到collection -->
<collection property="articles" ofType="Article" resultMap="articleResultMap"/>
</resultMap>

<!-- select语句 -->
<select id="getBlogByID" parameterType="int" resultMap="blogResultMap">
select user.id user_id,user.userName user_userName,user.userAddress user_userAddress,
article.id article_id,article.title article_title,article.content article_content,
blog.id blog_id, blog.title blog_title
from user,article,blog
where user.id=article.userid and blog.id=article.blogid and blog.id=#{id}
</select>

</mapper>


IArticleOperation定义:

package com.mybatis.test;

import java.util.List;

public interface IArticleOperation {

public List<Article> getUserArticles(int userID);
}


IBlogOperation定义:

package com.mybatis.test;

public interface IBlogOperation {

Blog getBlogByID(int id);

}


Test类:


View
Code

Mybatis的“N+1查询问题”

示例:

<resultMap id=”blogResult” type=”Blog”>
<association property="author" column="blog_author_id"
javaType="Author" select=”selectAuthor” />
</resultMap>

<select id=”selectBlog” parameterType=”int” resultMap=”blogResult”>
SELECT * FROM BLOG WHERE ID = #{id}
</select>

<select id=”selectAuthor” parameterType=”int” resultType="Author">
SELECT * FROM AUTHOR WHERE ID = #{id}
</select>


有两个查询语句:一个来加载博客,另外一个来加载作者,而且博客的结果映射描述了“selectAuthor”语句应该被用来加载它的 author 属性。

其他所有的属性将会被自动加载,假设它们的列和属性名相匹配。

这种方式很简单,但是对于大型数据集合和列表将不会表现很好。问题就是我们熟知的“N+1 查询问题”。概括地讲,N+1 查询问题可以是这样引起的:

你执行了一个单独的 SQL 语句来获取结果列表(就是“+1”)。

对返回的每条记录,你执行了一个查询语句来为每个加载细节(就是“N”)。

这个问题会导致成百上千的 SQL 语句被执行。这通常不是期望的。

可以采用关联的嵌套结果来解决这个问题:

<resultMap id="blogResult" type="Blog">
<id property=”id” column="blog_id" />
<result property="title" column="blog_title" />
<association property="author" column="blog_author_id"
javaType="Author" resultMap=”authorResult” />
</resultMap>

<resultMap id="authorResult" type="Author">
<id property="id" column="author_id" />
<result property="username" column="author_username" />
<result property="password" column="author_password" />
<result property="email" column="author_email" />
<result property="bio" column="author_bio" />
</resultMap>


resultMap 这是结果映射的 ID,可以映射关联的嵌套结果到一个合适的对象图中。这是一种替代方法来调用另外一个查询语句。

代码下载:http://download.csdn.net/detail/luxiaoxun/8056559

Source Code:https://github.com/luxiaoxun/MybatisDemo

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: