昨天寫了一個 mybatis 的helloWord,雖然能跑起來,但是那種方式還是會存在一些問題。
- 每次進行增刪改查,方法裏傳入的 sql 唯一標識id 就好長一串。
- 再者就是傳入的查詢入參類型是一個object,也就是什麼都可以往裏面傳,如果傳"a",肯定查不出來數據。
那麼,mybatis 還提供了另一種更高級的使用方式:接口式編程,這也是後續開發中主要使用的方式。
我們可以使用一個接口來描述一個給定的sql語句,它的參數和返回值。
一、接口與配置文件動態綁定
在測試平臺項目下的 dao 層新建一個接口com.pingguo.bloomtest.dao.UserMapper
:
package com.pingguo.bloomtest.dao;
import com.pingguo.bloomtest.pojo.User;
public interface UserMapper {
User getUserById(Integer id);
}
定義好了接口,裏面有一個方法getUserById
,顧名思義就是通過id查詢數據,返回 User 對象。
按照以往,定義好了接口,接下來還需要定義出接口的實現類。
但是現在這個接口就是用來查詢出 user 表記錄數據並封裝成 User 對象返回,而在之前定義好的 sql 映射文件UserMapper.xml
裏,<select>
標籤裏的 sql 也是做這個事情。
<mapper namespace="org.mybatis.example.UserMapper">
<select id="selectUser" resultType="com.pingguo.bloomtest.pojo.User">
select * from user where id = #{id}
</select>
</mapper>
那麼,現在就可以把接口與配置文件進行動態綁定:
namespace
:不要隨便寫了,對應接口的全類名id
: 對應接口裏的方法名
改完之後應該是這樣了:
<mapper namespace="com.pingguo.bloomtest.dao.UserMapper">
<select id="getUserById" resultType="com.pingguo.bloomtest.pojo.User">
select * from user where id = #{id}
</select>
</mapper>
再寫一個測試方法查詢一下:
@Test
void test2() throws IOException {
// 根據配置文件,創建一個 SqlSessionFactory 對象
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
// 獲取 SqlSession 實例,可以執行已經映射的 sql 語句
SqlSession session = sqlSessionFactory.openSession();
// 獲取接口的實現類對象
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = userMapper.getUserById(4);
System.out.println(user);
}
getMapper
方法可以獲取到這個接口的實現對象。
第一步因爲要經常使用,所以抽出去了:
public SqlSessionFactory getSqlSessionFactory() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
return new SqlSessionFactoryBuilder().build(inputStream);
}
執行測試,查詢成功。
那麼問題來了,這個接口還沒寫實現類,那麼
`UserMapper userMapper = session.getMapper(UserMapper.class);`
獲取到的是什麼?
加個打印System.out.println(userMapper.getClass());
看下輸出。
原來是個代理對象。
所以說,只要把接口和 xml文件進行動態綁定,mybatis 會爲接口自動創建一個代理對象,然後由代理對象去執行增刪改查方法。
二、關於 SqlSession
SqlSession
代表和數據庫的一次會話。用完必須關閉,我上面的事例應該加上session.close();
。
另外,SqlSession
也是非線程安全。
- 線程安全:就是在多線程環境下也不會出現數據不一致,
- 非線程安全: 就有可能出現數據不一致的情況。
所以不能像這樣寫:
如果這樣寫,可能會出現A線程 用了 SqlSession,然後關掉了,但是線程B 還在用。所以每次使用都應該去獲取新的對象,不要放在成員變量中。