MyBatis开发过程常见的坑

之所以把写关于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时就会报错。
  

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

  1. select中的resultMap属性不正确

一些Eclipse或idea有根据Mapper接口自动生成xml的功能,比如作者之前安装的一个插件就会把所有的mapper中的方法生成 select user_id, name, password from user

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

  
  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过来的,很多情况下也思考为什么。比如 这些条件语句的使用,如果你的参数是必传的话,那么就不要写,这样可以减少不必要的运算和使代码清晰。比如你们公司的DBA看见这样的语句,知道你的索引使用的对吗?

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

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

你可能感兴趣的:(MyBatis开发过程常见的坑)