美文网首页工作生活
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