<1>通过一个表的一个字段去查询另一个表的多条记录
一对多的级联查询表示一个表中一条记录对应另一个表中多条记录,例如一种型号的手机有多个人使用。
手机对应的表为PHONE:
人对应的表PERSON:
建立PHONE表对应的实体类,一个品牌的手机有多个人在使用
package com.lzj.mybaits.bean;
public class Phone {
private String brand;
private float price;
private List<Person> persons;
/*省略get和set方法*/
}
建立PERSON表对应的实体类:
package com.lzj.mybaits.bean;
public class Person {
private int id;
private String name;
}
下面介绍两种一对多的级联查询方式:集合封装查询和分布查询。
方式一:集合封装查询
通过phone_brand字段查询出所有使用指定型号品牌的人
1、建立Dao接口
package com.lzj.mybatis.dao;
import com.lzj.mybaits.bean.Phone;
public interface PhoneDao {
public Phone getPhone(String brand);
}
2、建立sql的mapper文件
<mapper namespace="com.lzj.mybatis.dao.PhoneDao">
<!--嵌套结果集的方式,使用collection标签定义关联的集合类型的属性封装规则 -->
<resultMap type="com.lzj.mybaits.bean.Phone" id="MyPhone">
<id column="brand" property="brand"/>
<result column="price" property="price"/>
<!--
collection定义关联集合类型的属性的封装规则
ofType:指定集合里面元素的类型
-->
<collection property="persons" ofType="com.lzj.mybaits.bean.Person">
<id column="id" property="id"/>
<result column="name" property="name"/>
</collection>
</resultMap>
<select id="getPhone" resultMap="MyPhone">
SELECT ph.phone_brand brand,
ph.phone_price price, ps.id, ps.name FROM PHONE ph LEFT JOIN PERSON ps
ON ph.phone_brand=ps.phone_brand
WHERE ph.phone_brand=#{brand}
</select>
</mapper>
3、建立查询方法
public static void testGepPhone(){
String resource = "conf.xml";
InputStream in = MybaitsTest.class.getClassLoader().getResourceAsStream(resource);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = factory.openSession();
PhoneDao phoneDao = session.getMapper(PhoneDao.class);
Phone phone = phoneDao.getPhone("iphone");
System.out.println("phone :" + phone);
}
执行测试方法,输出结果如下:
phone :Phone [brand=iphone, price=5000.0, persons=[Person [id=1, name=lzj], Person [id=4, name=Bob]]]
方式二:分布查询
PHONE表与PERSON表时一对多的关系,PHONE表中一条数据对应PERSON表中的多条数据。因此也可以先查PHONE表,然后用查到的记录再去查PERSON表,实现分布查询。
先查PHONE表,首先创建PHONE表对应的DAO接口:
package com.lzj.mybatis.dao;
import com.lzj.mybaits.bean.Phone;
public interface PhoneDao {
public Phone getPhoneByStep(String brand);
}
创建PHONE表对应的mapper文件
<mapper namespace="com.lzj.mybatis.dao.PhoneDao">
<resultMap type="com.lzj.mybaits.bean.Phone" id="MyPhoneStep">
<id column="phone_brand" property="brand"/>
<result column="phone_price" property="price"/>
/*用collection 定义一条PHONE数据对应多条PERSON数据;
返回类型为Phone,property="persons"指明phone中persons属性对应多条数据;
select指定调用接口中的方法,返回多条数据放在persons属性中*/
<collection property="persons" select="com.lzj.mybatis.dao.PersonDao.getPersonByPhone"
column="phone_brand">
</collection>
</resultMap>
/*查询PHONE表*/
<select id="getPhoneByStep" resultMap="MyPhoneStep">
select * from PHONE where phone_brand=#{brand}
</select>
</mapper>
由于上面调用了PERSON对应接口中查询方法,下面定义PERSON对应的DAO:
package com.lzj.mybatis.dao;
import com.lzj.mybaits.bean.Person;
public interface PersonDao {
/*上面PHONE表对应的mapper文件用slelect指明了要调用该方法*/
public Person getPersonByPhone(String brand);
}
PERSON表对应的mapper文件为:
<mapper namespace="com.lzj.mybatis.dao.PersonDao">
<select id="getPersonByPhone" resultType="com.lzj.mybaits.bean.Person">
select * from PERSON where phone_brand=#{brand}
</select>
</mapper>
创建测试方法:
public static void testGepPhoneByStep(){
String resource = "conf.xml";
InputStream in = MybaitsTest.class.getClassLoader().getResourceAsStream(resource);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = factory.openSession();
PhoneDao phoneDao = session.getMapper(PhoneDao.class);
Phone phone = phoneDao.getPhoneByStep("iphone");
System.out.println("phone :" + phone);
}
执行测试方法,输出结果:
phone :Phone [brand=iphone, price=5000.0, persons=[Person [id=1, name=lzj], Person [id=4, name=Bob]]]
<2>通过一个表的多个字段去查询另一个表的多条记录
上面的示例都是查询PHONE表后,然后用查询的phone_brand字段数据去查询PERSON表的记录。如果查询PHONE表后,需要用多个字段去查询PERSON表呢?此时就需要在collection标签中的column指定具体对应的列名,如下形式:
column="{key1=column1,key2=column2}"
查询一个表后,用查询到的记录中的一个字段对应的数据去查其它表也可以用这种形式,本例中通过phone_brand字段去查PERSON表可改成如下形式:
只需要把PHONE的mapper文件中的<resultMap >
中的内容改成如下形式(只改了column中内容)
<resultMap type="com.lzj.mybaits.bean.Phone" id="MyPhoneStep">
<id column="phone_brand" property="brand"/>
<result column="phone_price" property="price"/>
/*column="{brand=phone_brand}"指定把phone_brand列传给brand键*/
<collection property="persons" select="com.lzj.mybatis.dao.PersonDao.getPersonByPhone"
column="{brand=phone_brand}">
</collection>
</resultMap>
注意:column="{brand=phone_brand}"
中的brand键不是随意些的,要与select=”com.lzj.mybatis.dao.PersonDao.getPersonByPhone”中获取的键值名相同。
/*#{brand}与column="{brand=phone_brand}中的键值保持一致*/
<select id="getPersonByPhone" resultType="com.lzj.mybaits.bean.Person">
select * from PERSON where phone_brand=#{brand}
</select>
假设要通过查询PHONE表的phone_brand和name再去查PERSON时,PHONE表对应的mapper文件中的<resultMap >
中的<collection
> 标签中的column可以写成如下形式:
column="{brand=phone_brand,userName=name}"
在PERSON的select语句中获取两个键对应的值就可以了
<select id="getPersonByPhone" resultType="com.lzj.mybaits.bean.Person">
select * from PERSON where phone_brand=#{brand} AND name=#{username}
</select>