注解的CRUD;重点:多对一和一对多处理

8.3、CRUD(20-12-22)

我们可以在工具类创建的时候实现自动提交事务!

    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession(true);//自动提交事务
    }

编写接口,增加注解

public interface UserMapper {

    @Select("select * from user ")
    List<User> getUsers();

    //方法存在多个参数,所有的参数前面必须加上 @Param(" ") 注解
    @Select("select * from user where id = #{id}")
    User getUserByID(@Param("id") int id);

    @Insert("insert into user(id,name,pwd) values (#{id},#{name},#{pwd})")
    int addUser(User user);

    @Update("update user set name=#{name},pwd=#{pwd} where id = #{id}")
    int updateUser(User user);

    @Delete("delete from user where id= #{uid}")
    int deleteUser(@Param("uid") int id);
}

测试类

【注意:我们必须要将接口注册绑定到我们的核心配置文件中!】

关于@Param(" ") 注解

  • 基本类型的参数或者String类型,需要加上
  • 引用类型不需要加
  • 如果只有一个基本类型的话,可以忽略,但是建议大家都加上!
  • 我们在SQL中引用的就是我们这里的@Param( ) 中设定的属性名!

#{} ${}区别 安全性,防止SQL注入!

9、Lombok

Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java.
Never write another getter or equals method again, with one annotation your class has a fully featured builder, Automate your logging variables, and much more.
  • java library
  • plugs
  • build tools
  • with one annotation your class

使用步骤:

  1. 在IDEA中安装Lombok插件!

  2. 在项目中导入Lombok的jar包

    <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.12</version>
    </dependency>
    
  3. 在实体类上加注解即可!

@Data
@AllArgsConstructor
@NoArgsConstructor

Lombok 的一些注解

@Getter and @Setter
@FieldNameConstants
@ToString
@EqualsAndHashCode
@AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
@Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
@Data
@Builder
@SuperBuilder
@Singular
@Delegate
@Value
@Accessors
@Wither
@With
@SneakyThrows

说明:

@Data:无参构造,get、set、tostring、hashcode、equals
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
@ToString
@Getter and @Setter

10、多对一处理

  • 多个学生,对应一个老师
  • 对于学生这边而言,关联,多个学生,关联一个老师【多对一】
  • 对于老师而言,集合,一个老师,有很多学生【一对多】

SQL

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');

测试环境搭建

  1. 导入Lombok(可选)
  2. 新建实体类 Teacher,Student
  3. 建立Mapper接口
  4. 建立Mapper.XML文件
  5. 在核心配置中绑定我们的Mapper接口或者文件!【绑定方式很多】
  6. 测试查询是否能成功!

按照查询嵌套处理

  1. 给StudentMapper接口增加方法

    //获取所有学生及对应老师的信息
    public List<Student> getStudents();
    
  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.kuang.mapper.StudentMapper">
    
       <!--
       需求:获取所有学生及对应老师的信息
       思路:
           1. 获取所有学生的信息
           2. 根据获取的学生信息的老师ID->获取该老师的信息
           3. 思考问题,这样学生的结果集中应该包含老师,该如何处理呢,数据库中我们一般使用关联查询?
               1. 做一个结果集映射:StudentTeacher
               2. StudentTeacher结果集的类型为 Student
               3. 学生中老师的属性为teacher,对应数据库中为tid。
                  多个 [1,...)学生关联一个老师=> 一对一,一对多
               4. 查看官网找到:association – 一个复杂类型的关联;使用它来处理关联查询
       -->
       <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>
    
    </mapper>
    
  3. 编写完毕去Mybatis配置文件中,注册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());
  }
}

按照结果嵌套处理

除了上面这种方式,还有其他思路吗?

我们还可以按照结果进行嵌套处理;

  1. 接口方法编写

    public List<Student> getStudents2();
    
  2. 编写对应的mapper文件

    <!--
    按查询结果嵌套处理
    思路:
       1. 直接查询出结果,进行结果集的映射
    -->
    <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 集合:collection-->
       <association property="teacher" javaType="Teacher">
           <result property="name" column="tname"/>
       </association>
    </resultMap>
    
  3. 去mybatis-config文件中注入【此处应该处理过了】

  4. 测试

    @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());
      }
    }
    

回顾MySQL多对一查询方式:

  • 子查询(按照查询进行嵌套处理)
  • 联表查询(按照结果进行嵌套处理)

11、一对多处理

比如:一个老师拥有多个学生!

对于老师而言,就是一对多的关系!

环境搭建

  1. 环境搭建,和刚才一样

实体类

public class Student {
    private int id;
    private String name;
    private int tid;
}
public class Teacher {
    private int id;
    private String name;

    //一个老师拥有多个学生
    private List<Student> students;
}

按照结果嵌套处理

<!--按结果嵌套查询-->
    <select id="getTeacher" resultMap="TeacherStudent">
        select s.id sid,s.name sname,t.name tname,t.id tid
        from mybatis.student s,mybatis.teacher t
        where s.tid=t.id and t.id= #{tid}
    </select>
    <resultMap id="TeacherStudent" type="Teacher">
        <result property="id" column="tid"/>
        <result property="name" column="tname"/>
        <!--复杂的属性,我们需要单独处理 对象: association 集合:collection
        javaType="" 指定属性的类型!
        集合中的泛型信息,我们使用ofType获取
        -->
        <collection property="students" ofType="Student">
            <result property="id" column="sid" />
            <result property="name" column="sname" />
            <result property="tid" column="tid" />
        </collection>
    </resultMap>

按照查询嵌套处理

<!--按照查询嵌套-->
    <select id="getTeacher2" resultMap="TeacherStudent2">
        select * from mybatis.teacher where id=#{tid}
    </select>
    
    <resultMap id="TeacherStudent2" type="Teacher">
        <collection property="students" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id" />
    </resultMap>

    <select id="getStudentByTeacherId" resultType="Student">
        select * from mybatis.student where tid=#{tid}
    </select>

小结

  1. 关联-association 【多对一】
  2. 集合-collection 【一对多】
  3. javaType & ofType
    1. javaType 用来指定实体类中的属性的类型
    2. ofType 用来指定映射到List或者集合中的pojo类型,泛型中的约束类型!

注意点:

  • 保证SQL的可读性,尽量保证通俗易懂
  • 注意一对多多对一中,属性名和字段的问题!
  • 如果问题不好排查错误,可以使用日志,建议使用 Log4j

避免 慢SQL

面试高频

  • MySQL引擎
  • InnoDB底层原理
  • 索引
  • 索引优化!
posted @ 2020-12-22 21:35  None1014  阅读(116)  评论(0编辑  收藏  举报