幾個常見的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 []
主要原因:
-
Mybatis XML中的SQL語句查詢的列,不在資料庫中。
-
新增SQL語句中的列不在資料庫中,或列對應的值,資料型別不一致。
解決辦法: 根據專案實際情況,通常有以下三種解決辦法:
-
修改SQL語句中,將不存在的列從語句中去掉。
-
在資料庫中,新增該不存在的列。
-
在新增時,不要使用中文符號的``表示字串。也就是~符號對應的鍵。
注意事項:
-
刪除了資料庫中的列。在SQL語句中,沒有同步刪除該欄位的。會比較容易出現該問題。
-
這裡還有一個比較特殊的場景,會導致上述問題的發生。
以下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後,有多條符合條件的資料。
解決方案:
根據實際的業務場景,通常有以下兩種解決辦法:
-
修改介面的返回結果為集合。
-
修改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
最後
上述幾個都屬於比較常見且容易解決的問題。基本上能夠通過描述,就能定位到問題的原因。之所以能夠發生。簡答歸納為以下兩點:
-
xml檔案中的SQL,沒有在資料庫中執行。
-
沒有寫單元測試。
由此可見,單元測試能夠為我們排除掉一些比較低階,甚至是手誤帶來的bug。也能為我們節省不少時間來解決更復雜,更有挑戰性的問題。
推薦閱讀:
掃碼關注,一起進步
個人部落格: http://www.andyqian.com