1. 程式人生 > >幾個常見的Mybatis錯誤

幾個常見的Mybatis錯誤

本文首發於公眾號《andyqian》,期待你的關注

前言

  今天記錄幾個Mybatis常見錯誤。在使用Mybatis時,或多或少的會碰到這些問題。問題本身並不難,解決起來也非常簡單。下面會一一介紹各個問題出現的場景,發生原因以及解決方案。最後統一說說如何避免這類問題的發生。

問題一 (不存在的列)

這個問題在使用Mybatis時,屬於比較常見的低階錯誤。

問題描述:

### 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 []

主要原因

  1. Mybatis XML中的SQL語句查詢的列,不在資料庫中。

  2. 新增SQL語句中的列不在資料庫中,或列對應的值,資料型別不一致。

解決辦法: 根據專案實際情況,通常有以下三種解決辦法:

  1. 修改SQL語句中,將不存在的列從語句中去掉。

  2. 在資料庫中,新增該不存在的列。

  3. 在新增時,不要使用中文符號的``表示字串。也就是~符號對應的鍵。

     

注意事項:

  1. 刪除了資料庫中的列。在SQL語句中,沒有同步刪除該欄位的。會比較容易出現該問題。

  2. 這裡還有一個比較特殊的場景,會導致上述問題的發生。

     

以下SQL在windows環境下會顯示上述錯誤,不會進行新增操作:

insert into t_base_user(name,created_time,updated_time)values(`name`,now(),now());

但在Linux環境下,其會進行新增操作。但是 name 的值不會進行新增。

問題二 (模稜兩可的欄位)

問題描述:

### 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

主要原因:連線查詢時沒有指定共有欄位的所屬表。 也就是說。A表有name欄位,B表也有name欄位。連線查詢時查詢name時。SQL伺服器不知道返回哪個表的name欄位導致。

解決方案:明確查詢列的所屬表。

例如

表結構在文章最後,有興趣的童鞋可以測試。執行以下SQL即可還原上述問題,

select  u.id,name from t_base_user as u RIGHT JOIN
t_base_user_role as r  on u.id = r.user_id

注意事項: 將上述語句中的 u.id 修改為 id 也能正常執行。因為id不是公共欄位,只有user表才id欄位。

問題三 (不一致的接收物件)

問題描述:

Exception in thread "main" org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 9

主要原因:在介面中指定單個返回物件。但執行SQL後,有多條符合條件的資料。

解決方案
根據實際的業務場景,通常有以下兩種解決辦法:

  1. 修改介面的返回結果為集合。

  2. 修改SQL語句使其只返回一個符合條件的結果。

問題四 (重複的方法名)

描述:

Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.lang.RuntimeException: Error parsing Mapper XML. Cause: java.lang.IllegalArgumentException: Mapped Statements collection already contains value for UserDao.getUserByName

原因: 在UserDao中,有兩個同名方法getUserByName導致。

解決辦法: 重新命名其中一個方法名即可。

問題五 (不存在的屬性)

描述:

Error updating database.  Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'username' in 'com.andyqian.user.bean.User'
Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'education' in 'class com.andyqian.user.bean.User'

原因: SQL中查詢的列,在其實體物件中不存在對應的屬性。

解決辦法: 在對應的實體物件上,新增上缺失的屬性即可。

資料結構

在本文中,所有測試均使用以下表結構。SQL語句如下所示,有興趣的童鞋可以進行實驗。

create table t_base_user_role(
oid bigint(20) not null primary key auto_increment comment "",
user_id bigint(20) null comment "",
name varchar(50) null comment "",
create_time datetime null comment "",
update_time datetime null comment ""
)

CREATE TABLE `t_base_user` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(50) CHARACTER SET utf8mb4 DEFAULT NULL,
  `created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `deleted` tinyint(4) NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8

最後

  上述幾個都屬於比較常見且容易解決的問題。基本上能夠通過描述,就能定位到問題的原因。之所以能夠發生。簡答歸納為以下兩點:

  1. xml檔案中的SQL,沒有在資料庫中執行。

  2. 沒有寫單元測試。

     

由此可見,單元測試能夠為我們排除掉一些比較低階,甚至是手誤帶來的bug。也能為我們節省不少時間來解決更復雜,更有挑戰性的問題。

 

推薦閱讀:

說說Java單元測試  

CORS 跨域實踐

Git 常用命令以及常見錯誤

說說Java日誌

 

這裡寫圖片描述

 掃碼關注,一起進步

個人部落格: http://www.andyqian.com