目錄
一、遇到的問題
二、分析思路
1、映射文件
2、測試類
三、解決方案
一、遇到的問題
前幾日,有個工作不久的同事找我?guī)退鉀Q一個 Mybatis 的問題。他寫了一個增刪改查,但是在啟動程序的時候報錯:Invalid bound statement (not found) 。他試圖解決該異常,花了一個小時還是沒有解決,所以向我求助。所謂當局者迷,我?guī)退崂砹艘幌麻_發(fā)邏輯,幾分鐘后他發(fā)現(xiàn)了問題,并解決了該異常。剛工作兩三年的開發(fā)者特別容易碰到該異常,但是只要理清思路,就很容解決問題。我將分析問題的思路記錄一下,希望能幫到你。
二、分析思路
Mybatis 開發(fā)有兩種方式,一種是原始 Dao 開發(fā)方式,另一種是 Mapper 動態(tài)代理開發(fā)方式。在開發(fā)項目時,我們會用 Mapper 動態(tài)代理開發(fā)方式,動態(tài)代理會自動幫我們生成 Mapper 的代理類,將細節(jié)封裝起來。但是,在分析問題的時候,我們用原始 Dao 開發(fā)方式,可以讓我們了解到 statement 綁定映射文件的細節(jié)。
下面使用原始 Dao 的開發(fā)方式演示一下 statement 是如何綁定映射文件中的 Sql 語句的。
1、映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.test.mapper.UserMapper">
<!-- 查詢所有的用戶名 -->
<select id="findUserNameList" resultType="java.lang.String">
select user_name userName from user
</select>
</mapper>
2、測試類
public class Test {
//會話工廠
private SqlSessionFactory sqlSessionFactory;
@Before
public void createSqlSessionFactory() throws IOException {
// 配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 使用SqlSessionFactoryBuilder從xml配置文件中創(chuàng)建SqlSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
}
// 查詢所有的用戶名
@Test
public void testFindUserNameById() {
// 數(shù)據(jù)庫會話實例
SqlSession sqlSession = null;
try {
// 創(chuàng)建數(shù)據(jù)庫會話實例sqlSession
sqlSession = sqlSessionFactory.openSession();
// 查詢所有的用戶名
List<String> list = sqlSession.selectList("com.test.mapper.UserMapper.findUserNameById");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
}
在上面的測試中,使用了 sqlSession 的 selectList 方法,中間的參數(shù)就是 statement 。該參數(shù)用來確定映射文件中的 Sql 語句,換句話說就是用這個 statement 綁定映射文件中的 Sql 語句。
該參數(shù)是用映射文件中的 namespace 和 select 標簽的 id 組合而成的,在項目是唯一的。示例中映射文件的 namespace 是:com.test.mapper.UserMapper,select 標簽的 id 是:indUserNameById ,所以組合起來的 statement 是 com.test.mapper.UserMapper.findUserNameById
如果 statement 寫錯了,就會導致找不到映射文件中的 Sql 語句,就會報 Invalid bound statement (not found) 。所以造成該異常的原因是 statement 和 Sql 語句不匹配。
在實際項目會使用 Mapper 動態(tài)代理的開發(fā)方式,自動生成 mapper 接口的實現(xiàn)類,就更容易出現(xiàn)該異常了。
三、解決方案
既然知道了造成該異常的原因,就容易解決了,如果通過 statement 找不到映射文件中的 Sql 就會報錯誤:Invalid bound statement (not found) 。在項目中一般都是使用 Mapper 動態(tài)代理,所以我們要解決的也是動態(tài)代理的問題。先說一下 Mapper 動態(tài)代理的實現(xiàn)原理,看完之后你就知道應該怎么解決該異常了。
Mapper 動態(tài)代理只需要開發(fā)定義 Mapper 接口,Mybatis 會根據(jù)接口創(chuàng)建動態(tài)代理對象。使用該種方式開發(fā),需要遵守一定的開發(fā)規(guī)范,規(guī)范如下 4 點:
- Mapper.xml 文件中的 namespace 與 mapper 接口的類路徑相同。
- Mapper 接口方法名和 Mapper.xml 中定義的每個 statement 的 id 相同
- Mapper 接口方法的輸入?yún)?shù)類型和 mapper.xml 中定義的每個 Sql 的 parameterType 的類型相同
- Mapper 接口方法的輸出參數(shù)類型和 mapper.xml 中定義的每個 Sql 的 resultType 的類型相同?
所以,我們在使用 Mapper 動態(tài)代理遇到該異常,就是要檢查是否遵守開發(fā)規(guī)范,因為粗心或單詞寫錯了,容易導致程序報錯。
我列了幾個檢查步驟,你跟著步驟檢查一下,肯定能找到問題的所在之處。步驟如下 7 點:文章來源:http://www.zghlxwxcb.cn/news/detail-428608.html
- 檢查 target 目錄中有沒有 Mybatis 的映射文件
- 檢查 mybatis.mapper-locations 配置,該配置是把 mapper 的位置告訴 Mybatis 。默認是mapper-locations: classpath*:/mapper/**/*.xml
- 檢查映射文件是不是放在 resources/mapper 目錄中
- 檢查映射文件中的 namespace 與 mapper 接口的類路徑是不是一樣
- 檢查映射文件中的 statement 是不是和 Mapper 接口的方法名一樣
- 檢查映射文件中的 statement 的 parameterType 和 resultType 是不是和 Mapper 接口的方法中的入?yún)⒑统鰠⒁粯?/li>
- 如果你使用 Idea 開發(fā),檢查一下 resources 目錄,在該目錄下創(chuàng)建下級目錄是不能一次性創(chuàng)建的,要創(chuàng)建完成一個目錄后再創(chuàng)建另外的下級目錄
另外,如果你遇到過該異常,并且遇到的錯誤不在上述之中。不妨在留言區(qū)提出,大家一起討論一下,給后來者提個醒,避免遇到坑。文章來源地址http://www.zghlxwxcb.cn/news/detail-428608.html
到了這里,關于Invalid bound statement (not found)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!