Mybatis三:注解开发、Mybatis的执行流程、多对一、一对多

一、使用注解开发

1、面向接口编程:根本原因在于“解耦”,可拓展,提高复用。

  <!--绑定接口-->
    <mappers>
        <mapper class="com.hr.dao.UserMapper"/>
    </mappers>
 @Select("select * from user")
    List<User> findAll();
SqlSession sqlSession = MybatisUtils.getSqlSession();  
       //底层用反射机制
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> all = mapper.findAll();
        for (User user : all) {
            System.out.println(user);
        }

本质:通过反射机制实现;
底层:动态代理;

二、Mybatis的执行流程

1、Resources获取加载全局配置文件;

//1、获取sqlSessionFactory对象
    static {
        try {
            String resouce = "mybatis-code.xml";
            InputStream inputStream = Resources.getResourceAsStream(resouce);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2、实例化SqlSessionFactoryBuilder;

3、通过XMLConfigBuilder来解析配置文件流;

4、所有的配置信息再放到Configuration 对象里;(new SqlSessionFactoryBuilder().build(inputStream)在build中

5、SqlSessionFactory实例化(已经携带了以上对象)

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
        SqlSessionFactory var5;
        try {
            XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
            var5 = this.build(parser.parse());
        } catch (Exception var14) {
            throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
        } finally {
            ErrorContext.instance().reset();

            try {
                inputStream.close();
            } catch (IOException var13) {
            }

        }

        return var5;
    }

    public SqlSessionFactory build(Configuration config) {
        return new DefaultSqlSessionFactory(config);
    }

6、trasactional事物管理;

7、创建执行器executor;(它会执行mapper,通过反射加载出来类的信息,把SqlSession的执行器套用进去,执行sql)

8、创建SqlSession;(为了实现CRUD,事物出现问题,会回滚到事物管理,执行成功再提交事物,最后关闭SqlSession,未执行成功又会回滚到事物管理)

三、用注解实现CRUD

 public static SqlSession getSqlSession(){
        //设置为真,不用去手动SqlSession.commit();
        return sqlSessionFactory.openSession(true);
    }
    @Select("select * from user")
    List<User> findAll();
    //查单个,基本数据类型和String需要加上,多个参数一定要加@Param注解,引用对象不用加
    @Select("select * from user where id = #{id}")
    User findOne(@Param("id") int id);
   
    @Insert("insert into user (name,pwd) values (#{name},#{password})")
    int add(User user);

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

关于@Param注解

  • 基本类型的参数或者String要加上
  • 引用类型不需要加;
  • 如果只有一个基本类型,可以忽略,但是最好加上;
  • 在sql中引用的就是@Param()中设定的属性名

“# ”和 “$”的区别:

  • 使用#{} 相当于在原来的sql语句字段上加了双引号" ",可以很大程度上防止sql注入;
  • 使用${}引入数据会直接显示在生成的sql语句中,无法防止sql注入;

四、多对一处理(相当于站在学生的角度,主要查学生的信息)

1、多个学生,对应一个老师;

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

2、多对一,通常在多的那一方关联,private一个关联的对象
在这里插入图片描述

3、按照查询嵌套处理(子查询)
在这里插入图片描述

<!--在查询完所有学生,就已经将tid作为结果传给 #{id}查询老师了-->
     <select id="findAllStudentAndTeacher" resultMap="studentAndteacher">
         select * from student
     </select>
     <resultMap id="studentAndteacher" type="Student">
         <id property="id" column="id"/>
         <result property="name" column="name"/>
         <association property="teacher" column="tid" javaType="Teacher" select="findAllTeacher"/>
     </resultMap>
     <!--在这里把"#{id}"换成"#{tid}"也是一样的结果-->
     <select id="findAllTeacher" resultType="Teacher">
         select * from teacher where id = #{id}
     </select>

4、按照结果嵌套处理:通过结果做映射

<-- 在这里 column对应的是sql里面的别名,一一对应--/>
<select id="findAllStudentAndTeacher2" resultMap="studentAndteacher2">
       select s.id sid,s.name sname,t.name tname from student s,teacher t where t.id=s.tid
    </select>

    <resultMap id="studentAndteacher2" type="Student">
        <id property="id" column="sid"/>
        <result property="name" column="sname"/>
        <association property="teacher"  javaType="Teacher">
            <result property="name" column="tname"/>
        </association>
    </resultMap>

五、一对多处理(在案例中站在老师的角度,主要查的是有关老师的信息)

1、按照结果嵌套查询:

//获取指定老师下的所有学生和老师的信息
    List<Teacher> findAllTeacherAndStudent(@Param("tid") int id);

    <select id="findAllTeacherAndStudent" resultMap="AllTeacherAndStudent">
       select t.id tid,t.name tname,s.id sid,s.name sname,s.tid stid from teacher t,student s where t.id=s.tid
    </select>

    <resultMap id="AllTeacherAndStudent" type="Teacher">
        <id property="id" column="tid"/>
        <result property="name" column="tname"/>
        <!--javatype:指定属性的类型,ofType相当于javaType,但是ofTyPE是修饰集合的,集合中的泛型信息用oftype-->
        <collection property="studentList" ofType="Student">
            <id property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="tid" column="stid"/>
        </collection>
    </resultMap>

2、按照查询嵌套查询:

 <select id="findAllTeacherAndStudent2" resultMap="AllTeacherAndStudent2">
        select * from teacher where id = #{tid}
    </select>

    <resultMap id="AllTeacherAndStudent2" type="Teacher">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <!--老师里面的id-->
        <collection property="studentList" column="id" javaType="ArrayList" ofType="Student" select="findAllStudentByStudentId"/>
    </resultMap>

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

3、小结:

  • 关联:association【多对一】

  • 集合:collection【一对多】

  • javaType:指定实体类中属性的类型在这里插入图片描述

  • ofType:用来指定映射到list或者集中的pojo类型、泛型中的约束类型;在这里插入图片描述

在这里插入图片描述
面试高频:

  • Mysql引擎、
  • InnoDB底层原理、
  • 索引、
  • 索引优化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值