mybatis实战教程(mybatis in action)之四:实现关联数据的查询
有了前面几章的基础,对一些简单的应用是可以处理的,但在实际项目中,经常是关联表的查询,比如最常见到的多对一,一对多等。这些查询是如何处理的呢,这一讲就讲这个问题。我们首先创建一个Article 这个表,并初始化数据.
Drop TABLE IF EXISTS `article`;
Create TABLE `article` (
`id` int(11) NOT NULL auto_increment,
`userid` int(11) NOT NULL,
`title` varchar(100) NOT NULL,
`content` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; -- ----------------------------
-- 添加几条测试数据
-- ----------------------------
Insert INTO `article` VALUES ('', '', 'test_title', 'test_content');
Insert INTO `article` VALUES ('', '', 'test_title_2', 'test_content_2');
Insert INTO `article` VALUES ('', '', 'test_title_3', 'test_content_3');
Insert INTO `article` VALUES ('', '', 'test_title_4', 'test_content_4');
你应该发现了,这几个文章对应的userid都是1,所以需要用户表user里面有id=1的数据。可以修改成满足自己条件的数据.按照orm的规则,表已经创建了,那么肯定需要一个对象与之对应,所以我们增加一个 Article 的class
package com.yihaomen.mybatis.model;
public class Article {
private int id;
private User user;
private String title;
private String content;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
注意一下,文章的用户是怎么定义的,是直接定义的一个User对象。而不是int类型。
多对一的实现
场景:在读取某个用户发表的所有文章。当然还是需要在User.xml 里面配置 select 语句, 但重点是这个 select 的resultMap 对应什么样的数据呢。这是重点,这里要引入 association 看定义如下:
<!-- User 联合文章进行查询 方法之一的配置 (多对一的方式) -->
<resultMap id="resultUserArticleList" type="Article">
<id property="id" column="aid" />
<result property="title" column="title" />
<result property="content" column="content" /> <association property="user" javaType="User">
<id property="id" column="id" />
<result property="userName" column="userName" />
<result property="userAddress" column="userAddress" />
</association>
</resultMap> <select id="getUserArticles" parameterType="int" resultMap="resultUserArticleList">
select user.id,user.userName,user.userAddress,article.id aid,article.title,article.content from user,article
where user.id=article.userid and user.id=#{id}
</select>
这样配置之后,就可以了,将select 语句与resultMap 对应的映射结合起来看,就明白了。用association 来得到关联的用户,这是多对一的情况,因为所有的文章都是同一个用户的。
还有另外一种处理方式,可以复用我们前面已经定义好的 resultMap ,前面我们定义过一个 resultListUser ,看这第二种方法如何实现:
<resultMap type="User" id="resultListUser">
<id column="id" property="id" />
<result column="userName" property="userName" />
<result column="userAge" property="userAge" />
<result column="userAddress" property="userAddress" />
</resultMap> <!-- User 联合文章进行查询 方法之二的配置 (多对一的方式) -->
<resultMap id="resultUserArticleList-2" type="Article">
<id property="id" column="aid" />
<result property="title" column="title" />
<result property="content" column="content" />
<association property="user" javaType="User" resultMap="resultListUser" />
</resultMap> <select id="getUserArticles" parameterType="int" resultMap="resultUserArticleList">
select user.id,user.userName,user.userAddress,article.id aid,article.title,article.content from user,article
where user.id=article.userid and user.id=#{id}
</select>
将 association 中对应的映射独立抽取出来,可以达到复用的目的。
好了,现在在Test 类中写测试代码:
public void getUserArticles(int userid){
SqlSession session = sqlSessionFactory.openSession();
try {
IUserOperation userOperation=session.getMapper(IUserOperation.class);
List<Article> articles = userOperation.getUserArticles(userid);
for(Article article:articles){
System.out.println(article.getTitle()+":"+article.getContent()+
":作者是:"+article.getUser().getUserName()+":地址:"+
article.getUser().getUserAddress());
}
} finally {
session.close();
}
}
漏掉了一点,我们一定要在 IUserOperation 接口中,加入 select 对应的id 名称相同的方法:
public List<Article> getUserArticles(int id);
另外需要 Configuration.xml中加入
<typeAliases>
<typeAlias alias="User" type="com.shanheyongmu.mybatis.model.User"/>
<typeAlias alias="Article" type="com.shanheyongmu.mybatis.model.Article"/>
</typeAliases>
然后运行就可以测试。
关联查询(多表查询)的时候。。设置的aid是作用吗?
如果你不设置那个别名,那么结果集中将会有两个id列。会造成映射混乱吧。我做这个例子的时候没有设置别名,结果明明是4条记录,查询出来就只有1条了。
由于原文转载还是存在错误。特此粘贴 run as main 通过的代码
user.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.shanheyongmu.mybatis.models.UserMapper"> -->
<mapper namespace="com.shanheyongmu.mybatis.inter.IUserOperation">
<select id="selectUserByID" parameterType="int" resultType="User">
select * from user where id=#{id}
</select>
<!-- 多对一 方二 start--><!-- 为了返回list 类型而定义的returnMap -->
<resultMap type="User" id="resultListUser">
<id column="id" property="id"/>
<result column="userName" property="userName"/>
<result column="userAge" property="userAge"/>
<result column="userAddress" property="userAddress"/>
</resultMap> <!-- 返回list的select语句,注意resultMap的值是指向 前面定义好的-->
<select id="selectUsers" parameterType="string" resultMap="resultListUser">
select * from user where username like #{username}
</select>
<!-- User联合文章进行查询 方法二的配置 多对一 -->
<resultMap type="Article" id="resultUserArticleList2">
<id property="id" column="aid"/>
<result property="title" column="title"/>
<result property="content" column="content"/>
<association property="user" javaType="User" resultMap="resultListUser"/>
</resultMap> <!-- 多对一 方二 end-->
<!-- User 联合文章进行查询 方法之一的配置 (多对一的方式) start -->
<resultMap type="Article" id="resultUserArticleList">
<id column="aid" property="id"/>
<result column="title" property="title"/>
<result column="content" property="content"/> <association property="user" javaType="User">
<id column="id" property="id"/>
<result column="userName" property="userName"/>
<result column="userAddress" property="userAddress"/>
</association>
</resultMap>
<!-- 方法一 end -->
<!-- 查询语句 方法一 二公用 -->
<select id="getUserArticles" parameterType="int" resultMap="resultUserArticleList">
select user.id,user.userName,user.userAddress,article.id aid,article.title,article.content from user,article where user.id=article.userid and user.id=#{id}
</select> <!-- 执行增加操作的SQL语句。id和parameterType
分别与IUserOperation接口中的addUser方法的名字和
参数类型一致。以#{name}的形式引用Student参数
的name属性,MyBatis将使用反射读取Student参数
的此属性。#{name}中name大小写敏感。引用其他
的gender等属性与此一致。seGeneratedKeys设置
为"true"表明要MyBatis获取由数据库自动生成的主
键;keyProperty="id"指定把获取到的主键值注入
到Student的id属性 --> <insert id="addUser" parameterType="User" useGeneratedKeys="true" keyProperty="id"> insert into user(userName,userAge,userAddress) values(#{username},#{userAge},#{userAddress})
</insert> <update id="updateUser" parameterType="User">
update user set userName=#{userName},userAge=#{userAge},userAddress=#{userAddress} where id=#{id}
</update> <delete id="deleteUser" parameterType="int">
delete from user where id=#{id}
</delete> </mapper>
Test.java
package com.yihaomen.test; import java.io.Reader;
import java.util.List; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; import com.yihaomen.mybatis.inter.IUserOperation;
import com.yihaomen.mybatis.model.Article;
import com.yihaomen.mybatis.model.User; public class Test {
private static SqlSessionFactory sqlSessionFactory;
private static Reader reader; static{
try{
reader = Resources.getResourceAsReader("Configuration.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
}catch(Exception e){
e.printStackTrace();
}
} public static SqlSessionFactory getSession(){
return sqlSessionFactory;
} public void getUserArticles(int userid){
SqlSession session = sqlSessionFactory.openSession();
try {
IUserOperation userOperation=session.getMapper(IUserOperation.class);
List<Article> articles = userOperation.getUserArticles(userid);
for(Article article:articles){
System.out.println(article.getTitle()+":"+article.getContent()+
":作者是:"+article.getUser().getUserName()+":地址:"+
article.getUser().getUserAddress());
}
} finally {
session.close();
}
} public static void main(String[] args) {
Test testUser=new Test();
testUser.getUserArticles(1);
} }
config.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>
<typeAliases>
<typeAlias alias="User" type="com.shanheyongmu.mybatis.model.User"/>
<typeAlias alias="Article" type="com.shanheyongmu.mybatis.model.Article"/>
</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://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments> <mappers>
<mapper resource="com/shanheyongmu/mybatis/model/User.xml"/>
</mappers> </configuration>
mybatis实战教程(mybatis in action)之四:实现关联数据的查询的更多相关文章
- 4. mybatis实战教程(mybatis in action)之四:实现关联数据的查询
转自:https://www.cnblogs.com/shanheyongmu/p/5653599.html 有了前面几章的基础,对一些简单的应用是可以处理的,但在实际项目中,经常是关联表的查询,比如 ...
- 【转】mybatis实战教程(mybatis in action),mybatis入门到精通
MyBatis 目录(?)[-] mybatis实战教程mybatis in action之一开发环境搭建 mybatis实战教程mybatis in action之二以接口的方式编程 mybatis ...
- mybatis实战教程(mybatis in action),mybatis入门到精通
转自:http://www.yihaomen.com/article/java/302.htm (读者注:其实这个应该叫做很基础的入门一下下,如果你看过hibernate了那这个就非常的简单) (再加 ...
- mybatis实战教程(mybatis in action),mybatis入门到精通(转)
转自:http://www.yihaomen.com/article/java/302.htm (读者注:其实这个应该叫做很基础的入门一下下,如果你看过Hibernate了那这个就非常的简单) (再加 ...
- 转)mybatis实战教程(mybatis in action),mybatis入门到精通
mybatis实战教程(mybatis in action),mybatis入门到精通 http://limingnihao.iteye.com/blog/781671 http://blog.csd ...
- 1.mybatis实战教程mybatis in action之一开发环境搭建
转自:https://www.cnblogs.com/shanheyongmu/p/5652471.html 什么是mybatis MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框 ...
- mybatis实战教程(mybatis in action)之四:实现关联数据的查询
有了前面几章的基础,对一些简单的应用是可以处理的,但在实际项目中,经常是关联表的查询,比如最常见到的多对一,一对多等.这些查询是如何处理的呢,这一讲就讲这个问题.我们首先创建一个Article 这个表 ...
- mybatis实战教程(mybatis in action)之九:mybatis 代码生成工具的使用
mybatis 应用程序,需要大量的配置文件,对于一个成百上千的数据库表来说,完全手工配置,这是一个很恐怖的工作量. 所以mybatis 官方也推出了一个mybatis代码生成工具的jar包. 今天花 ...
- mybatis实战教程(mybatis in action)之二:以接口的方式编程
前面一章,已经搭建好了eclipse,mybatis,mysql的环境,并且实现了一个简单的查询.请注意,这种方式是用SqlSession实例来直接执行已映射的SQL语句:session.select ...
随机推荐
- Android ButterKnife注解框架使用
这段时间学习了下ButterKnife注解框架,学习的不是特别深入,但是基础也差不多了,在此记录总结一下. ButterKnife是一个Android View注入的库,主要是注解的使用,可以减少很多 ...
- Java Web----Java Web的数据库操作(三)
Java Web的数据库操作 前面介绍了JDBC技术和JDBC API及API的使用示例,下面详细介绍JDBC在Web中的应用. Java Web----Java Web的数据库操作(一) Java ...
- Delphi 的插件框架 WisdomPluginFramework
WisdomPluginFramework是融合OSGI微内核理念 + Eclipse的扩展点概念而精心设计的轻量级插件框架, 由Delphi实现,但可以使用于Delphi.BCB.VC++中,提供非 ...
- X86调用约定 calling convention
http://zh.wikipedia.org/wiki/X86%E8%B0%83%E7%94%A8%E7%BA%A6%E5%AE%9A 这里描述了在x86芯片架构上的调用约定(calling con ...
- 学习mfc书籍
Visual C++ and MFC Programming http://www.math.hcmuns.edu.vn/~tatuana/C%20For%20Win/MFC/Tai%20Lieu%2 ...
- promise和Rxjs的一点区别
promise 代码 let promise = new Promise( (resolve) => { setTimeout(() => { resolve('chen'); },200 ...
- Intent 的Flag属性(Activity在栈位置的主宰者)
Intent 的Flag属性可用来控制Activity在栈中的排列位置,本文列举了常见的Flag. 例--(以无动画方式启动ActivityB): Intent intent=new Intent(A ...
- [译林军] 译~CrossBridge 简介
本文由 9ria 社区译林军翻译,转载请注明出处.加入译林军 :http://bbs.9ria.com/thread-286920-1-1.html CrossBridge 是 Adobe Fla ...
- OpenCV Shi-Tomasi角点检测子
Shi-Tomasi角点检测子 目标 在这个教程中我们将涉及: 使用函数 goodFeaturesToTrack 来调用Shi-Tomasi方法检测角点. 理论 代码 这个教程的代码如下所示.源代码还 ...
- 第一章 consul简介
1.consul的作用 服务发现 Consul clients提供服务(例如API) 其他的client发现服务的提供者(通过DNS或http,应用可以轻松的发现他们所依赖的服务) 健康检查 Key- ...