多对一(association标签)

  • 老师和学生的例子
  • 以学生为出发点,就是一个多对一的例子,即多个学生关联一个老师!

首先搭建数据库

CREATE TABLE `teacher` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO teacher(`id`, `name`) VALUES (1, '羊羊');

CREATE TABLE `student` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
`tid` INT(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fktid` (`tid`),
CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8


INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', '小羊', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2', '小锅', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3', '小虎', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4', '小狗', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5', '小明', '1');

利用lombok简化代码

1、Lombok

  • lombok是一个可以帮助我们简化java代码编写的工具类,尤其是简化javabean的编写,即通过采用注解的方式,消除代码中的构造方法,getter/setter等代码,使我们写的类更加简洁,当然,这带来的副作用就是不易阅读…

2、引入Lombok的Maven依赖

<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
 <groupId>org.projectlombok</groupId>
 <artifactId>lombok</artifactId>
 <version>1.16.10</version>
</dependency>

3、在代码中增加注解

@Data //GET,SET,ToString,有参,无参构造
public class Teacher {
   private int id;
   private String name;
}
@Data
public class Student {
   private int id;
   private String name;
   //多个学生可以是同一个老师,即多对一
   private Teacher teacher;
}

4、编写实体类对应的Mapper接口

public interface StudentMapper {
}
public interface TeacherMapper {
}

5、编写Mapper接口对应的 mapper.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.yang.mapper.StudentMapper">

</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.yang.mapper.TeacherMapper">

</mapper>

复杂查询,获取所有学生及对应老师的信息

  • 两种方法实现
  • 按查询嵌套处理(像SQL中的子查询)
  • 按结果嵌套处理(像SQL中的联表查询)

1、给StudentMapper接口增加方法

public List<Student> getStudents();   //查询嵌套处理
public List<Student> getStudents2();  //结果嵌套处理

2、编写对应的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.yang.mapper.StudentMapper">

   <!--
   查询嵌套处理
   -->
   <select id="getStudents" resultMap="StudentTeacher">
    select * from student
   </select>
   <resultMap id="StudentTeacher" type="Student">
       <!--association关联属性 property属性名 javaType属性类型 column在多的一方的表中的列名-->
       <association property="teacher"  column="tid"javaType="Teacher" select="getTeacher"/>
   </resultMap>
   <!--
   这里传递过来的id,只有一个属性的时候,下面可以写任何值
   association中column多参数配置:
       column="{key=value,key=value}"
       其实就是键值对的形式,key是传给下个sql的取值名称,value是片段一中sql查询的字段名。
   -->
   <select id="getTeacher" resultType="teacher">
      select * from teacher where id = #{id}
   </select>
   
	<!--
	按查询结果嵌套处理
	-->
	<select id="getStudents2" resultMap="StudentTeacher2" >
	  select s.id sid, s.name sname , t.name tname
	  from student s,teacher t
	  where s.tid = t.id
	</select>
	
	<resultMap id="StudentTeacher2" type="Student">
	   <id property="id" column="sid"/>
	   <result property="name" column="sname"/>
	   <!--关联对象property 关联对象在Student实体类中的属性-->
	   <association property="teacher" javaType="Teacher">
	       <result property="name" column="tname"/>
	   </association>
	</resultMap>

</mapper>

3、记得注册Mapper

4、注意点说明:

<resultMap id="StudentTeacher" type="Student">
   <!--association关联属性 property属性名 javaType属性类型 column在多的一方的表中的列名-->
   <association property="teacher"  column="{id=tid,name=tid}"javaType="Teacher" select="getTeacher"/>
</resultMap>
<!--
这里传递过来的id,只有一个属性的时候,下面可以写任何值
association中column多参数配置:
   column="{key=value,key=value}"
   其实就是键值对的形式,key是传给下个sql的取值名称,value是片段一中sql查询的字段名。
-->
<select id="getTeacher" resultType="teacher">
  select * from teacher where id = #{id} and name = #{name}
</select>

5、测试

@Test
public void testGetStudents(){
   SqlSession session = MybatisUtils.getSession();
   StudentMapper mapper =session.getMapper(StudentMapper.class);

   List<Student> students = mapper.getStudents();

   for (Student student : students){
       System.out.println(
               "学生名:"+ student.getName()
                       +"\t老师:"+student.getTeacher().getName());
  }
}

@Test
public void testGetStudents2(){
   SqlSession session = MybatisUtils.getSession();
   StudentMapper mapper =session.getMapper(StudentMapper.class);

   List<Student> students = mapper.getStudents2();

   for (Student student : students){
       System.out.println(
               "学生名:"+ student.getName()
                       +"\t老师:"+student.getTeacher().getName());
  }
}

一对多的处理

  • 老师和学生的例子
  • 以老师为出发点,就是一个多对一的例子,即一个老师关联多个学生!

环境相同,使用两种方法分别实现
按结果嵌套处理

1、TeacherMapper接口编写方法

//获取指定老师,及老师下的所有学生
public Teacher getTeacher(int id);

2、编写接口对应的Mapper配置文件

<mapper namespace="com.yang.mapper.TeacherMapper">

   <!--
   思路:
       1. 从学生表和老师表中查出学生id,学生姓名,老师姓名
       2. 对查询出来的操作做结果集映射
           1. 集合的话,使用collection!
               JavaType和ofType都是用来指定对象类型的
               JavaType是用来指定pojo中属性的类型
               ofType指定的是映射到list集合属性中pojo的类型。
   -->
   <select id="getTeacher" resultMap="TeacherStudent">
      select s.id sid, s.name sname , t.name tname, t.id tid
      from student s,teacher t
      where s.tid = t.id and t.id=#{id}
   </select>

   <resultMap id="TeacherStudent" type="Teacher">
       <result  property="name" column="tname"/>
       <collection property="students" ofType="Student">
           <result property="id" column="sid" />
           <result property="name" column="sname" />
           <result property="tid" column="tid" />
       </collection>
   </resultMap>
</mapper>

3、将Mapper文件注册到MyBatis-config文件中

<mappers>
   <mapper resource="mapper/TeacherMapper.xml"/>
</mappers>

4、测试

@Test
public void testGetTeacher(){
   SqlSession session = MybatisUtils.getSession();
   TeacherMapper mapper =session.getMapper(TeacherMapper.class);
   Teacher teacher = mapper.getTeacher(1);
   System.out.println(teacher.getName());
   System.out.println(teacher.getStudents());
}

按查询嵌套处理

1、TeacherMapper接口编写方法

public Teacher getTeacher2(int id);

2、编写接口对应的Mapper配置文件

<select id="getTeacher2" resultMap="TeacherStudent2">
select * from teacher where id = #{id}
</select>
<resultMap id="TeacherStudent2" type="Teacher">
   <!--column是一对多的外键 , 写的是一的主键的列名-->
   <collection property="students" javaType="ArrayList"ofType="Student" column="id" select="getStudentByTeacherId"/>
</resultMap>
<select id="getStudentByTeacherId" resultType="Student">
  select * from student where tid = #{id}
</select>

3、将Mapper文件注册到MyBatis-config文件中

4、测试

@Test
public void testGetTeacher2(){
   SqlSession session = MybatisUtils.getSession();
   TeacherMapper mapper =session.getMapper(TeacherMapper.class);
   Teacher teacher = mapper.getTeacher2(1);
   System.out.println(teacher.getName());
   System.out.println(teacher.getStudents());
}