一、多对一
多对一,顾名思义就在一张数据表里有多个记录,他们有个字段对应对是另一个数据的数据,比如多个学生对应一个老师,直接使用select是不能够把另一个数据表的数据查询出来,这时就要用到多对一的查询方法。
在Mybatis里面,结果映射(resultMap)里的一个子元素association就可以实现多对一
association
– 一个复杂类型的关联;许多结果将包装成这种类型 嵌套结果映射 – 关联本身可以是一个 resultMap元素,或者从别处引用一个
相关属性:
property
:映射到列结果的字段或属性。如果用来匹配的 JavaBean 存在给定名字的属性,那么它将会被使用。否则 MyBatis 将会寻找给定名称的字段。 无论是哪一种情形,你都可以使用通常的点式分隔形式进行复杂属性导航。 比如,你可以这样映射一些简单的东西:“username”,或者映射到一些复杂的东西上:“address.street.number”。
javaType
:一个 Java 类的完全限定名,或一个类型别名(关于内置的类型别名,可以参考上面的表格)。 如果你映射到一个 JavaBean,MyBatis 通常可以推断类型。然而,如果你映射到的是 HashMap,那么你应该明确地指定 javaType 来保证行为与期望的相一致。
column
:数据库中的列名,或者是列的别名。一般情况下,这和传递给 resultSet.getString(columnName) 方法的参数一样。 注意:在使用复合主键的时候,你可以使用 column=”{prop1=col1,prop2=col2}” 这样的语法来指定多个传递给嵌套 Select 查询语句的列名。这会使得 prop1 和 prop2 作为参数对象,被设置为对应嵌套 Select 语句的参数。
select
:用于加载复杂类型属性的映射语句的 ID,它会从 column 属性指定的列中检索数据,作为参数传递给目标 select 语句。 具体请参考下面的例子。注意:在使用复合主键的时候,你可以使用 column=”{prop1=col1,prop2=col2}” 这样的语法来指定多个传递给嵌套 Select 查询语句的列名。这会使得 prop1 和 prop2 作为参数对象,被设置为对应嵌套 Select 语句的参数。
1.建立数据表
这里我就建立了一个peo和teacher两个数据表,peo对应的是学生,teacher对应了教师,其中peo中的tid字段对应的就是teacher的id字段,查询时主要就是用到tid来查询teacher数据表的数据
2.编写实体类
在工程里创建一个Peo类和Teacher类,分别对应peo和teacher数据表,注意要在Peo类里创建一个Teacher类来存放查询到的teacher信息
3.编写XML映射文件
我这里是分开了两个xml文件,分别对应的是peo和teacher
peo.mapper.xml
<select id="getPeoTeacher" resultMap="PeoTeacher">
select * from peo
</select>
<resultMap id="PeoTeacher" type="Peo">
<association property="teacher" column="tid" javaType="Teacher" select="entity.TeacherMapper.getTeacher">
</association>
</resultMap>
teacher.mapper.xml
<select id="getTeacher" resultType="Teacher" >
select * from teacher where id = #{id}
</select>
在peo.mapper.xml里的<association>
里的property
是映射到列结果的字段或属性,就是你在实体类里的变量名,column
就是要根据什么字段来查询,这里的tid就是peo里的tid,对应着teacher的id,javaType
就是返回的类型,这里为teacher,select
里就是要执行的查询teacher数据的方法,我这里是存放在了另一个xml文件里。
用resultMap
的<association>
来实现多对一,相当于执行了两次select查询,第一次就是查询peo,然后使用查询到的tid字段来查询teacher。
dao层的编写:
public List<Peo> getPeoTeacher() throws IOException {
SqlSession session = MybatisUtil.getSession();
List<Peo> list = session.selectList("entity.PeoMapper.getPeoTeacher");
session.close();
return list;
}
4.测试
public class Test {
public static void main(String[] args) throws IOException {
PeoDao peoDao = new PeoDao();
List<Peo> l = peoDao.getPeoTeacher();
for (Peo p : l){
System.out.println(p+" "+p.getTeacher());
}
}
}
我这里就将每一个peo和对应的teacher给查询出来了
二、一对多
当知道如何实现多对一之后,一对多就很容易写了
多对一是根据peo的tid来查询teacher的id,一对多就是反过来的,根据teacher的id来查询peo的tid
这里是使用resultMap
的collection
来实现
1.编写实体类
这里就只用在Teacher类里多添加一个子元素peo来存放查询到到peo数据,因为peo数据会不止一个,所以要用list来存放
private List<Peo> peo;
2.编写XML映射文件
teacher.mapper.xml
<select id="getTeacherPeo" resultMap="TeacherPeo">
select * from teacher where id = #{id}
</select>
<resultMap id="TeacherPeo" type="Teacher" >
<collection property="peo" javaType="ArrayList" ofType="Peo" column="id" select="entity.PeoMapper.getByTid">
</collection>
</resultMap>
peo.mapper.xml
<select id="getByTid" resultType="Peo">
select * from peo where tid=#{id}
</select>
注意这里的javaType="ArrayList" ofType="Peo"
dao层:
public Teacher getTeacher(int id) throws IOException {
Teacher teacher = new Teacher();
SqlSession session = MybatisUtil.getSession();
teacher = session.selectOne("entity.TeacherMapper.getTeacherPeo",id);
session.close();
return teacher;
}
3.测试
public class Test {
public static void main(String[] args) throws IOException {
TeacherDao teacherDao = new TeacherDao();
Teacher tea = teacherDao.getTeacher(1);
System.out.println(tea);
for (Peo p : tea.getPeo()) {
System.out.println(p);
}
}
}
三、动态sql
平时编写sql语句,一般都是写死的,比如要写一个根据性别来查询,我们要将全部男性查询出来
select * from peo where sex=#{sex}
这时我们就必须传入一个参数给到sex,若没有传入则不会查询出任何数据
动态sql就可以解决参数为空时查询不到数据到问题,当你传入参数时就会根据参数来参数,若不传入则是查询全部数据
在mybatis里if+where语句就可以很方便的实现动态sql
<select id="selectAll" resultType="Peo" parameterType="Peo">
select * from peo
<where>
<if test="name!=null">
name = #{name}
</if>
<if test="sex!=null">
and sex = #{sex}
</if>
</where>
</select>
当有多个条件时,若第一个条件不成立,<where>
会自动将后面的满足条件的sql语句中的and去掉
还有使用set+if就可以实现update的动态sql
<update id="updatePeo" parameterType="Peo">
update peo p
<set>
<if test="name != null and name != ''">
p.name = #{name},
</if>
<if test="sex != null and sex != ''">
p.sex = #{sex}
</if>
</set>
where id = #{id}
</update>
动态sql一般就是运用在搜索时的条件筛选