mybatis從入門到精通(五) sqlSession API的使用
一丶簡介
SqlSession類似於mybatis對外的接口層, 它幾乎囊括了所有對外的api, 因此, 學習SqlSession的使用方法對於了解mybatis還是有必要的.
二丶配置SqlSession的環境<environment/>
<environment/> 主要包括了兩種配置, 事務管理和數據源. 這里的配置僅僅是用於學習, 實際應用一般是將事務交由Spring容器管理, 數據源一般選用成熟的數據庫連接池, 如druid, HikariCP
<environments default="development"> <environment id="development" > <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments>
三丶使用配置構建對應的SqlSessionFactory
String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); this.sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
四丶使用SqlSessionFactory獲取SqlSession
在獲取SqlSession實例之前, 需要考慮以下3件事:
事務處理:我需要在 session 使用事務或者使用自動提交功能(auto-commit)嗎?(通常意味着很多數據庫和/或 JDBC 驅動沒有事務)
連接:我需要依賴 MyBatis 獲得來自數據源的配置嗎?還是使用自己提供的配置?
執行語句:我需要 MyBatis 復用預處理語句和/或批量更新語句(包括插入和刪除)嗎?
4.1) 默認方法
@Test public void sqlSessionTest(){ // openSession() 會開啟一個事務, 它不會自動提交 // 會從當前環境配置的Datasource實例中獲取Connection // 事務隔離級別使用jdbc或數據源默認的配置 // 不會復用預處理語句, 每次都是新建一個處理語句 try(SqlSession sqlSession=this.sqlSessionFactory.openSession();){ UserMapper mapper=sqlSession.getMapper(UserMapper.class); User user=mapper.selectUser(1); sqlSession.commit(); Assert.assertTrue(user.getUserId() == 1); } }
4.2) 批量執行(自定義)
/* SqlSession openSession() //默認開啟事務, 不自動提交 SqlSession openSession(boolean autoCommit) // 可設置是否自定提交 SqlSession openSession(Connection connection) // 需要使用自定義的connection, 傳遞參數即可, 注意並未覆寫同時設置 Connection 和 autoCommit 兩者的方法,因為 MyBatis 會使用正在使用中的、設置了 Connection 的環境 SqlSession openSession(TransactionIsolationLevel level) // 事務隔離級別 SqlSession openSession(ExecutorType execType,TransactionIsolationLevel level) SqlSession openSession(ExecutorType execType) SqlSession openSession(ExecutorType execType, boolean autoCommit) SqlSession openSession(ExecutorType execType, Connection connection) Configuration getConfiguration(); ExecutorType.SIMPLE:這個執行器類型不做特殊的事情。它為每個語句的執行創建一個新的預處理語句。 ExecutorType.REUSE:這個執行器類型會復用預處理語句。 ExecutorType.BATCH:這個執行器會批量執行所有更新語句,如果 SELECT 在它們中間執行,必要時請把它們區分開來以保證行為的易讀性。 */ @Test public void sqlSessionTest2(){ SqlSession sqlSession=null; try{ /* 批量執行 DEBUG [main] - ==> Preparing: insert into user(user_id, user_name, age, country) values (?, ?, ?, ?) DEBUG [main] - ==> Parameters: 11(Integer), ttxxxxxx(String), 11(Integer), null DEBUG [main] - ==> Parameters: 12(Integer), ttxxxxx12(String), 12(Integer), null */ sqlSession=sqlSessionFactory.openSession(ExecutorType.BATCH); UserMapper userMapper=sqlSession.getMapper(UserMapper.class); User user=new User(); user.setUserId(11); user.setAge(11); user.setUserName("ttxxxxxx"); userMapper.insertUser(user); user.setUserId(12); user.setAge(12); user.setUserName("ttxxxxx12"); userMapper.insertUser(user); sqlSession.commit(); }catch (Exception e){ e.printStackTrace(); if(sqlSession!=null){ sqlSession.rollback(); } }finally { if(sqlSession!=null){ sqlSession.close(); } } }
4.3) 使用statement指定對應的方法,執行對應的sql
該方法更加原始,更接近底層. 之前使用sqlSession.getMapper(UserMapper.class)獲取對應的mapper實例, 不過是使用動態代理, 生成的代理類, 里面的方法也是使用stement指定對應的方法, 執行對應的sql
/* sqlSession執行語句的的方法 注意, statement是mapper對應的類名+方法名, 用於指定對應的sql語句 <T> T selectOne(String statement, Object parameter) <E> List<E> selectList(String statement, Object parameter) <T> Cursor<T> selectCursor(String statement, Object parameter) //返回一個游標, 可延遲獲取數據 <K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey) int insert(String statement, Object parameter) int update(String statement, Object parameter) int delete(String statement, Object parameter) */ @Test public void execSqlTest(){ try(SqlSession sqlSession=this.sqlSessionFactory.openSession()){ Cursor<User> userCursor=sqlSession.selectCursor("com.ttx.example.mapper.UserMapper.selectUser", 1); // statement 是 類名+方法名 Iterator<User> iter=userCursor.iterator(); while (iter.hasNext()){ User user=iter.next(); System.out.println(user.getUserId()+" : "+ user.getUserName()); } } }
4.4) @SqlProvider 在java代碼中編寫sql
UserSqlProvider.java
public static String buildSelectUserById(){ return new SQL(){{ SELECT("*"); FROM("user"); WHERE("user_id = #{userId}"); ORDER_BY("user_id"); }}.toString(); }
UserSqlProviderMapper.java
@ResultMap("UserMap") @SelectProvider(type = UserSqlProvider.class, method = "buildSelectUserById") User selectUserById(@Param("userId") int userId);
UserSqlProviderMapper.xml
<?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.ttx.example.mapper.UserSqlProviderMapper"> <!-- resultMap, 結果映射 --> <resultMap id="UserMap" type="com.ttx.example.entity.User"> <constructor></constructor> <!-- 用於引用構造參數, 可以省略掉 --> <id column="user_id" property="userId"/> <!-- id 元素表示的結果將是對象的標識屬性 --> <result column="user_name" property="userName"/> <result column="age" property="age"/> <result column="country" property="country"/> </resultMap> </mapper>
測試代碼
// 注解 @SelectProvider @Test public void sqlProviderTest(){ try(SqlSession sqlSession=this.sqlSessionFactory.openSession()){ UserSqlProviderMapper mapper=sqlSession.getMapper(UserSqlProviderMapper.class); User user=mapper.selectUserById(1); Assert.assertTrue(user.getUserId()==1); } }
注意事項, 使用SqlSession之后, 需要關閉連接, 上面中的代碼使用了try(){}, 會自動關閉
學習資料: