MyBatis关联查询之一对一查询

18 篇文章 9 订阅
4 篇文章 0 订阅

        关联查询一对一查询是最基础的关联查询知识,何谓一对一。比如本文要讲到的例子,学生去图书馆借书的例子,有一个表叫做tb_user表示学生的信息,另一个表表示tb_book,那么假定每个人只能借一本书,那么两个表之间的关系就是一对一的,即一本书只能借给一个人,一个人只能借一本书。所以相对来说,一对一的关联查询,逻辑比较清晰,容易理解。我们接下来通过两种方法进行讲解一对一的关联查询。

1.示例简介
        如下本文有如下两个表,tb_book表示被借出去书的情况,tb_user表示学生信息,现在需要查询借书者的相关信息。

        如果用sql语句完成,则是如下语句:
select * from tb_user,tb_book where tb_book.user_id=tb_user.id
        运行结果如下,正是需要的查询结果。接下来,介绍MyBatis中两种一对一关联查询的方法。

                           
2.方法一:通过构造新类
        1.两个表对应有两个实体类:User类和Book类。查询结果是既有Book类中的属性值,又有User类中的属性值,并且查询结果是一个对象集合,如果使用泛型,那么泛型类型无法确定,那么就构造一个类,可以继承其中一个类,然后将另一个类需要的属性添加到这个新类中,那么这个新构造的类就是查询结果输出的类型。
首先是User类的代码,是一个典型的JavaBean
package com.mybatis.model.impl;
import java.io.Serializable;
public class User implements Serializable {
	private Integer id;
	private String name;
	private String sex;
	private Integer age;
	public User()
	{
	}
	public User(String name,String sex,Integer age)
	{
		this.name=name;
		this.sex=sex;
		this.age=age;
	}
	public Integer getId()
	{
		return this.id;
	}
	public void setId(Integer id)
	{
		this.id=id;
	}
	
	public String getName()
	{
		return this.name;
	}
	public void setName(String name)
	{
		this.name=name;
	}
	
	public String getSex()
	{
		return this.sex;
	}
	public void setSex(String sex)
	{
		this.sex=sex;
	}
	
	public Integer getAge()
	{
		return this.age;
	}
	public void setAge(Integer age)
	{
		this.age=age;
	}
	public String toString()
	{
		return "User [id="+id+",name="+name+",sex="+sex+",age"+age+"]";
	}		
}
然后是Book类:
package com.mybatis.model.impl;

public class Book {
	public Integer book_id;
	public Integer user_id;
	public String book_name;
	
	public  Integer getBook_id()
	{
		return this.book_id;
	}
	
	public void setBook_id(Integer book_id)
	{
		this.book_id=book_id;
	}
	
	public Integer getUser_id()
	{
		return this.user_id;
	}
	
	public void setUser_id(Integer user_id)
	{
		this.user_id=user_id;
	}
	
	public String getBook_name()
	{
		return this.book_name;
	}
	
	public void setBook_name(String book_name)
	{
		this.book_name=book_name;
	}

}
2.接着便是构造新类BookOrder类,这里让该类继承Book类,然后将需要的User类的属性添加进去。

package com.mybatis.model.impl;

public class BookOrder extends Book {
	//除了继承Book类的所有属性,还需要User中的name和sex属性
	public String name;
	public String sex;
	
	public String getName()
	{
		return this.name;
	}
	public void setName(String name)
	{
		this.name=name;
	}
	
	public String getSex()
	{
		return this.sex;
	}
	public void setSex(String sex)
	{
		this.sex=sex;
	}
	
	public String toString()
	{
		return "User [book_id="+book_id+",user_id="+user_id+",book_name="+book_name+",name="+name+",sex="+sex+"]";
	}	

}
       3. 然后便是mapper代理文件BookOfUserMapper.xml,可以看出该代理文件内容比较简单,查询就是相当于普通的sql语句。
<?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.mapper.BookOfUserMapper">
	
	<select id="getBookOfUser" resultType="com.mybatis.model.impl.BookOrder">
		select tb_book.*,tb_user.name,tb_user.sex from tb_user,tb_book where tb_user.id=tb_book.user_id
	</select>
</mapper>
       4. 根据上述映射文件可以知道该代理文件对应的mapper接口是BookOfUserMapper接口。
package com.mybatis.mapper;
import java.util.*;
import com.mybatis.model.impl.*;
public interface BookOfUserMapper {
	public List<BookOrder> getBookOfUser();
	//public List<Book1> getBookInfo();
	

}
        5.将该mapper映射文件放入mybatis配置文件中

                                             
        6.测试程序:
package com.mybatis.test;
import java.util.*;
import java.io.InputStream;
import org.apache.ibatis.io.*;
import org.apache.ibatis.session.*;

import com.mybatis.mapper.*;
import com.mybatis.model.impl.*;;

public class QueryTest {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		// TODO Auto-generated method stub
		//读取MyBatis配置文件
		InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
		//初始化mybatis,创建SqlSessionFactory类的实例。
		SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
		//创建Session实例
		SqlSession session=sqlSessionFactory.openSession();
		//创建User对象
		BookOfUserMapper bookOfUserMapper=session.getMapper(BookOfUserMapper.class);
		List<BookOrder> list=bookOfUserMapper.getBookOfUser();
		System.out.println(list);
	}

}
7.运行测试程序,结果如下,正是需要的结果:



