mybatis_user_guide(6) Java API
【1】SqlSessions 1)intro: 我們知道, SqlSessionFactoryBuilder 創(chuàng)建?SqlSessionFactory ,?SqlSessionFactory 創(chuàng)建?SqlSession,然后?SqlSession 獲得映射器,而映射器可以執(zhí)行 sql 語(yǔ)句映射的方法,從而達(dá)到與數(shù)據(jù)庫(kù)交互的目的;
【1.1】SqlSessionFactoryBuilder 1)SqlSessionFactoryBuilder 有五個(gè) build()方法,每一種都允許你從不同的資源中創(chuàng)建一個(gè) SqlSession 實(shí)例。 SqlSessionFactory build(InputStream inputStream) SqlSessionFactory build(InputStream inputStream, String environment) SqlSessionFactory build(InputStream inputStream, Properties properties) SqlSessionFactory build(InputStream inputStream, String env, Properties props) SqlSessionFactory build(Configuration config) 對(duì)以上代碼的分析(Analysis): Environment 決定加載哪種環(huán)境,包括數(shù)據(jù)源和事務(wù)管理器。比如:
<environments default="development"><environment id="development"><transactionManager type="JDBC">...<dataSource type="POOLED">...</environment><environment id="production"><transactionManager type="MANAGED">...<dataSource type="JNDI">...</environment> </environments> 2)?如果一個(gè)屬性存在于這些位置,那么 MyBatis 將會(huì)按找下面的順序來(lái)加載它們:
- 在 properties 元素體中指定的屬性首先被讀取,
- 從 properties 元素的類路徑 resource 或 url 指定的屬性第二個(gè)被讀取, 可以覆蓋已經(jīng) 指定的重復(fù)屬性,
- 作為方法參 數(shù)傳遞 的屬性最 后被讀 取,可以 覆蓋已 經(jīng)從 properties 元 素體和 resource/url 屬性中加載的任意重復(fù)屬性。
? ? ? 因此,最高優(yōu)先級(jí)的屬性是通過(guò)方法參數(shù)傳遞的,之后是 resource/url 屬性指定的,最 后是在 properties 元素體中指定的屬性。(干貨——屬性設(shè)置的優(yōu)先級(jí))
Conclusion) ?總結(jié)一下,前四個(gè)方法很大程度上是相同的,但是由于可以覆蓋,就允許你可選地指定 environment 和/或 properties。 這里給出一個(gè)從 mybatis-config.xml 文件創(chuàng)建 SqlSessionFactory 的示例:(干貨——從 mybatis-config.xml 文件創(chuàng)建 SqlSessionFactory 的示例)
String resource = "org/mybatis/builder/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(inputStream); 3)以上代碼用到了Resources 工具類,這個(gè)類在 org.mybatis.io 包中。Resources 類正 如其名,會(huì)幫助你從類路徑下,文件系統(tǒng)或一個(gè) web URL 加載資源文件。其方法列表如下: URL getResourceURL(String resource) URL getResourceURL(ClassLoader loader, String resource) InputStream getResourceAsStream(String resource) InputStream getResourceAsStream(ClassLoader loader, String resource) Properties getResourceAsProperties(String resource) Properties getResourceAsProperties(ClassLoader loader, String resource) Reader getResourceAsReader(String resource) Reader getResourceAsReader(ClassLoader loader, String resource) File getResourceAsFile(String resource) File getResourceAsFile(ClassLoader loader, String resource) InputStream getUrlAsStream(String urlString) Reader getUrlAsReader(String urlString) Properties getUrlAsProperties(String urlString) Class classForName(String className) 4)看個(gè)荔枝:?如何手動(dòng)配置 configuration 實(shí)例,然后將它傳遞給 build()方法來(lái)創(chuàng)建 SqlSessionFactory DataSource dataSource = BaseDataTest.createBlogDataSource(); TransactionFactory transactionFactory = new JdbcTransactionFactory();Environment environment = new Environment("development", transactionFactory, dataSource);Configuration configuration = new Configuration(environment); configuration.setLazyLoadingEnabled(true); configuration.setEnhancementEnabled(true); configuration.getTypeAliasRegistry().registerAlias(Blog.class); configuration.getTypeAliasRegistry().registerAlias(Post.class); configuration.getTypeAliasRegistry().registerAlias(Author.class); configuration.addMapper(BoundBlogMapper.class); configuration.addMapper(BoundAuthorMapper.class);SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(configuration);【1.2】SqlSessionFactory 1)intro:?SqlSessionFactory 有六個(gè)方法可以用來(lái)創(chuàng)建 SqlSession 實(shí)例。通常來(lái)說(shuō),如何決定是你 選擇下面這些方法時(shí):
- Transaction (事務(wù)):你想為 session 使用事務(wù)或者使用自動(dòng)提交(通常意味著很多 數(shù)據(jù)庫(kù)和/或 JDBC 驅(qū)動(dòng)沒(méi)有事務(wù))?
- Connection (連接):你想 MyBatis 獲得來(lái)自配置的數(shù)據(jù)源的連接還是提供你自己
- Execution (執(zhí)行):你想 MyBatis 復(fù)用預(yù)處理語(yǔ)句和/或批量更新語(yǔ)句(包括插入和 刪除)?
2)?重載的 openSession()方法簽名設(shè)置允許你選擇這些可選中的任何一個(gè)組合。 SqlSession openSession() SqlSession openSession(boolean autoCommit) SqlSession openSession(Connection 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(); 對(duì)以上代碼的分析(Analysis):
A1)默認(rèn)的 openSession()方法沒(méi)有參數(shù),它會(huì)創(chuàng)建有如下特性的 SqlSession:
- 會(huì)開(kāi)啟一個(gè)事務(wù)(也就是不自動(dòng)提交)
- 連接對(duì)象會(huì)從由活動(dòng)環(huán)境配置的數(shù)據(jù)源實(shí)例中得到。
- 事務(wù)隔離級(jí)別將會(huì)使用驅(qū)動(dòng)或數(shù)據(jù)源的默認(rèn)設(shè)置。
- 預(yù)處理語(yǔ)句不會(huì)被復(fù)用,也不會(huì)批量處理更新。
- ExecutorType.SIMPLE: 這個(gè)執(zhí)行器類型不做特殊的事情。它為每個(gè)語(yǔ)句的執(zhí)行創(chuàng)建一個(gè)新的預(yù)處理語(yǔ)句。
- ExecutorType.REUSE: 這個(gè)執(zhí)行器類型會(huì)復(fù)用預(yù)處理語(yǔ)句。
- ExecutorType.BATCH: 這個(gè)執(zhí)行器會(huì)批量執(zhí)行所有更新語(yǔ)句,如果 SELECT 在它們中間執(zhí)行還會(huì)標(biāo)定它們是 必須的,來(lái)保證一個(gè)簡(jiǎn)單并易于理解的行為。
【1.3】SqlSession 1)intro:?在 SqlSession 類中有超過(guò) 20 個(gè)方法,所以將它們分開(kāi)成易于理解的組合。
【1.3.1】語(yǔ)句執(zhí)行方法 1)intro:?這些方法被用來(lái)執(zhí)行定義在 SQL 映射的 XML 文件中的 SELECT,INSERT,UPDA E T 和 DELETE 語(yǔ)句。它們都會(huì)自行解釋,每一句都使用語(yǔ)句的 ID 屬性和參數(shù)對(duì)象,參數(shù)可以 是原生類型(自動(dòng)裝箱或包裝類) ,JavaBean,POJO 或 Map。(干貨——sql 語(yǔ)句需要參數(shù)的case) <T> T selectOne(String statement, Object parameter) <E> List<E> selectList(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) 對(duì)以上代碼的分析(Analysis):?selectOne 和 selectList 的不同僅僅是 selectOne 必須返回一個(gè)對(duì)象。 如果多余一個(gè), 或者 沒(méi)有返回 (或返回了 null) 那么就會(huì)拋出異常。 , 如果你不知道需要多少對(duì)象, 使用 selectList。
2)如果你想檢查一個(gè)對(duì)象是否存在,那么最好返回統(tǒng)計(jì)數(shù)(0 或 1) 。因?yàn)椴⒉皇撬姓Z(yǔ)句都需 要參數(shù),這些方法都是有不同重載版本的,它們可以不需要參數(shù)對(duì)象。(干貨——sql 語(yǔ)句不需要參數(shù)的case) <T> T selectOne(String statement) <E> List<E> selectList(String statement) <K,V> Map<K,V> selectMap(String statement, String mapKey) int insert(String statement) int update(String statement) int delete(String statement) 3)最后,還有查詢方法的三個(gè)高級(jí)版本:它們?cè)试S你限制返回行數(shù)的范圍,或者提供自定 義結(jié)果控制邏輯,這通常用于大量的數(shù)據(jù)集合。 <E> List<E> selectList (String statement, Object parameter, RowBounds rowBounds) <K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowbounds) void select (String statement, Object parameter, ResultHandler<T> handler) void select (String statement, Object parameter, RowBounds rowBounds, ResultHandler<T> handler) 對(duì)以上代碼的分析(Analysis): A1)RowBounds 參數(shù)會(huì)告訴 MyBatis 略過(guò)指定數(shù)量的記錄,還有限制返回結(jié)果的數(shù)量。 RowBounds 類有一個(gè)構(gòu)造方法來(lái)接收 offset 和 limit,否則是不可改變的。(干貨——引入 RowBounds 參數(shù)) int offset = 100; int limit = 25; RowBounds rowBounds = new RowBounds(offset, limit); A2)?ResultHandler 參數(shù)允許你按你喜歡的方式處理每一行。你可以將它添加到 List 中,創(chuàng) 建 Map, 或拋出每個(gè)結(jié)果而不是只保留總計(jì)。 Set 你可以使用 ResultHandler 做很多漂亮的事, 那就是 MyBatis 內(nèi)部創(chuàng)建結(jié)果集列表。它的接口很簡(jiǎn)單。 package org.apache.ibatis.session; public interface ResultHandler<T> {void handleResult(ResultContext<? extends T> context); }
【1.3.2】Batch update statement Flush Method
1)intro: There is method for flushing(executing) batch update statements that stored in a JDBC driver class at any timing. This method can be used when you use the?ExecutorType.BATCH?as?ExecutorType.
List<BatchResult> flushStatements()【1.3.3.】?事務(wù)控制方法
1)intro: 控制事務(wù)范圍有四個(gè)方法。 當(dāng)然, 如果你已經(jīng)選擇了自動(dòng)提交或你正在使用外部事務(wù)管 理器,這就沒(méi)有任何效果了。然而,如果你正在使用 JDBC 事務(wù)管理員,由 Connection 實(shí) 例來(lái)控制,那么這四個(gè)方法就會(huì)派上用場(chǎng):
void commit() void commit(boolean force) void rollback() void rollback(boolean force) Attention)?默認(rèn)情況下 MyBatis 不會(huì)自動(dòng)提交事務(wù), 除非它偵測(cè)到有插入, 更新或刪除操作改變了 數(shù)據(jù)庫(kù)。如果你已經(jīng)做出了一些改變而沒(méi)有使用這些方法,那么你可以傳遞 true 到 commit 和 rollback 方法來(lái)保證它會(huì)被提交(注意,你不能在自動(dòng)提交模式下強(qiáng)制 session,或者使用 了外部事務(wù)管理器時(shí)) 。很多時(shí)候你不用調(diào)用 rollback(),因?yàn)槿绻銢](méi)有調(diào)用 commit 時(shí) MyBatis 會(huì)替你完成。然而,如果你需要更多對(duì)多提交和回滾都可能的 session 的細(xì)粒度控 制,你可以使用回滾選擇來(lái)使它成為可能。(干貨——?默認(rèn)情況下 MyBatis 不會(huì)自動(dòng)提交事務(wù), 除非它偵測(cè)到有插入, 更新或刪除操作改變了 數(shù)據(jù)庫(kù)。)【1.3.4】清理 Session 級(jí)的緩存 void clearCache() 對(duì)以上代碼的分析(Analysis):?SqlSession 實(shí)例有一個(gè)本地緩存在執(zhí)行 update,commit,rollback 和 close 時(shí)被清理。要 明確地關(guān)閉它(獲取打算做更多的工作) ,你可以調(diào)用 clearCache()。
【1.3.5】?確保 SqlSession 被關(guān)閉 1)intro: void close()
2)你必須保證的最重要的事情是: 你要關(guān)閉所打開(kāi)的任何 session。保證做到這點(diǎn)的最佳方 式是下面的工作模式:(干貨——關(guān)閉打開(kāi)的任何 Session)
SqlSession session = sqlSessionFactory.openSession(); try {// following 3 lines pseudocod for "doing some work"session.insert(...);session.update(...);session.delete(...);session.commit(); } finally {session.close(); }2.1)還有,如果你正在使用jdk 1.7以上的版本還有MyBatis 3.2以上的版本,你可以使用try-with-resources語(yǔ)句:(干貨——使用帶資源的 try 語(yǔ)句)
try (SqlSession session = sqlSessionFactory.openSession()) {// following 3 lines pseudocode for "doing some work"session.insert(...);session.update(...);session.delete(...);session.commit(); }Attention)就像 SqlSessionFactory,你可以通過(guò)調(diào)用 getConfiguration()方法獲得 SqlSession 使用的 Configuration 實(shí)例
Configuration getConfiguration()【1.4】使用映射器(推薦使用映射器和數(shù)據(jù)庫(kù)交互) <T> T getMapper(Class<T> type)
1)intro:上述的各個(gè) insert,update,delete 和 select 方法都很強(qiáng)大,但也有些繁瑣,沒(méi)有類型安 全,對(duì)于你的 IDE 也沒(méi)有幫助,還有可能的單元測(cè)試。在上面的入門(mén)章節(jié)中我們已經(jīng)看到 了一個(gè)使用映射器的示例。
2)因此, 一個(gè)更通用的方式來(lái)執(zhí)行映射語(yǔ)句是使用映射器類。 一個(gè)映射器類就是一個(gè)簡(jiǎn)單 的接口,其中的方法定義匹配于 SqlSession 方法。下面的示例展示了一些方法簽名和它們是 如何映射到 SqlSession 的。
public interface AuthorMapper {// (Author) selectOne("selectAuthor",5);Author selectAuthor(int id); // (List<Author>) selectList(“selectAuthors”)List<Author> selectAuthors();// (Map<Integer,Author>) selectMap("selectAuthors", "id")@MapKey("id")Map<Integer, Author> selectAuthors();// insert("insertAuthor", author)int insertAuthor(Author author);// updateAuthor("updateAuthor", author)int updateAuthor(Author author);// delete("deleteAuthor",5)int deleteAuthor(int id); }【1.4.1】映射器注解 1)intro:?注解提供了一種簡(jiǎn)單的方式來(lái)實(shí)現(xiàn)簡(jiǎn)單映射語(yǔ)句,而 不會(huì)引入大量的開(kāi)銷(xiāo);
【1.4.2】 映射聲明樣例 ?荔枝1)intro:?這個(gè)例子展示了如何使用 @SelectKey 注解來(lái)在插入前讀取數(shù)據(jù)庫(kù)序列的值: @Insert("insert into table3 (id, name) values(#{nameId}, #{name})") @SelectKey(statement="call next value for TestSequence", keyProperty="nameId", before=true, resultType=int.class) int insertTable3(Name name); 荔枝2)這個(gè)例子展示了如何使用 @SelectKey 注解來(lái)在插入后讀取數(shù)據(jù)庫(kù)識(shí)別列的值: @Insert("insert into table2 (name) values(#{name})") @SelectKey(statement="call identity()", keyProperty="nameId", before=false, resultType=int.class) int insertTable2(Name name);
荔枝3)This example shows using the?@Flush?annotation to call the?SqlSession#flushStatements():
@Flush List<BatchResult> flush();荔枝4)These examples show how to name a ResultMap by specifying id attribute of @Results annotation.
@Results(id = "userResult", value = {@Result(property = "id", column = "uid", id = true),@Result(property = "firstName", column = "first_name"),@Result(property = "lastName", column = "last_name") }) @Select("select * from users where id = #{id}") User getUserById(Integer id);@Results(id = "companyResults") @ConstructorArgs({@Arg(property = "id", column = "cid", id = true),@Arg(property = "name", column = "name") }) @Select("select * from company where id = #{id}") Company getCompanyById(Integer id);荔枝5)This example shows solo parameter using the Sql Provider annotation:
@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName") List<User> getUsersByName(String name);class UserSqlBuilder {public String buildGetUsersByName(final String name) {return new SQL(){{SELECT("*");FROM("users");if (name != null) {WHERE("name like #{value} || '%'");}ORDER_BY("id");}}.toString();} }荔枝6)This example shows multiple parameters using the Sql Provider annotation:
@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName") List<User> getUsersByName(@Param("name") String name, @Param("orderByColumn") String orderByColumn);class UserSqlBuilder {// If not use @Param, you should be define same arguments with mapper methodpublic String buildGetUsersByName(final String name, final String orderByColumn) {return new SQL(){{SELECT("*");FROM("users");WHERE("name like #{name} || '%'");ORDER_BY(orderByColumn);}}.toString();}// If use @Param, you can define only arguments to be usedpublic String buildGetUsersByName(@Param("orderByColumn") final String orderByColumn) {return new SQL(){{SELECT("*");FROM("users");WHERE("name like #{name} || '%'");ORDER_BY(orderByColumn);}}.toString();} }總結(jié)
以上是生活随笔為你收集整理的mybatis_user_guide(6) Java API的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 魔方高级玩法 这样玩真的是高级还原了
- 下一篇: mybatis_user_guide(7