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

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

难度中级
时长 2小时43分
学习人数
综合评分9.77
214人评价 查看评价
9.9 内容实用
9.7 简洁易懂
9.7 逻辑清晰
  • 其他相关代码: @Message.xml <select id="queryMessageListByPage" parameterType="java.util.Map" resultMap="MessageResult"> select <include refid="columns"></include> from MESSAGE <where> <if test="message.command != null and !"".equals(message.command.trim())"> and COMMAND=#{message.command} </if> <if test="message.description != null and !"".equals(message.description.trim())"> and DESCRIPTION like '%' #{message.description} '%' </if> </where> order by ID </select> @Configuration.xml <plugins> <!-- <plugin interceptor="com.imooc.interceptor.PageInterceptor" ></plugin> 如果不需要初始化参数(setProperties()),则直接这条语句即可 --> <plugin interceptor="com.imooc.interceptor.PageInterceptor"> <property name="test" value="abc"></property> </plugin> </plugins> Ps:一个拦截器对应一个<plugin>。
    查看全部
    0 采集 收起 来源:拦截器总结

    2018-03-22

  • 通过BoundSql获得原始的sql语句之后,再次使用的是BoundSql的getParameterObject()来获取配置文件中的参数,因为得到的参数是一个map,调用对象的get方法得到Page对象,得到page对象之后就可以拼接分页sql了。metaObject.setValue(“delegate.boundSql.sql”,pageSql)修改原本不可以修改的值,修改原来的属性值为新的sql。 mybatis通过Invocation这个参数的proceed()方法交回主权,这个方法的源码 return method.invoke(target,args)
    查看全部
  • 使用BoundSql的getParameterObject()的方法,里面的入参就是正常调用Mapper的方法,获取查询结果对象的的参数,这里就是Map<String,Object>parameter,通过BoundSql的getParameterObject()的方法,可以获得入参对象,由于这个对象是一个map,封装了xml配置文件中执行sql语句时候的参数,所以可以这个对象获得分页查询limit关键字所需要的(起始页)和(每页显示记录数)parameter.getKey().
    查看全部
  • 在使用拦截器开发分页的时候,拦截器的参数(Invocation)中保存了拦截器所拦截的所有对象,根据方法签名,这里仅仅只是对statementHandler中的关键信息进行处理,原理就是使用分页的sql替换拦截到的原始sql,拦截对象类型是StatementHandler,由方法签名决定的,StatementHandler将对配置文件中的sql语句进行处理(sql语句在MappedStatement中),但是在StatementHandler中,所有的对象属性均为受保护的以及私有的,首先想到的是通过反射读写信息,幸好Mybatis已经有一个类MetaObject,有个方法 MetaObject.forObject(statementHandler,__,__)可以对注解的拦截方法签名所对应的对象进行包装,这样我们得到的是被包装的statementHandler,它可以通过getValue("delegate.mappedStatement")方法,得到想要任何属性;当我们得到原始sql并拼接page参数的时候,通过原始sql对象的BoundSql.getParameterObject()便可以拿到page参数,这样分页sql就可以拼接完成了,但是还需要给page对象设置总页数,总页数是个难点,需要在原始的sql语句上拼接 select count(*),这里的问题在于sql是否能执行以及如何执行,需要connection对象,而此对象就是方法签名的参数,可以通过invocation.getArgs()[0]获得,然后通过connection.prepareStatement(countSql)将拼接好的sql语句进行预编译,并执行,就可以获得结果,由于此结果是统计总数的,只有一条记录,将此记录转换为int类型,并赋值给page对象。
    查看全部
  • 实现拦截器需要实现三个方法:①intercept(Invocation invacation) ② plugin(Object target)方法参数就是被拦截的对象target,返回的就是满足条件的代理类,Plugin.wrap(target,this):this也就是自定义拦截器实例,通过获取注解得到要拦截的类型,比较target的类型与this获取的要拦截的类型是不是一致,如果满足条件就获取代理对象,并执行intercept方法,没有获取代理对象的将直接返回,不会经过intercept方法。 mybatis获取statement其实是在statementHandler中,这是一个处理接口,有个prepare方法,返回Statement,这个方法是在BaseStatementHandler中实现的,statement是在instantiateStatement这个方法中获取的,这个方法是一个抽象方法,看它的PrepareStatementHandler实现,在这里边看到了connection.prepareStatement(sql,PreparedStatement.),也就是和JDBC类似的代码了,这就是分页拦截器要拦截的位置了。如何实现拦截呢?mybatis提供了相应的注解:@Intercept({@Signnature(type=StatementHandler.class),method=“prepare”,args={Connection.class}}) ①type指向要连接的接口class,这里指向StatementHandler.class, ②Method指向要拦截的方法,这里是prepare ③args[]拦截的方法的参数类型,这里是Connection.class 这样就准确描述了要拦截StatementHandler接口下的prepare方法。目标确定,接下来就可以做手脚了,在PrepareStatementHandler拿到sql语句之前将这个sql语句改装成我们的分页sql,然后在塞回去,让程序继续执行,这样就成功了。
    查看全部
  • mybatis获取statement其实是在statementHandler中,这是一个处理接口,有个prepare方法,返回Statement,这个方法是在BaseStatementHandler中实现的,statement是在instantiateStatement这个方法中获取的,这个方法是一个抽象方法,看它的PrepareStatementHandler实现,在这里边看到了connection.prepareStatement(sql,PreparedStatement.),也就是和JDBC类似的代码了,这就是分页拦截器要拦截的位置了。如何实现拦截呢?mybatis提供了相应的注解:@Intercept({@Signnature(type=StatementHandler.class),method=“prepare”,args={Connection.class}}) 1.type指向要连接的接口class,这里指向StatementHandler.class 2.Method指向要拦截的方法,这里是prepare 3.args[]拦截的方法的参数类型,这里是Connection.class 这样就准确描述了要拦截StatementHandler接口下的prepare方法。目标确定,接下来就可以做手脚了,在PrepareStatementHandler拿到sql语句之前将这个sql语句改装成我们的分页sql,然后在塞回去,让程序继续执行,这样就成功了。
    查看全部
  • mybatis拦截器实现分页
    查看全部
  • <select id="queryMessageList" parameterType="com.imooc.bean.Message" resultMap="MessageResult"> select <include refid="columns"/> from message <where> <if test="command!=null and !&quot;&quot;.equals(command.trim())"> and COMMAND=#{command} </if> </where> </select> //对比上下代码 <select id="queryMessageList" parameterType="java.util.Map" resultMap="MessageResult"> select <include refid="columns"/> from message <where> <if test="message.command!=null and !&quot;&quot;.equals(message.command.trim())"> and COMMAND=#{message.command} </if> </where> order by ID limit #{page.dbIndex},#{page.dbNumber} </select> Q1:为何选择java.util.Map?不用实体类? 因为里面代码涉及到两个实体类,所以选择一个它们通用的类型。 Q2:为何选择java.util.Map?不用Lits等之类的? 从parameterType来看字面意思是:参数类型,所以如下代码: parameter.put("message", message); parameter.put("page", page); 传过来的参数parameter来使用。所以接下来的属性前加上message.xxx;page.xxx;(key值对应)。 注意:过早过迟的拦截都不合适。所以在PreparedStatement pstmt=conn.prepareStatement(sql.toString());之前拦截即可(把SQL语句处理再放进去提交)。
    查看全部
  • 前端校验等于没有校验,为了保证安全,最好后端做校验。
    查看全部
  • @list.jsp部分代码 <div class='page fix'> 共 <b>${page.totalNumber}</b> 条 <c:if test="${page.currentPage != 1}"> <a href="javascript:changeCurrentPage('1')" class='first'>首页</a> <a href="javascript:changeCurrentPage('${page.currentPage-1}')" class='pre'>上一页</a> </c:if> 当前第<span>${page.currentPage}/${page.totalPage}</span>页 <c:if test="${page.currentPage != page.totalPage}"> <a href="javascript:changeCurrentPage('${page.currentPage+1}')" class='next'>下一页</a> <a href="javascript:changeCurrentPage('${page.totalPage}')" class='last'>末页</a> </c:if> 跳至&nbsp;<input id="currentPageText" type='text' value='${page.currentPage }' class='allInput w28' />&nbsp;页&nbsp; <a href='javascript:changeCurrentPage($(' #currentPageText').val()') class='go'>GO</a> </div> <!--js代码--> /** * 修改当前页码,调用后台重新查询 */ function changeCurrentPage(currentPage){ $("#currentPage").val(currentPage); $("#mainForm").submit(); }
    查看全部
  • @Page部分源码 /** * 分页对应的实体类 * */ public class Page { private int totalNumber;//总条数 private int currentPage;//当前第几页 private int totalPage;//总页数 private int pageNumber=5;//每页显示条数 private int dbIndex;//数据库中Limit的参数,从第几条开始取 private int dbNumber;//数据库中Limit的参数,一共取多少条 /** * 根据当前对象中属性值计算并设置相关属性值 */ public void count(){ //计算总页数 int totalPageTemp=this.totalNumber / this.pageNumber; int plus=(this.totalNumber % this.pageNumber) == 0 ? 0 : 1; totalPageTemp=totalPageTemp+plus; if(totalPageTemp<=0){ totalPageTemp=1; } this.totalPage=totalPageTemp; //设置当前页数 //总页数小于当前页数,将当前页数设为总页数 if(this.totalPage<this.currentPage){ this.currentPage=this.totalPage; } //当前页数小于1时,设当前页数为1 if(this.currentPage<1){ this.currentPage=1; } //设置limit参数 this.dbIndex=(this.currentPage-1)*this.pageNumber; this.dbNumber=this.pageNumber; } //其他getter和setter方法,在此忽略 public void setTotalNumber(int totalNumber) { this.totalNumber = totalNumber; this.count(); } }
    查看全部
  • 课后作业 关键代码: @MessageDao.java IMessage imessage = sqlSession.getMapper(IMessage.class); messageList=imessage.queryMessageList(message); //messageList=sqlSession.selectList("Message.queryMessageList",message); @IMessage.java /** * 与Message配置文件相对应的接口 */ public interface IMessage { public List<Message> queryMessageList(Message message); } @Message.xml <mapper namespace="com.imooc.dao.IMessage"> <select id="queryMessageList" ...
    查看全部
  • 面向接口编程---源码详细步骤 加载配置信息... 通过配置信息加载一个代理工厂Map: 这个Map存放的是接口Class与对应的代理工厂 通过接口的Class从代理工厂取出对应的代理工厂 通过代理工厂实例化一个代理类 用这个代理类将代理实例返回出去 通过接口与method获取对应的配置文件信息: 接口名.方法名==namspace.id 通过配置文件中的信息获取SQL语句类型 根据SQL语句类型调用sqlSession对应的增删改查方法 当SQL语句类型是查询时: 根据返回值类型是List,Map,Object 分别调用selectList,selectMap,selectObject方法
    查看全部
  • 查看一个接口的所有实现类:选中接口名,Ctrl+T 或者选中该接口名,按F4,即 Open Type Hierarchy IMessage imessage=sqlSession.getMapper(IMessage.class);//获取到的就是代理实例 messageList =imessage.queryMessageList(parameter);//代理实例执行接口方法时,就会触发调用处理程序,也就是第三个参数对象的invoke()方法,MapperProxy是实现了InvocationHandler接口的 MapperProxyFactory.newInstance(MapperProxy<T> mapperProxy){ --return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader()//通过接口获取类加载器,new Class[]{mapperInterface}//代理类实现的接口数组,mapperProxy//调用代理实例的处理程序) --} 解决了三个问题: 1、为什么只定义了一个接口,没有实现类的情况下,接口方法可以被调用,因为动态代理。 2、为什么sqlSession.getMapper(.class)可以根据传入的参数,返回一个对应的类型,因为泛型。 3、Mybatis加载文件时,利用namespace加载了一个class,然后把这个class与代码中传入接口的class进行匹配,方法执行所需要的信息就是来自于已经匹配成功的配置文件中,当结果与配置文件对应上后,调用接口的方法执行sql语句。
    查看全部
  • /*动态代理,接口没有实现类.Mybatis为接口提供实现类,即用Proxy.newProxyInstance()创建代理实例,返回类型为Object,利用泛型强制转换*/ IMessage imessage = sqlSession.getMapper(IMessage.class); /*代理实例调用接口方法时,并不会执行,而是触发 MapperProxy.invoke(),其中包含sqlSession.selectList(namespace.id,parameter)*/ /*至于为什么会包含,因为接口方法与(加载Mybatis的)配置信息对应得上,即 接口名.方法=namespace.id*/ messageList = imessage.queryMessageList(message);
    查看全部

举报

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

微信扫码,参与3人拼团

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

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