zoukankan      html  css  js  c++  java
  • 7.Mybatis的一对多,多对一处理

    一.代码简化工具Lombok(只要了解,一般不用)

    • Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率。例如开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护,当属性多时会出现大量的getter/setter方法,这些显得很冗长也没有太多技术含量,一旦修改属性,就容易出现忘记修改对应方法的失误。

    • Lombok能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法。出现的神奇就是在源码中没有getter和setter方法,但是在编译生成的字节码文件中有getter和setter方法。这样就省去了手动重建这些代码的麻烦,使代码看起来更简洁些。

    1.使用步骤:

    (1)在IDEA中安装Lombok插件

    (2)在项目中导入lombok的jar包

    1 <dependencies>
    2     <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
    3     <dependency>
    4         <groupId>org.projectlombok</groupId>
    5         <artifactId>lombok</artifactId>
    6         <version>1.18.10</version>
    7     </dependency>
    8 </dependencies>

    (3)Lombok有哪些简化配置

     1 @Getter and @Setter
     2 @FieldNameConstants
     3 @ToString
     4 @EqualsAndHashCode
     5 @AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
     6 @Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
     7 @Data
     8 @Builder
     9 @SuperBuilder
    10 @Singular
    11 @Delegate
    12 @Value
    13 @Accessors
    14 @Wither
    15 @With
    16 @SneakyThrows
    17 @val
    18 @var
    19 experimental @var
    20 @UtilityClass
    21 Lombok config system
    22 Code inspections
    23 Refactoring actions (lombok and delombok)

    (4)使用在实体类上加注解即可

    只需要知道:

    •  @Data :添加了无参构造,getter,setter,hashcode,toString, equals等方法
    •  @AllArgsConstructor :有参构造
    •  @Getter and @Setter 
    •  @ToString 
    •  @EqualsAndHashCode 
     1 import lombok.Data;
     2 
     3 //实体类
     4 @Data
     5 public class User {
     6     private int id;  //id
     7     private String name;   //姓名
     8     private String password;   //密码
     9 
    10 
    11 }

    (5)lombok优缺点

    • 优点:

      1. 能通过注解的形式自动生成构造器、getter/setter、equals、hashcode、toString等方法,提高了一定的开发效率

      2. 让代码变得简洁,不用过多的去关注相应的方法

      3. 属性做修改时,也简化了维护为这些属性所生成的getter/setter方法等

    • 缺点:

      1. 不支持多种参数构造器的重载

      2. 虽然省去了手动创建getter/setter方法的麻烦,但大大降低了源代码的可读性和完整性,降低了阅读源代码的舒适度

    (6)建议不要去使用lombok只要了解即可

    二.多对一处理

    • 多个学生对应一个老师

    • 如果对于学生这边,就是一个多对一的现象,即从学生这边关联一个老师!

    1.复杂查询环境搭建

    (1)新建teacher和student表:

     1 CREATE TABLE `teacher` (
     2   `id` INT(10) NOT NULL,
     3   `name` VARCHAR(30) DEFAULT NULL,
     4   PRIMARY KEY (`id`)
     5 ) ENGINE=INNODB DEFAULT CHARSET=utf8;
     6 
     7 INSERT INTO teacher(`id`, `name`) VALUES (1, '秦老师'); 
     8 
     9 CREATE TABLE `student` (
    10   `id` INT(10) NOT NULL,
    11   `name` VARCHAR(30) DEFAULT NULL,
    12   `tid` INT(10) DEFAULT NULL,
    13   PRIMARY KEY (`id`),
    14   KEY `fktid` (`tid`),
    15   CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
    16 ) ENGINE=INNODB DEFAULT CHARSET=utf8;
    17 
    18 
    19 INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', '小明', '1'); 
    20 INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2', '小红', '1'); 
    21 INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3', '小张', '1'); 
    22 INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4', '小李', '1'); 
    23 INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5', '小王', '1'); 

    (2)新建子项目mybatis-05

    1. 导入Lombok

    2. 创建Teacher和Student两个实体类

    3. 建立Mapper接口

    4. 建立Mapper.xml文件

    5. 在核心配置文件中绑定注册我们的Mapper接口或Mapper.xml文件!

    6. 测试执行是否成功!

    Student.java:

     1 import lombok.Data;
     2 
     3 @Data
     4 public class Student {
     5 
     6     private int id;
     7     private String name;
     8 
     9     //学生需要关联一个老师
    10     private Teacher teacher;
    11 }

    Teacher.java:

    1 import lombok.Data;
    2 
    3 @Data
    4 public class Teacher {
    5 
    6     private int id;
    7     private String name;
    8 }

    2.查询所有学生信息以及对应的老师信息

    (1)SQL语句:

    1 select s.id as '学生id',s.name as '学生姓名',t.id as '老师id',t.name as '老师姓名' from student s ,teacher t where s.tid = t.id;

    (2)mybatis中的SQL语句:

    • 子查询

    • 联表查询(推荐)

    (2.1)子查询方式

    StudentMapper.java接口:

    1 List<Student> getStudent();

    StudentMapper.xml:

     1 <!--需要查询所有学生信息以及对应的老师信息-->
     2 <resultMap id="StudentTeacher" type="Student">
     3     <result property="id" column="id"></result>
     4     <result property="name" column="name"></result>
     5 
     6     <!--复杂的属性,我们需要单独处理, 对象使用association,集合使用collection-->
     7     <!--property属性名 javaType属性类型 column表中的列名-->
     8     <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"></association>
     9 </resultMap>
    10 
    11 <select id="getStudent" resultMap="StudentTeacher">
    12     select * from mybatis.student;
    13 </select>
    14 
    15 <select id="getTeacher" parameterType="_int" resultType="Teacher">
    16     select * from mybatis.teacher where id=#{teacherId};
    17 </select>

    测试代码:

     1 @Test
     2 public void getStudentTest() {
     3     SqlSession session = MybatisUtils.getSession();
     4 
     5     StudentMapper mapper = session.getMapper(StudentMapper.class);
     6 
     7     List<Student> studentList = mapper.getStudent();
     8 
     9     for (Student student : studentList) {
    10         System.out.println(student);
    11     }
    12 
    13     session.close();
    14 }

    (2.2)联表查询方式:(推荐使用,简单易懂)

    StudentMapper.java接口:

    1 List<Student> getStudent2();

    StudentMapper.xml:

     1 <!--方式二:连表查询-->
     2 <select id="getStudent2" resultMap="StudentTeacher2">
     3     select s.id as sid,s.name as sname,t.id as tid,t.name as tname
     4     from student s ,teacher t
     5     where s.tid = t.id;
     6 </select>
     7 
     8 <resultMap id="StudentTeacher2" type="Student">
     9     <result property="id" column="sid"></result>
    10     <result property="name" column="sname"></result>
    11     <association property="teacher" javaType="Teacher">
    12         <result property="id" column="tid"></result>
    13         <result property="name" column="tname"></result>
    14     </association>
    15 </resultMap>

    测试代码:

     1 @Test
     2 public void getStudent2Test() {
     3     SqlSession session = MybatisUtils.getSession();
     4 
     5     StudentMapper mapper = session.getMapper(StudentMapper.class);
     6 
     7     List<Student> studentList = mapper.getStudent2();
     8 
     9     for (Student student : studentList) {
    10         System.out.println(student);
    11     }
    12 
    13     session.close();
    14 }

    三.一对多处理

    一个老师对多个学生

    1.复杂查询环境搭建

    (1)新建子项目mybatis-06

    1. 导入Lombok

    2. 创建Teacher和Student两个实体类

    3. 建立Mapper接口

    4. 建立Mapper.xml文件

    5. 在核心配置文件中绑定注册我们的Mapper接口或Mapper.xml文件!

    6. 测试执行是否成功!

    Student.java:

    1 import lombok.Data;
    2 
    3 @Data
    4 public class Student {
    5 
    6     private int id;
    7     private String name;
    8     private int tid;
    9 }

    Teacher.java:

     1 import lombok.Data;
     2 
     3 import java.util.List;
     4 
     5 @Data
     6 public class Teacher {
     7 
     8     private int id;
     9     private String name;
    10 
    11     //一个老师拥有多个学生
    12     private List<Student> students;
    13 }

    SQL语句:

    1 select t.id as tid, t.name as tname,s.id as sid, s.name as sname
    2 from student s,teacher t
    3 where s.tid = t.id;

    2.根据ID查询老师信息以及老师对应的学生信息

    (1)子查询:

    TeacherMapper.java接口:

    1 Teacher getTeacher2(@Param("tid") int id);

    TeacherMapper.xml:

    • 由于分开来写所以 javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id" 
      • javaType用于绑定是一个List
      • ofType用于绑定List中的类型
      • select 用于拿到子查询数据为一个List<Student> 
      • column中的值为Teacher的id对应子查询为Student的tid
     1 <select id="getTeacher2" resultMap="TeacherStudent2">
     2     select id , name from mybatis.teacher where id = #{tid}
     3 </select>
     4 
     5 <resultMap id="TeacherStudent2" type="Teacher">
     6     <result property="id" column="id"></result>
     7     <result property="name" column="name"></result>
     8     <collection property="students" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id"></collection>
     9 </resultMap>
    10 
    11 <select id="getStudentByTeacherId" resultType="Student">
    12     select * from mybatis.student where tid = #{tid};
    13 </select>

    测试代码:

     1 @Test
     2 public void getTeacherTest2() {
     3     SqlSession session = MybatisUtils.getSession();
     4 
     5     TeacherMapper mapper = session.getMapper(TeacherMapper.class);
     6 
     7     Teacher teacher = mapper.getTeacher2(1);
     8 
     9     System.out.println(teacher);
    10 
    11     session.close();
    12 }

    可以看出只有一条数据,select 用于拿到子查询数据为一个List<Student> :

    (2)联表查询:(推荐使用,简单易懂)

    TeacherMapper.java接口:

    1 //根据老师id获得老师信息并获得对应的多个学生信息
    2 Teacher getTeacher(@Param("tid") int id);

    TeacherMapper.xml:

    每次只获得一条数据所以 property="students" ofType="Student" ,每次拼接一条数据最后一次性返回

     1 <!--联表查询方式-->
     2     <select id="getTeacher" resultMap="TeacherStudent">
     3         select t.id as tid, t.name as tname,s.id as sid, s.name as sname
     4         from student s,teacher t
     5         where s.tid = t.id and t.id = #{tid};
     6     </select>
     7 
     8     <resultMap id="TeacherStudent" type="Teacher">
     9         <result property="id" column="tid"></result>
    10         <result property="name" column="tname"></result>
    11         <!--集合的话,使用collection!
    12                 JavaType和ofType都是用来指定对象类型的
    13                 JavaType是用来指定pojo中属性的类型
    14                 ofType指定的是映射到list集合属性中pojo的类型。-->
    15         <collection property="students" ofType="Student">
    16             <result property="id" column="sid"></result>
    17             <result property="name" column="sname"></result>
    18             <result property="tid" column="tid"></result>
    19         </collection>
    20     </resultMap>

    测试代码:

     1 @Test
     2 public void getTeacherTest() {
     3     SqlSession session = MybatisUtils.getSession();
     4 
     5     TeacherMapper mapper = session.getMapper(TeacherMapper.class);
     6 
     7     Teacher teacher = mapper.getTeacher(1);
     8 
     9     System.out.println(teacher);
    10 
    11     session.close();
    12 }

    可以看出拿到了五条数据

    四.小结

    1. 关联-association 【一对一和多对一】

    2. 集合-collection【一对多】

    3. JavaType和ofType都是用来指定对象类型的

      • JavaType是用来指定pojo中属性的类型

      • ofType指定的是映射到list集合属性中pojo的类型。

    注意说明:

    1. 保证SQL的可读性,尽量通俗易懂

    2. 根据实际要求,尽量编写性能更高的SQL语句

    3. 注意属性名和字段不一致的问题

    4. 注意一对多和多对一 中:字段和属性对应的问题

    5. 尽量使用Log4j,通过日志来查看自己的错误

  • 相关阅读:
    YourSQLDba低版本的一个Bug的浅析
    VMware虚拟机(Linux)如何找出系统中磁盘设备对应的硬盘
    SSH登录报pam_unix(sshd:auth): authentication failure的案例
    Linux shell中如何给文本加上行号呢
    Linux查看系统块大小
    存储基础知识:扇区与块/簇
    SQL Server中GETDATE转换时间时注意事项
    SQL Server 2008 R2执行存储过程sp_MailItemResultSets引起大量PREEMPTIVE_OS_WAITFORSINGLEOBJEC等待
    Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool
    SQL Server 2014下Database Mail Engine进程消耗大量CPU资源
  • 原文地址:https://www.cnblogs.com/zhihaospace/p/12301067.html
Copyright © 2011-2022 走看看