3.方法二:通过映射文件
        接下类讲述的是一种不需要增添新类的方法,即通过在mapper文件中进行操作。
1.首先假定最后输出的对象类型是Book1(区分上述的Book),但是在这个Book1类中需要添加User对象属性,相当于将两个类进行关联,以下是Book1类的代码:
package com.mybatis.model.impl;
import java.util.*;
public class Book1 {
	public Integer book_id;
	public Integer user_id;
	public String book_name;
	public User user;//添加User类型属性
	
	
	public  Integer getBook_id()
	{
		return this.book_id;
	}
	
	public void setBook_id(Integer book_id)
	{
		this.book_id=book_id;
	}
	
	public Integer getUser_id()
	{
		return this.user_id;
	}
	
	public void setUser_id(Integer user_id)
	{
		this.user_id=user_id;
	}
	
	public String getBook_name()
	{
		return this.book_name;
	}
	
	public void setBook_name(String book_name)
	{
		this.book_name=book_name;
	}
	public User getUser()
	{
		return this.user;
	}
	public void setUser(User user)
	{
		this.user=user;
	}
	public String toString()
	{
		return "User [book_id="+book_id+",user_id="+user_id+",book_name="+book_name+",name="+user.getName()+",sex="+user.getSex()+"]";
	}	
	
	
}


2.然后就是User类:
package com.mybatis.model.impl;
import java.io.Serializable;
public class User implements Serializable {
	private Integer id;
	private String name;
	private String sex;
	private Integer age;
	public User()
	{
	}
	public User(String name,String sex,Integer age)
	{
		this.name=name;
		this.sex=sex;
		this.age=age;
	}
	public Integer getId()
	{
		return this.id;
	}
	public void setId(Integer id)
	{
		this.id=id;
	}
	
	public String getName()
	{
		return this.name;
	}
	public void setName(String name)
	{
		this.name=name;
	}
	
	public String getSex()
	{
		return this.sex;
	}
	public void setSex(String sex)
	{
		this.sex=sex;
	}
	
	public Integer getAge()
	{
		return this.age;
	}
	public void setAge(Integer age)
	{
		this.age=age;
	}
	public String toString()
	{
		return "User [id="+id+",name="+name+",sex="+sex+",age"+age+"]";
	}		
}
3.然后便是mapper接口,定义相应的方法getBookInfo()。
package com.mybatis.mapper;
import java.util.*;
import com.mybatis.model.impl.*;
public interface BookOfUserMapper {
	//public List<BookOrder> getBookOfUser();
	public List<Book1> getBookInfo();
	

}
4.然后便是mapper文件:
<?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.mapper.BookOfUserMapper">
	<select id="getBookInfo" resultMap="bookOrder">
		select tb_book.*,tb_user.name,tb_user.sex from tb_user,tb_book where tb_user.id=tb_book.user_id
	</select>
	<resultMap type="com.mybatis.model.impl.Book1" id="bookOrder">
		<id property="user_id" column="user_id"/>
		<result property="book_id" column="book_id"/>
		<result property="book_name" column="book_name"/>
		<association property="user" javaType="com.mybatis.model.impl.User">
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="sex" column="sex"/>
		</association>   
	</resultMap>
</mapper>
    从上述的mapper文件可以看出,该查询结果输出的是resultMap名为bookOrder,这里主要是为了与以下的resultMap的id相匹配,可以实现映射,并定义该resultMap输出类型是Book1类。首先先列出Book1类的元素,其中<id property="user_id" column="user_id"/>这里的id的property是查询中使用与外表关联的属性即user_id,其它属性则用<result....>列出。然后通过<association property="user" javaType="com.mybatis.model.impl.User">来关联User类,即通过Book1类中的User类属性user来实现,这里的property: 表示关联查询的结果存储在com.mybatis.model.impl.User的user属性中,javaType表示关联查询的结果类型为User类,相当于将User类的被查询的几个属性值存储在user属性作为Book1类的一个对象属性。
5.测试程序:
package com.mybatis.test;
import java.util.*;
import java.io.InputStream;
import org.apache.ibatis.io.*;
import org.apache.ibatis.session.*;

import com.mybatis.mapper.*;
import com.mybatis.model.impl.*;;

public class QueryTest {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		// TODO Auto-generated method stub
		//读取MyBatis配置文件
		InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
		//初始化mybatis,创建SqlSessionFactory类的实例。
		SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
		//创建Session实例
		SqlSession session=sqlSessionFactory.openSession();
		
		BookOfUserMapper bookOfUserMapper=session.getMapper(BookOfUserMapper.class);
		//通过构建新类的关联查询结果
		List<BookOrder> list=bookOfUserMapper.getBookOfUser();
		System.out.println(list);
		
		//通过mapper文件添加resultMap实现的查询结果
		List<Book1> list1=bookOfUserMapper.getBookInfo();
		System.out.println(list1);
	}

}
6.运行程序结果如下,可以发现两种方法查询结果一致。

3.两种方法比较
        两种方法特点都非常明显,因此使用需要依情况而定。
1.方法一优点就是mapper映射文件简洁,但是需要添加新类,那么无疑添加了系统的复杂度。
2.方法二就是不用添加许多类,但是mapper映射文件变得十分复杂,如果查询多而且复杂,那么文件内容会十分庞大。


        如果需要源代码,请点击 mybatisdemo下载。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值