为了账号安全,请及时绑定邮箱和手机立即绑定

通过自动回复机器人学Mybatis---加强版

难度中级
时长 2小时43分
学习人数
综合评分9.77
214人评价 查看评价
9.9 内容实用
9.7 简洁易懂
9.7 逻辑清晰
  • 没实现类的接口,为什么能调用定义的方法
    查看全部
  • Sprinf 1.Db层会消失, 2.Dao层会消失
    查看全部
    0 采集 收起 来源:接口式编程

    2021-03-18

  • 接口的方式,规范了如何去访问配置文件
    查看全部
    0 采集 收起 来源:接口式编程

    2021-03-18

  • 通过接口调用,就不会出现那么多问题了 1.xml设置了全线类名,不会重复 2.调用的方法和参数也不会弄错了
    查看全部
    0 采集 收起 来源:接口式编程

    2021-03-18

  • 一行代码

    查看全部
    0 采集 收起 来源:接口式编程

    2021-03-18

  • 拦截器实现分页

    实际开发中,会有很多查询列表页面需要分页功能,这时分页的简单实现就不再适用,这时就需要把分页功能的共通代码分离出来,以供其他需要分页的地方使用。

    【1】页面的jsp和js方法的封装(完成跳转到后台)

    https://img4.sycdn.imooc.com/5d4b796500015dda08560395.jpg

    【2】sql的xml文件的sql语句进行封装(因为要传入Limit的参数,这里定义了两条几乎同样的sql语句,只不过是一条通过count(*)返回所有记录数,这里需要把查询所有sql语句封装)

    【3】配置文件sql语句后的Limit和起始位置和返回数量的封装

    https://img1.sycdn.imooc.com/5d4b799b00014cb806650157.jpg

    【4】页面可以通过自定义标签来解决,这样每个需要分页的地方直接引入该标签即可。

    https://img3.sycdn.imooc.com/5d4b797d00019d5408740414.jpg


    原始的JDBC中Dao层的封装:

    开发一个共通的方法,得到Connection对象,得到查询的sql语句,该共通方法可以根据sql语句查询出总条数(该sql语句无需截断再拼接count(*),这样容易出错。可以把该sql语句当作子查询,外面再嵌套一层sql语句),这样Page的属性就都有值了,就可以再Dao的sql语句后拼接Limit参数了。

    Mybatis中Dao层的封装:

    该封装的关键是sql语句在配置文件里,配置文件貌似获取不到sql参数。

    Mybatis拦截器:Mybatis拦截器提供为所有页面实现分页的功能,对拦截到的都会实现分页功能(实现原理:就是拦截查询的sql语句并把它修改为分页查询的sql语句)。

    在没有使用拦截器时,在执行sql之前拦截,并调用分页共通,修改的是Mybatis的源码。所以提供了拦截器,在不改变Mybatis源码的同时,可以修改源码的行为。

    Mybatis执行sql语句简化版的过程:它的原理和JDBC相似,根据sql语句得到PreparedStatement对象,为该对象setObject,再执行execute方法,最后得到结果,Mybatis拦截器就是相当于在传入sql语句获得PreparedStatement对象前,修改它为分页的sql语句。


    查看全部
  • 分页的简单实现

    重点关注分页功能中Mybatis部分的内容(观察Mybatis的介入和之前的分页有何不同)

    该分页功能的参数:

    1、记录总数。

    2、每页显示记录数。

    3、总页数。

    4、当前页。

    5、分页查询Limit的起始点。

    6、分页查询Limit的返回个数。

    通常封装一个类来实现分页功能:

    Mysql使用Limit进行分页。Limit关键字需要两个参数,一个是从第几条开始取,另一个是取多少条。

    该类中还封装了计算总页数的方法,并且可以计算出Limit需要的两个参数值,然后放到该类对象里供程序使用,如下图1,如果传进来的当前页数大于总页数,就把当前页数置为最后一页(也可以在前端页面进行设置,这里都在后端实现)如图2,还需保证当前页数不能小于1,如果小于1,则把它置为1。如图3,最后还需要计算sql语句Limit需要的参数,如图4。

    https://img1.sycdn.imooc.com/5d4a67c70001130208510344.jpg


    https://img1.sycdn.imooc.com/5d4a77d400011b9609150204.jpg

    https://img1.sycdn.imooc.com/5d4a78e30001d28907010206.jpg

    https://img2.sycdn.imooc.com/5d4a78e400011d1a08960210.jpg

    执行逻辑之前可以先查看Limit语句,第一页是从第0条开始获取,取5条。第二页是从第5条开始取,取5条,以此类推。

    https://img1.sycdn.imooc.com/5d4a79a700011afd04620139.jpg

    分页查询过程:

    预先定义好当前页面记录数和当前页面数,通过查询出来的记录数,可以计算出总页数,Limit的参数也就获取到了,这样Dao层就将Page对象交给XML,XML根据这两个参数查询,然后将查询的结果返回。

    Mybatis如果想传入XML两个参数时,可以使用Map集合。

    分页查询一般来说是按照某一字段进行排序,而且该字段值最好不要重复,可以是主键或者该字段创建的时间createTime,如果不主动设置排序方式,按照数据库默认排序方式,并不能保证每次执行sql语句的默认排序方式都是相同的。

    前端的javascript的校验相当于没有校验,所以如果考虑安全的问题时,在后端也需要加上校验。


    https://img4.sycdn.imooc.com/5d4ad1160001ec3709780795.jpg

    https://img1.sycdn.imooc.com/5d4ad1160001c10009460701.jpg


    查看全部
  • 接口式编程原理(中)

    SqlSession接口有两个实现类,分别为DefaultSqlSession和SqlSessionManager,这里获取的对象是属于DefaultSqlSession实现类的。

    首先sqlSession是我们手动封装获取的,这里调用的是Mybatis的方法,然后通过SqlSessionFactory对象的OpernSession方法获取SqlSession,其中SqlSessionFactory接口也有两个实现类,分别为DefaultSqlSessionFactory和SqlSessionManager,由源码得知SqlSessionFactoryBuilder类提供了build(Reader reader),该方法返回的是SqlSessionFactoryBuilder类提供的build(Reader reader,String envirment,Properties properties),该方法又返回的是SqlSessionFactoryBuilder提供的build(Configuration config)方法,该方法最后返回的是DefaultSqlSessionFactory对象。所以SqlSessionFactory获取的是DefaultSqlSessionFactory实现类对象。所以openSession方法是属于DefaultSqlSessionFactory里的方法。该openSession方法返回的是DefaultSqlSessionFactory提供的openSessionFromDataSource(ExecutorType execType,..),该方法最终返回的是DefaultSqlSession类的对象

    所以最终获取的是DefaultSqlSession。


    https://img3.sycdn.imooc.com/5d3e6afa00017b4706740219.jpg

    https://img4.sycdn.imooc.com/5d3e6afa0001269b07400268.jpg

    https://img1.sycdn.imooc.com/5d3e6afa0001b23710870526.jpg

    https://img1.sycdn.imooc.com/5d3e6b8c0001058a11200617.jpghttps://img4.sycdn.imooc.com/5d3e6c2900018d9d11290560.jpghttps://img2.sycdn.imooc.com/5d3e6c6b00018d9d11290560.jpg

    这里我们可以查看DefaultSqlSession的getMapper方法,该方法返回的是Configuration类提供的getMapper方法,该方法第一个参数就是传进来的class,也就是接口的类类型,第二个参数是this,也就是方法的对象,也就是sqlSession,该方法返回的是MapperRegistry类提供的getMapper方法,该方法返回值可以理解为通过代理工厂,生产一个代理返回出去(这里就是前面说的通过动态代理创建实例)。

    https://img1.sycdn.imooc.com/5d3e6d2500010a2a11320574.jpghttps://img3.sycdn.imooc.com/5d3e6d930001ff6510690588.jpghttps://img1.sycdn.imooc.com/5d3e6ddd000180f411070615.jpg


    该动态工厂的由来是Map对象(以类类型作为Key,MapperProxyFactory作为Value)的get方法,该get方法中传入一个类类型,MapperRegistry类提供了addMapper方法,该方法需要传入一个类类型,然后用Map对象的input方法把传入的类类型作为key,临时创建一个动态工厂作为value,并传入这个类类型,只有调用了这个方法才会对Map集合初始化,该方法的调用是在加载Mybatis核心配置文件时进行调用的,它会不停的调用这个方法,为不同的Class创建代理工厂。


    https://img2.sycdn.imooc.com/5d3e878d0001601b11490170.jpg

    https://img2.sycdn.imooc.com/5d3e878e0001728d11390142.jpg

    https://img2.sycdn.imooc.com/5d3e88440001745f11260313.jpg

    动态工厂创建代理对象是通过MapperProxyFactory的new Instance(SqlSession sqlSession)方法,该方法中创建了代理类,该代理类的构造函数中第一个参数是传进来的sqlSession,后两个参数是代理工厂的属性,第二个参数就是接口的类类型,构造函数并没有为其他属性赋值,所以第三个参数只是Map初始化的一个对象。

    https://img1.sycdn.imooc.com/5d3e8a140001af8711350580.jpg

    https://img1.sycdn.imooc.com/5d3e8ac40001f60311100309.jpg


    查看全部
  • 接口式编程原理

    讲解接口式原理之前需了解如下几个问题

    https://img2.sycdn.imooc.com/5d3925440001225e10590498.jpg

    问题1:没有实现类的接口为甚么可以实现方法的功能(答案:是通过动态代理。简单的动态代理过程,是要有一个实现InvocationHandler接口的类,这里给这个类起名为MapperProxy,因为Mybatis源码中就是起的这个名称,这个类必须实现invoke()方法。然后用这个类通过Proxy.newProxyInstance(类加载器,接口,MapperProxy对象)创建一个代理实例,在案例中是通过sqlSession.getMapper()获取到代理实例的,表面上看是使用接口承接的,但该对象不是实现类的对象,而是一个代理实例,然后是通过这个代理实例调用接口里的方法,由动态代理知识,它并不会执行这个方法,而是会触发MapperProxy的invoke()方法,这样没有实现类的接口方法就可以执行了)。

    https://img3.sycdn.imooc.com/5d3922320001931d11580680.jpg


    问题2:虽然调用接口方法时,走的是invoke()方法,怎么知道调用的sql语句是什么样子的呢?(因为调用的sql语句在配置文件中,在获取SqlSession对象之前,由于调用加载Mybatis核心配置文件的方法,Mybatis配置文件中引入了sql配置文件的路径,这样加载Mybatis总配置文件的同时,也把其他配置文件加载了,这些信息Mybatis会存储到对象(Configuration)中,当代理实例调用接口方法时,如果该接口方法与配置信息能对应上(配置文件的namespace等于包名+接口名,方法名等于id名,接口参数等于parameterType,返回值类型等于resultType),就可以成功调用,根据上节课知识,这里是存在某种联系的——>接口的全名称就是配置文件的namespace,调用的方法名就是定义sql标签的id,接口的全名称和调用的方法名在invoke()方法中是可以获取到的,有了这些信息就可以获取到配置文件信息,然后再invoke方法里就可以代替原来写的方法)

    https://img2.sycdn.imooc.com/5d3924af0001bafb09370631.jpg

    问题3:根据动态代理的知识,Proxy.newProxyInstance()返回的是Object类型的对象,但却赋值给接口类型的对象?

    (答案:这里是泛型的作用,当使用getMapper()传入的是什么样的类类型,就可以使用什么样的类型去接值,这就是Mybatis利用泛型进行强转了)。

    https://img2.sycdn.imooc.com/5d3e63220001016211360630.jpg


    查看全部
  • 接口式编程(针对调用配置文件sql语句这行代码,有四处值得分析的地方)

    1、namespace :方法里的namespace需要和mapper标签的namespace一致,由于两边是手写的,可能存在不一致的风险,而且也不能保证多个sql配置文件,namespace不冲突。

     2、与sql关联的id :方法里的id和标签的id也是手写的,也存在不一致的风险。

     3、传入的参数 :例如selectList传入的参数类型是Object,所以传入的参数不管是何种类型,它不会报错,但是如果传入的类型和parameterType类型不匹配,sql语句中引用的参数就会出错。

     4、返回值:例如selectList方法,Mybatis提供了一种约束,只要是List即可,无论集合中存储何种类型,但是这样不意味执行就是对的,因为真正存入的是resultMap约束的,编译时不会报错,执行时可能就会报错。

    SqlSession方法的mapper的namespace、与sql关联的id、传入的参数、返回值。

    接口式编程:就是为了避免上述风险,而人为做的强制性规范和约束,Mybatis提供的这种方式,就称作接口式编程(相当于sql的配置文件有一个java接口作为代言人,这样SqlSession对象直接调用接口里的方法即可。但是该接口有一些前提:

    1、namespace的统一:该接口的包名+接口名就是namespace名。

    2、sql标签id的统一:代言人代言一条sql语句提供给外面,代言哪条sql语句,就提供和该sql的id相同名称方法。该接口可以代言sql配置文件的sql语句,通过提供方法,方法名为id名。

    3、方法参数的统一:接口方法参数类型为parameterType类型。

    4、方法返回值的统一:接口方法返回值类型为resultMap类型。

    注意:如上该接口就可以代言sql语句了。该接口不用人为手动编写实现类,通过Mybatis获取该接口,就可以调用,Mybatis已经实现了该接口(它就会知道该方法是调用配置文件中的哪条sql语句)。因为当前该接口没有实现类,这里通过SqlSession对象的getMapper(接口的类类型)就可以获得该接口实现类的代理对象,这样就可以直接调用接口里的方法,而不用传入namespace+id,而是按照接口的约束进行调用)。

    这样就避免了上述的问题:namespace不可能相同,因为不可能有多个相同名全路径的接口,调用方法时也不需要传入namespace。同一个接口里也不肯有多个相同名称的方法。传入的参数已经被限制,如果不符合编译会报错。返回的接口也被限定,如果不符合编译也会报错。

    接口式编程的作用:
    1、规范访问配置文件

    2、当mybatis和spring整合后,配置的数据源将交给Spring管理,也就意味着认为手写的提供SqlSession会消失,Spring将提供SqlSesssion,传入的参数应该交给Service处理好再传入进来。通过SqlSession调用接口式编程的这些代码统统都由Spring来实现。这个Dao层将会消失,该接口将会变成真正的Dao层,这时Dao层将只剩下接口文件和配置文件。

    https://img4.sycdn.imooc.com/5d391bc00001803c08140440.jpg

    https://img2.sycdn.imooc.com/5d391bc20001ef2210950322.jpg

    https://img2.sycdn.imooc.com/5d391c1a0001437809360282.jpg
    当Mybatis与Spring结合时,这些Spring提供了便捷,这里只做一些了解即可,整合之后整个Dao层只剩接口文件和配置文件。



    查看全部
    0 采集 收起 来源:接口式编程

    2020-09-06

  • invoke方法的第一个参数proxy即拿到的代理实例

    查看全部
  • getMapper返回的对象实际上是一个Proxy.newProxyInstance返回的代理实例

    查看全部
  • MyBatis会加载mapper配置文件的namespace为一个Class<T>类型实例

    查看全部
  • 使用SqlSession的getMapper方法来直接获取Dao接口的实现类

    查看全部
    0 采集 收起 来源:接口式编程

    2019-12-25

  • 1、在sql的配置文件中,parameterType是如何被加载出现的,

    首先是加载总configuration.xml,将其转换为Reader流,通过Reader流转换为Document,使用jdk中的dom来解析其中的xml标签,使用XPath来读取xml中信息。

    在逐步解析mappers,mapper,resource,慢慢解析到parameterType,其中这个parameterType不是固定的写法需要类名.包名这种,此属性无须担心大小写,简写map,int[]等什么的都是可以的,源码中会将输入的字符串都转为小写,而且对于简写也有相应的匹配项。


    查看全部

举报

0/150
提交
取消
课程须知
本课程的前导课程为《通过自动回复机器人学 Mybatis ---基础版》, 课程中案例的关联性极强,所以学习本课程唯一的条件就是学习过《通过自动回复机器人学 Mybatis ---基础版》
老师告诉你能学到什么?
1、 Mybatis 的接口式编程 2、实现分页查询 3、通过拦截器实现分页共通来了解 Mybatis 的拦截器 4、通过如何用数组做参数来了解 Mybatis 对类型的处理 5、 Mybatis 如何实现 jdbc 的 addBatch ,即批量插入

微信扫码,参与3人拼团

意见反馈 帮助中心 APP下载
官方微信
友情提示:

您好,此课程属于迁移课程,您已购买该课程,无需重复购买,感谢您对慕课网的支持!