用注解还是用 xml 配置?
常用注解:@Insert、@Select、@Update、@Delete、@Param、@Results、
@Result
在 MyBatis 的工程中,我们有两种配置 SQL 的方式。一种是在 Mapper.xml 中集中
管理,一种是在 Mapper 接口上,用注解方式配置 SQL。很多同学在工作中可能两种方
式都用过。那到底什么时候用 XML 的方式,什么时候用注解的方式呢?
注解的缺点是 SQL 无法集中管理,复杂的 SQL 很难配置。所以建议在业务复杂的项
目中只使用 XML 配置的形式,业务简单的项目中可以使用注解和 XML 混用的形式。
Mapper 接口无法注入或 Invalid bound statement (not found)
我们在使用 MyBatis 的时候可能会遇到 Mapper 接口无法注入,或者 mapper
statement id 跟 Mapper 接口方法无法绑定的情况。基于绑定的要求或者说规范,我们
可以从这些地方去检查一下:
1、扫描配置,xml 文件和 Mapper 接口有没有被扫描到
2、namespace 的值是否和接口全类名一致
3、检查对应的 sql 语句 ID 是否存在
怎么获取插入的最新自动生成的 ID
在 MySQL 的插入数据使用自增 ID 这种场景,有的时候我们需要获得最新的自增 ID,
比如获取最新的用户 ID。常见的做法是执行一次查询,max 或者 order by 倒序获取最
大的 ID(低效、存在并发问题)。在 MyBatis 里面还有一种更简单的方式:
insert 成功之后,mybatis 会将插入的值自动绑定到插入的对象的 Id 属性中,我们
用 getId 就能取到最新的 ID。
<insert id="insert" parameterType="com.gupaoedu.domain.Blog">
insert into blog (bid, name, author_id)
values (#{bid,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{author,jdbcType=CHAR})
</insert>
blogService.addBlog(blog);
 
如何实现模糊查询 LIKE
1、字符串拼接
在 Java 代码中拼接%%(比如 name = "%" + name + "%"; ),直接 LIKE。因为没
有预编译,存在 SQL 注入的风险,不推荐使用。
2、CONCAT(推荐)
<when test="empName != null and empName != ''">
AND e.emp_name LIKE CONCAT(CONCAT('%', #{emp_name, jdbcType=VARCHAR}),'%')
</when>
3、bind 标签
<select id="getEmpList_bind" resultType="empResultMap" parameterType="Employee">
<bind name="pattern1" value="'%' + empName + '%'" />
<bind name="pattern2" value="'%' + email + '%'" />
SELECT * FROM tbl_emp
<where>
<if test="empId != null">
emp_id = #{empId,jdbcType=INTEGER},
</if>
<if test="empName != null and empName != ''">
AND emp_name LIKE #{pattern1}
</if>
<if test="email != null and email != ''">
AND email LIKE #{pattern2}
</if>
</where>
ORDER BY emp_id
</select>
什么时候用#{},什么时候用${}?
在 Mapper.xml 里面配置传入参数,有两种写法:#{} 、${}。作为 OGNL 表达式,
System.out.println(blog.getBid()); 
 
都可以实现参数的替换。这两种方式的区别在哪里?什么时候应该用哪一种?
要搞清楚这个问题,我们要先来说一下 PrepareStatement 和 Statement 的区别。
1、两个都是接口,PrepareStatement 是继承自 Statement 的;
2、Statement 处理静态 SQL,PreparedStatement 主要用于执行带参数的语句;
3、PreparedStatement 的 addBatch()方法一次性发送多个查询给数据库;
4、PS 相似 SQL 只编译一次(对语句进行了缓存,相当于一个函数),比如语句相
同参数不同,可以减少编译次数;
5、PS 可以防止 SQL 注入。
MyBatis 任意语句的默认值:PREPARED
这两个符号的解析方式是不一样的:
#会解析为 Prepared Statement 的参数标记符,参数部分用?代替。传入的参数会
经过类型检查和安全检查。
(mybatis-standalone - MyBatisTest - testSelect())
 
==> Preparing: select * from blog where bid = ?
==> Parameters: 1(Integer)
<==
Columns: bid, name, author_id
<==
Row: 1, 咕泡学院, 1001
<==
Total: 1
查询结果:Blog{bid=1, name='咕泡学院', authorId='1001'}
$只会做字符串替换,比如参数是咕泡学院,结果如下:
(mybatis-standalone - MyBatisTest - selectBlogByBean ())
==> Preparing: select bid,name,author_id authorId from blog where name = '咕泡学院'
==> Parameters:
<==
Columns: bid, name, authorId
<==
Row: 1, 咕泡学院, 1001
<==
Total: 1
查询结果:[Blog{bid=1, name='咕泡学院', authorId='1001'}]
#和$的区别:
1、 是否能防止 SQL 注入:$方式不会对符号转义,不能防止 SQL 注入
2、 性能:$方式没有预编译,不会缓存
结论:
1、 能用#的地方都用#
2、 常量的替换,比如排序条件中的字段名称,不用加单引号,可以使用$
对象属性是基本类型 int double,数据库返回 null 是报错
使用包装类型。如 Integer,不要使用基本类型如 int。
If test !=null 失效了?
在实体类中使用包装类型。
XML 中怎么使用特殊符号,比如小于 &
1、转义< < (大于可以直接写)
2、使用<![CDATA[ ]]>——当 XML 遇到这种格式就会把[]里面的内容原样输出,不
进行解析
 
1、resultType 和 resultMap 的区别?
resultType 是<select>标签的一个属性,适合简单对象(POJO、JDK 自带类型:
Integer、String、Map 等),只能自动映射,适合单表简单查询。
<select id="selectAuthor" parameterType="int" resultType="com.gupaoedu.domain.Author">
select author_id authorId, author_name authorName
from author where author_id = #{authorId}
</select>
resultMap 是一个可以被引用的标签,适合复杂对象,可指定映射关系,适合关联
复合查询。
<resultMap id="BlogWithAuthorResultMap"
type="com.gupaoedu.domain.associate.BlogAndAuthor">
<id column="bid" property="bid" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<!-- 联合查询,将 author 的属性映射到 ResultMap -->
<association property="author" javaType="com.gupaoedu.domain.Author">
<id column="author_id" property="authorId"/>
<result column="author_name" property="authorName"/>
</association>
</resultMap>
2、collection 和 association 的区别?
association:一对一
<!-- 另一种联合查询(一对一)的实现,但是这种方式有“N+1”的问题 -->
<resultMap id="BlogWithAuthorQueryMap" type="com.gupaoedu.domain.associate.BlogAndAuthor">
<id column="bid" property="bid" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<association property="author" javaType="com.gupaoedu.domain.Author"
column="author_id" select="selectAuthor"/> <!-- selectAuthor 定义在下面
-->
</resultMap>
collection:一对多、多对多
<!-- 查询文章带评论的结果(一对多) -->
<resultMap id="BlogWithCommentMap" type="com.gupaoedu.domain.associate.BlogAndComment"
extends="BaseResultMap" >
<collection property="comment" ofType="com.gupaoedu.domain.Comment">
<id column="comment_id" property="commentId" />
<result column="content" property="content" />
</collection>
</resultMap>
<!-- 按作者查询文章评论的结果(多对多) -->
<resultMap id="AuthorWithBlogMap" type="com.gupaoedu.domain.associate.AuthorAndBlog" >
<id column="author_id" property="authorId" jdbcType="INTEGER"/>
<result column="author_name" property="authorName" jdbcType="VARCHAR"/>
<collection property="blog" ofType="com.gupaoedu.domain.associate.BlogAndComment">
<id column="bid" property="bid" />
<result column="name" property="name" />
<result column="author_id" property="authorId" />
<collection property="comment" ofType="com.gupaoedu.domain.Comment">
<id column="comment_id" property="commentId" />
<result column="content" property="content" />
</collection>
</collection>
</resultMap> 
3、PrepareStatement 和 Statement 的区别?
两个都是接口,PrepareStatement 是继承自 Statement 的;
Statement 处理静态 SQL,PreparedStatement 主要用于执行带参数的语句;
PreparedStatement 的 addBatch()方法一次性发送多个查询给数据库;
PS 相似 SQL 只编译一次(对语句进行了缓存,相当于一个函数),减少编译次
数;
PS 可以防止 SQL 注入;
MyBatis 默认值:PREPARED
4、跟踪 update()流程,绘制每一步的时序图(4 个)
自行绘制。
5、总结:MyBatis 里面用到了哪些设计模式?(已讲解)
第三次课已讲解,笔记中有。
6、当我们传入 RowBounds 做翻页查询的时候,使用 limit 物理分页,代替原来的逻辑分页
基于 mybatis-standalone,MyBatisTest.java —— testSelectByRowBounds()
>代码在 interceptor 包中
7、在未启用日志组件的情况下,输出执行的 SQL,并且统计 SQL 的执行时间(先实现查询
的拦截)
>代码在 interceptor 包中 
 
 
 

mybatis(十一)mybatis常见问题的更多相关文章

  1. MyBatis(十一):MyBatis架构流程浅析

    架构分层 我们将MyBatis架构分为三层,分别为接口层.数据处理层和框架支撑层 接口层:提供外部接口调用的API,使用端通过这些API来操作数据库,接口层收到请求后会调用数据处理层完成具体的数据处理 ...

  2. 【Mybatis】MyBatis之配置自定义数据源(十一)

    本例是在[Mybatis]MyBatis之配置多数据源(十)的基础上进行拓展,查看本例请先学习第十章 实现原理 1.扩展Spring的AbstractRoutingDataSource抽象类(该类充当 ...

  3. Hello Mybatis 02 mybatis generator

    接着上一篇文章通过Mybatis完成了一个User的CRUD的功能之后,这篇开始还需要建立一个Blog类,这样就可以模拟一个简单的微博平台的数据库了. 数据库准备 首先我们,还是需要在数据库中新建一个 ...

  4. 【Mybatis】MyBatis之动态SQL(六)

    MyBatis 的强大特性之一便是它的动态 SQL,本章介绍动态 SQL 查看本章,请先阅读[Mybatis]MyBatis对表执行CRUD操作(三). 本例表结构 CREATE TABLE `emp ...

  5. 【Mybatis】MyBatis之Sql配置文件的使用(四)

    上一章[Mybatis]MyBatis对表执行CRUD操作(三),已经讲了基本操作,本章介绍Sql配置文件中常用功能 1.插入返回主键 2.参数值的获取方式 3.resultMap使用 插入返回主键 ...

  6. MyBatis笔记----MyBatis 入门经典的两个例子: XML 定义与注解定义

    ----致敬MyBatis官方开放文档让大家翻译,不用看书直接看文档就行了,mybatis的中文文档还需要完备的地方 简介 什么是 MyBatis ? MyBatis 是支持定制化 SQL.存储过程以 ...

  7. 【Mybatis】MyBatis对表执行CRUD操作(三)

    本例在[Mybatis]MyBatis配置文件的使用(二)基础上继续学习对表执行CRUD操作 使用MyBatis对表执行CRUD操作 1.定义sql映射xml文件(EmployeeMapper.xml ...

  8. 【Mybatis】MyBatis配置文件的使用(二)

    本例在[Mybatis]MyBatis快速入门(一)基础上继续学习XML映射配置文件 MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置(settings)和属性(properti ...

  9. 【转】Mybatis学习---MyBatis知识、原始Dao开发和mapper代理开发

    [原文]https://www.toutiao.com/i6594610137560777223/ 一.什么是MyBatis MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及 ...

随机推荐

  1. Python 身份证校验代码

    Python 身份证校验代码 居民身份证bai编号识别 1.身份证编码规则如下:根据[中华人民共和国国家标准GB11643-1999]中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本 ...

  2. 并发编程常用工具类(一) countDownLatch和cyclicBarrier的使用对比

    1.CountDownLatch           countDownLatch的作用是让一组线程等待其他线程完成工作以后在执行,相当于加强版的join(不懂可以百度一下join的用法),一般在初始 ...

  3. try-catch-finally中的4个大坑,不小心就栽进去了!

    在 Java 语言中 try-catch-finally 看似简单,一副人畜无害的样子,但想要真正的"掌控"它,却并不是一件容易的事.别的不说,咱就拿 fianlly 来说吧,别看 ...

  4. jmeter进行分布式压测过程与 注意事项

    jmeter命令行运行但是是单节点下的, jmeter底层用java开发,耗内存.cpu,如果项目要求大并发去压测服务端的话,jmeter单节点难以完成大并发的请求,这时就需要对jmeter进行分布式 ...

  5. (011)每日SQL学习:SQL开窗函数

    开窗函数:在开窗函数出现之前存在着很多用 SQL 语句很难解决的问题,很多都要通过复杂的相关子查询或者存储过程来完成.为了解决这些问题,在 2003 年 ISO SQL 标准加入了开窗函数,开窗函数的 ...

  6. celery 原理

    https://mp.weixin.qq.com/s/FzvZHQpF5mhV9t_HBzlcwg Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处 ...

  7. new() 和 make() 的区别 var arr1 = new([5]int) var arr2 [5]int

    Effective Go - The Go Programming Language https://golang.org/doc/effective_go.html#allocation_new A ...

  8. Jenkins部署springboot项目

    记录jenkins如何部署springboot项目(jar类型的) 一.首先需要先配置好jenkins的基本配置(jdk.maven--),可在系统管理-->>全局工具配置中进行配置. 配 ...

  9. 六:Spring Security 中使用 JWT

    Spring Security 中使用 JWT 1.无状态登录 1.1 什么是有状态? 1.2 什么是无状态 1.3 如何实现无状态 2.JWT 2.1 JWT数据格式 2.2 JWT交互流程 2.3 ...

  10. hadoop(集群)完全分布式环境搭建

    一,环境 主节点一台: ubuntu desktop 16.04 zhoujun      172.16.12.1 从节点(slave)两台:ubuntu server 16.04 hadoop2  ...