美文网首页工作生活
MyBatis开发过程常见的坑

MyBatis开发过程常见的坑

作者: 欧文不哭 | 来源:发表于2019-06-29 17:58 被阅读0次

之所以把写关于MyBatis开发过程中遇到的坑写下来并变成文章,第一个是对自己开发MyBatis的过程中遇到的问题的一个总结,同事也是希望其他看到本博文的网友可以少遇到一些坑。

1. 异常篇

  1. 无效绑定



    提示无效的绑定的方式(映射错误)(比如没有找到那个findAll 的方法)
    原因:出在了XML Mapper文件上,去对应的XML文件查看。
    可能是:
    1). namespace 错误
    2). resultMap 错误(type错误、属性错误)

  2. 查询结果集超过一个


    此异常也是开发过程中常见的坑,比如public User findUserByUsername()这样的查询,方法返回的是一个User对象,但实际数据有可能是可以查询出多条的。很多时候开发的时候由于数据不够真实或者测试的不够充分,问题往往不会暴露出来,等到生产环境才会暴露出来。对于此类问题避免的方法就是对应返回一个非集合类的时候,需要特别注意查询是不是会返回多条记录的问题(单字段查询的话可以看看此字段数据库是不是有唯一性索引),如果不确定那么可以加上limit 1比较保险。
  3. 字段映射不正确


### Error querying database.  Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'name' in 'field list'
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'name' in 'field list'
; bad SQL grammar []

主要原因:

  • Mybatis XML中的SQL语句查询的列,不在数据库中。
  • 新增SQL语句中的列不在数据库中,或列对应的值,数据类型不一致。
    解决办法: 根据项目实际情况,通常有以下三种解决办法:
  • 修改SQL语句中,将不存在的列从语句中去掉。
  • 在数据库中,新增该不存在的列。
  • 在新增时,不要使用中文符号的``表示字符串。也就是~符号对应的键。
  1. join时多个表表中含有相同的字段但是未使用别名
### Error querying database.  Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'oid' in field list is ambiguous
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'oid' in field list is ambiguous
; SQL []; Column 'oid' in field list is ambiguous

2. 其他潜在的问题

  1. insert写成select
    在通常的情况下,此写法是可以正常运行的。不过在有一些公司自定义的MyBatis时(像我们公司为了支持分库分表)开发了一套自定义的mybatis组件,这个组件如果select标签里面写insert时就会报错。
  <select id="insert" resultMap="BaseResultMap">
    insert into user (id, name, password) values
   (#{id}, #{name}, #{password})
  </select>

所以大家标签和语句还是需要对应的好,否则有可能会出现不可预知的错误。

  1. select中的resultMap属性不正确

一些Eclipse或idea有根据Mapper接口自动生成xml的功能,比如作者之前安装的一个插件就会把所有的mapper中的方法生成<select>的标签的的属性是resultType而不是resultMap,这样user_id属性的值就不能得到正确的映射了。

  <select id="selectAll" resultType="com.bfbm.mybatis.entity.User">
    select user_id, name, password
    from user
  </select>

正确的方法是使用resultMap或者select语句中有_的字段都增加AS

  <select id="selectAll" resultType="com.bfbm.mybatis.entity.User">
    select user_id AS userId, name, password
    from user
  </select>
  1. #和$混用的问题
    看官方文档如何描述的http://www.mybatis.org/mybatis-3/sqlmap-xml.html#select

    可以看到官方的问题写的很清楚,使用#,MyBatis会使用PreparedStatement来进行SQL查询,可以防止SQL注入。而$更多的是用来访问配置文件中的属性的。所以大家在自己的SQL中还是应该经量使用#。
    image.png
  2. 在使用resultMap的时候,要把ID写在第一行,否则的话,就会报错。


  3. 时间戳的使用
    很多表一般会给一个create_time和update_time两个字段。很多小伙伴一般在Java中去手动设置两个字段的值。其实更好的办法是使用数据自带的时间戳函数
CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `name` varchar(255) DEFAULT NULL COMMENT '姓名',
  `password` varchar(255) DEFAULT NULL COMMENT '密码',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  1. 可以不用if choose等语句就经量少用
    有一些开发,很多代码都是从别人的Mapper文件copy过来的,很多情况下也思考为什么。比如<if> <choose>这些条件语句的使用,如果你的参数是必传的话,那么就不要写<if>,这样可以减少不必要的运算和使代码清晰。比如你们公司的DBA看见这样的语句,知道你的索引使用的对吗?
<select id="selectByXxx" parameterType="com.bfbm.mybatis.entity.Student">
    select 
  <include refid="Base_Column_List" />
  from student
    <where>
      <if test="mobile != null">
        and mobile = #{mobile,jdbcType=VARCHAR},
      </if>
      <if test="name != null">
        `and name` = #{name,jdbcType=VARCHAR},
      </if>
      <if test="userId != null">
        and user_id = #{userId,jdbcType=INTEGER},
      </if>
    </where>
  </select>

比如此例中的userId如果已经是添加了索引,而且是必填的,那么就不要写<if>啦,直接最后写user_id = #{userId}就可以了。

更多Java开发相关技术文章请关注巴分巴秒官方简书号。

相关文章

网友评论

    本文标题:MyBatis开发过程常见的坑

    本文链接:https://www.haomeiwen.com/subject/cswpcctx.html