MyBatis--关联查询
来源:互联网 发布:mac 搜狗输入法设置 编辑:程序博客网 时间:2024/06/09 18:52
MyBatis–关联查询
当查询内容涉及到具有关联关系的多个表时,就需要使用关联查询。根据表与表间的关联关系的不同,关联查询分为四种:
- 一对一关联查询
- 一对多关联查询
- 多对一关联查询
- 多对多关联查询
一、一对多关联查询
一对多关联查询是指,在查询一对象的时候,同时将其所关联的多放对象也都查询出来。
例:国家Country与部长Minister间的一对多关系
1.定义实体
若定义的是双向关联,即双方的属性中均有对方的对象作为作用域属性出现,那么它们在定义个各自的toString()方法时需要注意,只让某一方可以输出另一方即可,不要让双方的toString()方法均可输出对方。这样会形成递归调用,程序出错。
Country:
public class Country { private Integer cid; private String cname; //关联属性 private Set<Minister> ministers;}
Minister:
public class Minister { private Integer mid; private String mname;}
2.定义数据库表
3.定义dao接口
public interface ICountyrDao { Country selectCountryById(int cid);}
4.测试类:
public class MyTest { private ICountryDao dao; private SqlSession session; @Before public void setUp(){ session = MyBatisUtils.getSqlSession(); dao = session.getMapper(ICountryDao.class); } @After public void tearDown(){ if(session!=null){ session.close(); } } @Test public void test01(){ Country country = dao.selectCountryById(2); System.out.println(country); } }
5.映射文件
方式一:多表连接查询方式:
<mapper namespace="com.hcx.dao.ICountryDao"> <resultMap type="Country" id="countryMapper"> <id column="cid" property="cid"/> <result column="cname" property="cname"/> <collection property="ministers" ofType="Minister"> <id column="mid" property="mid"/> <result column="mname" property="mname"/> </collection> </resultMap> <select id="selectCountryById" resultMap="CountryMapper"> select cid,cname,mid,mname from country,minster where countryId=cid and cid=#{cid} </select></mapper>
注意,此时即使字段名与属性名相同,在中也要写出他们的映射关系。因为框架是依据封装对象的。
在映射文件中使用标签体现出两个实体对象间的关联关系。其两个属性的意义为:
- property:指定关联属性,即Country类中的集合属性
- ofType:集合属性的泛型类型
方式二:多表单独查询方式:
多表连接查询方式是将多张表进行连接,连为一张表后进行查询。其查询的本质是一张表。而多表单独查询方式是多张表各自查询各自的相关内容,需要多张表的联合数据,则将主表的查询结果联合其他表的查询结果,封装为一个对象。
多个查询时可以跨越多个映射文件的,即是可以跨越多个namespace的。在使用其它namespace的查询时,添加上其所在的namespace即可。
<mapper namespace="com.hcx.dao.ICountryDao"> <select id="selectMinisterByCountry" resultType="Minister"> select mid,mname from minister where countryId=#{cid} </select> <resultMap type="Country" id="countryMapper"> <id column="cid" property="cid"/> <result column="cname" property="cname"/> <collection property="ministers" ofType="Minister" select="selectMinisterByCountry" column="cid"/> </resultMap> <select id="selectCountryById" resultMap="CountryMapper"> select cid,cname from country where cid=#{cid} </select></mapper>
手动sql语句过程:
select cid,cname from country where cid=2
select mid,mname from minister where countryId=2
关联属性的数据来自于另一个查询。而该查询的动态参数countryId=#{cid}的值来自于查询的查询结果字段cid。
二、多对一关联查询
这里的多对一关联查询是指,在查询多方对象的时候,同时将其所关联的一方对象也查询出来。
由于查询多方对象时也是一个一个查询,所以多对一关联查询,其实就是一对一关联查询。即一对一关联查询的实现方式与多对一的实现方式是相同的。
例:部长Minister与国家Country间的多对一关系
1.实体类:
Minister:
public class Minister { private Integer mid; private String mname; //关联属性 private Country country;}
Country:
public class Country { private Integer cid; private String cname; }
2.dao接口:
public interface IMinisterDao { Minister selectMinisterById(int mid);}
3.测试类:
public class MyTest { private IMinisterDao dao; private SqlSession session; @Before public void before(){ session = MyBatisUtils.getSqlSession(); dao = session.getMapper(IMinisterDao.class); } @After public void tearDown(){ if(session!=null){ session.close(); } } @Test public void test01(){ Minister minister = dao.selectMinisterById(2); System.out.println(minister); }}
映射文件:
方式一:多表连接查询方式:
<mapper namespace="com.hcx.dao.IMinisterDao"> <resultMap type="Minister" id="ministerMapper"> <id column="mid" property="mid"/> <result column="mname" property="mname"/> <association property="country" javaType="Country"> <id column="cid" property="cid"/> <result column="cname" property="cname"/> </association> </resultMap> <select id="selectMinisterById" resultMap="ministerMapper"> select mid,mname,cid,cname from minister,country where countryId=cid and mid=#{mid} </select></mapper>
注意,在映射文件中使用标签体现出两个实体对象间的关联关系。
- property:指定关联属性,即Minister类中的country属性
- javaType:关联属性的类型
方式二:多表单独查询方式:
<mapper namespace="com.hcx.dao.IMinisterDao"> <select id="selectCountryById" resultType="Country"> select cid,cname from country where cid=#{cid} </select> <resultMap type="Minister" id="ministerMapper"> <id column="mid" property="mid"/> <result column="mname" property="mname"/> <association property="country" javaType="Country" select="selectCountryById" column="countryId"/> </resultMap> <select id="selectMinisterById" resultMap="ministerMapper"> select mid,mname,countryId from minister where mid=#{mid} </select></mapper>
手动写sql过程:
select mid,mname,countryId from minister where mid=2
select cid,cname from country where cid=1
三、自关联查询
所谓自关联查询是指,自己即充当一方,又充当多方,是1:n或n:1的变型。例如,对于新闻栏目NewsLabel,可以充当一方,即父栏目,也可以充当多方,即子栏目。而反映到DB表中,只有一张表,这张表中具有一个外键,用于表示该栏目的父栏目。一级栏目没有父栏目,所以可以将其外键值设为0,而子栏目则具有外键值。
将自关联分为两种情况。一种是当作1:n,即当前类作为一方,其包含多方的集合域属性。一种是当作n:1,即当前类作为多方,其包含一方的域属性。
1.自关联的DB表
手动查询:
2.以一对多方式处理
以一对多方式处理,即一方可以看到多方。该处理方式的应用场景比较多。例如页面点击父栏目,显示出其子栏目。将鼠标定位在窗口中的某菜单项上会显示其所有子菜单项等。
查询指定栏目的所有子孙栏目
根据指定的id,仅查询出其所有子栏目。包括其所有辈分的孙子栏目。即给出的插叙id实际为父栏目id
a.实体类
//新闻栏目:当前的新闻栏目被看作是一方,即父栏目public class NewsLabel { private Integer id; private String name; //栏目名称 private Set<NewsLabel> children;}
b.dao接口
public interface INewsLabelDao { List<NewsLabel> selectChildrenByParent(int pid);}
c.mapper映射
通过select语句的递归调用实现查询所有下级栏目的功能。查询结果的集合数据来自于递归调用的selectChildrenByParentId查询。与第一次进行该查询不同的是,第一次的pid动态参数值来自于调用方法传递来的实参,而中查询语句的pid动态参数值来自于上一次的查询结果的id值
<mapper namespace="com.hcx.dao.INewsLabelDao"> <resultMap type="NewsLabel" id="newslabelMapper"> <id column="id" property="id"/> <result column="name" property="name"/> <collection property="children" ofType="NewsLabel" select="selectChildrenByParent" column="id"/> </resultMap> <select id="selectChildrenByParent" resultMap="newsLabelMapper"> select id,name from newslabel where pid=#{pid} </select></mapper>
d.测试类
public class MyTest { private INewsLabelDao dao; private SqlSession session; @Before public void before(){ session = MyBatisUtils.getSqlSession(); dao = session.getMapper(INewsLabelDao.class); } @After public void tearDown(){ if(session!=null){ session.close(); } } @Test public void test01(){ List<NewsLabel> children = dao.selectChildrenByParent(1); for (NewsLabel newsLabel : children) { System.out.println(newsLabel); } } }
查询指定栏目及其所有子孙栏目
查询结果既要包含指定id的当前栏目,还包含其所有辈分的孙子栏目。即给出的id实际为当前要查询的栏目的id。
a.dao接口:
public interface INewsLabelDao { //List<NewsLabel> selectChildrenByParent(int pid); NewsLabel selectNewsLabelById(int id);}
b.mapper映射文件
<mapper namespace="com.hcx.dao.INewsLabelDao"> <select id="selectNewslabelByParent" resultMap="newslabelMapper"> select id,name from newslabel where pid=#{id} </select> <resultMap type="NewsLabel" id="newslabelMapper"> <id column="id" property="id"/> <result column="name" property="name"/> <collection property="children" ofType="NewsLabel" select="selectNewslabelByParent" column="id"/> </resultMap> <select id="selectNewslabelById" resultMap="newsLabelMapper"> select id,name from newslabel where id=#{id} </select></mapper>
c.测试类
@Testpublic void test02(){ NewsLabel newslabel = dao.selectNewsLabelById(1); System.out.println(newslabel);}
3.以多对一方式处理
多对一方式处理,即多方可以看到一方。该处理方式的应用场景,例如在网页上显示当前页面的站内位置
a.实体类
//新闻栏目:当前的新闻栏目被看作是多方,即子栏目public class NewsLabel { private Integer id; private String name; //栏目名称 private NewsLabel parent;}
b.dao接口
public interface INewsLabelDao { //List<NewsLabel> selectChildrenByParent(int pid); NewsLabel selectNewsLabelById(int id);}
c.mapper映射:
<mapper namespace="com.hcx.dao.INewsLabelDao"> <!-- <select id="selectNewsLabelById" resultMap="newslabelMapper"> select id,name,pid from newslabel where id=#{pid} </select> --> <resultMap type="NewsLabel" id="newslabelMapper"> <id column="id" property="id"/> <result column="name" property="name"/> <association property="parent" javaType="NewsLabel" select="selectNewsLabelById" column="pid"/> </resultMap> <select id="selectNewsLabelById" resultMap="newslabelMapper"> select id,name,pid from newslabel where id=#{id} </select></mapper>
d.测试类
@Testpublic void test02(){ NewsLabel newslabel = dao.selectNewsLabelById(1); System.out.println(newslabel);}
四、多对多关联查询
多对多关联关系,例如一个学生可以选多门课程,而一门课程可以由多个学生选择。多对多关系,其实是由两个互反的一对多关系组成。一般情况下,多对多关系都会通过一个中间表来建立,例如选课表。
1.定义实体:
在定义双向关联(双方均可看到对方的关联关系)的实体的toString方法时,只让一方的toString方法中输出对方,不要让双方均可输出对方。否则将会出现输出时的递归现象。
Student:
public class Student { private Integer sid; private String sname; private Set<Course> courses;}
Course:
public class Course { private Integer cid; private String cname; private Set<Student> students;}
2.数据库表:
3.dao接口
public interface IStudentDao { Student selectStudentById(int sid);}
4.mapper映射
多对多关联关系也是通过映射文件的体现的。但是,需要注意的是SQL语句中是对三张表的连接查询。
<mapper namespace="com.hcx.dao.IStudentDao"> <resultMap type="Student" id="studentMapper"> <id column="sid" property="sid"/> <result column="sname" property="sname"/> <collection property="courses" ofType="Course"> <id column="cid" property="cid"/> <result column="cname" property="cname"/> </collection> </resultMap> <select id="selectStudentById" resultMap="studentMapper"> select sid,sname,cid,cname from student,middle,course where sid=studentId and cid=courseId and sid=#{sid} </select></mapper>
5.测试类:
public class MyTest { private IStudentDao dao; private SqlSession session; @Before public void before(){ session = MyBatisUtils.getSqlSession(); dao = session.getMapper(IStudentDao.class); } @After public void tearDown(){ if(session!=null){ session.close(); } } @Test public void test01(){ Student student = dao.selectStudentById(1); System.out.println(student); }}
- mybatis关联查询
- mybatis表关联查询
- Mybatis关联表查询
- MyBatis关联查询
- Mybatis关联查询
- MyBatis 关联查询
- mybatis实现关联查询
- Mybatis如何关联查询
- mybatis 关联sql查询
- MyBatis关联查询(一对一)
- mybatis 关联查询
- MyBatis 关联查询
- mybatis一对一关联查询
- Mybatis关联查询
- Mybatis的关联查询
- MyBatis关联查询
- Mybatis一对一关联查询
- mybatis的关联查询
- uefi+gpt+centos7探索历程之一:win10下安装centos7
- Python资料
- MessagePack二进制序列化动态库的使用
- 中位数
- Win7下U盘安装Ubuntu14.04双系统步骤
- MyBatis--关联查询
- C#设计模式---单例模式
- 图形数据库 Neo4j 开发
- This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
- oj 3058: 算法设计:直接插入排序
- rman备份到磁带库注意事项
- 77、78、79
- 三款程序员必备神器,爆炸!
- Neo4j运行原理