頭圖: www.zcool.com.cn/work/ZNTE1M…html
框架的好處java
框架是一個半成品,已經對基礎的代碼進行了封裝並提供相應的 API,開發者在 使用框架是直接調用封裝好的 API 能夠省去不少代碼編寫,從而提升工做效率和開發速度mysql
學習目標git
掌握:程序員
Mybatis的基本使用、Java 日誌處理框架、Mybatis 配置完善 、SqlSession 經常使用 API 、Mapper 動態代理 、動態 SQL 、Mybatis 緩存 、Mybatis 多表關聯查詢、Mybatis 註解的使用 、Mybatis Generator 工具的使用、PageHelper 分頁插件、Mybatis 與 Servlet 整合web
MyBatis框架的優勢和缺點算法
對象關係映射,它的做用是在關係型數據庫和對象之間做一個映射處理。項目中的業務實體有兩種表現形式:對象和關係數據,即在內存中表現爲對象,在數據庫中表現爲關係數據。spring
JDBC 的缺點:須要手動的完成面向對象的 Java 語言、面向關係的數據庫之間數據的轉換,代碼繁瑣,影響了開發效率。sql
ORM:在面向對象的java語言中,面向關係的數據庫之間數據的轉換是必須的,數據庫中的數據是不能直接拿來使用,須要轉換成須要的對象來使用,可是每次在開發時須要先創建數據庫而後在對數據庫中的數據轉成咱們能夠操做的對象;所以ORM就至關於轉換的橋樑,開發者不須要和sql語句打交道了。數據庫
ORM將數據庫映射成對象
MyBatis 是一款優秀的持久層框架,它支持定製化 SQL、存儲過程以及高級映射。MyBatis 避免了幾乎全部的 JDBC 代碼和手動設置參數以及獲取結果集。MyBatis 可使用簡單的 XML 或註解來配置和映射原生信息,將接口和 Java 的 POJOs(Plain OrdinaryJava Object,普通的 Java 對象)映射成數據庫中的記錄。MyBatis是一個半自動ORM框架,其本質是對JDBC的封裝。使用MyBatis重點須要程序員編寫 SQL 命令,不須要寫一行 JDBC 代碼。
持久層框架:優化了對數據庫的訪問速度,減小了對數據庫中的訪問頻率,將數據庫中的關係數據經過對象關係映射成對象,這時對象中的存放的就是數據庫中的內容(若是須要執行則存放到內存中),當程序須要某一個對象的屬性執行時,無需再從數據庫中訪問且作轉換就能夠獲取。
與 Hibernate 的比較:
Hibernate 是一個全自動的 ORM 框架。由於 Hibernate 建立了 Java 對象和數據庫表之間的完整映射,能夠徹底以面向對象的思想來操做數據庫,程序員不須要手寫 SQL 語句。而 MyBatis 中還須要手寫 SQL 語句,因此是半自動化的,工做量要大於 Hibernate。爲何半自動化的 Mybatis 自動化的 Hibernate 受歡迎?
MyBatis 須要手寫 SQL 語句,因此工做量要大於 Hibernate。可是也正是因爲自定義SQL 語句,因此其靈活性、可優化性就超過了 Hibernate。MyBatis 將手寫 SQL 語句的工做丟給開發者,能夠更加精確的定義 SQL,更加靈活, 也便於優化性能。完成一樣功能的兩條 SQL 語句的性能可能相差十幾倍到幾十倍,在高併發、快響應要求下的互聯網系統中,對性能的影響更明顯。MyBatis 對存儲過程可提供很好的支持。
SqlSessionFactoryBuilder
SqlSessionFactoryBuilder的做用是用來建立 SqlSessionFactory 對象。當 SqlSessionFactory 對象被建立後,SqlSessionFactoryBuilder 就失去了做用,因此它只能存在於建立 SqlSessionFactory 的方法中,而不要讓其長期存在。所以 SqlSessionFactoryBuilder 實例的最佳做用域是方法做用域。
SqlSessionFactory
能夠被認爲是一個數據庫鏈接池,它的做用是建立 SqlSession接口對象。一旦建立了SqlSessionFactory,就要長期保存它,直至再也不使用 MyBatis 應用,因此能夠認爲SqlSessionFactory 的生命週期就等同於 MyBatis 的應用週期。因爲 SqlSessionFactory是 一 個 對 數 據 庫 的 連 接 池 , 所 以 它 佔 據 着 數 據 庫 的 連 接 資 源 。 如 果 創 建 多 個SqlSessionFactory,那麼就存在多個數據庫鏈接池,這樣不利於對數據庫資源的控制,也會致使數據庫鏈接資源被消耗光,出現系統宕機等狀況,因此儘可能避免發生這樣的狀況。所以 SqlSessionFactory 是一個單例,讓它在應用中被共享。
SqlSession
若是說 SqlSessionFactory 至關於數據庫鏈接池,那麼 SqlSession 就至關於一個數據庫鏈接(Connection 對象),你能夠在一個事務裏面執行多條 SQL,而後經過它的commit、rollback 方法提交或者回滾事務。SqlSession 應該存活在一個業務請求中,處理完整個請求後,應該關閉這條鏈接,讓它歸還給 SqlSessionFactory,不然數據庫資源就很快被耗費精光,系統就會癱瘓,因此用 try...catch...finally... 語句來保證其正確關閉
Mapper
映射器。由一個 Java 接口和 XML 文件(或者註解構成),須要給出對應的 SQL 和映射規則,負責發送 SQL 去執行並返回結果。因爲 SqlSession 的關閉,它的數據庫鏈接資源也會消失,因此它的生命週期應該小於等於 SqlSession 的生命週期。Mapper 表明的是一個請求中的業務處理,因此它應該在一個請求中,一旦處理完了相關的業務,就應該廢棄它。
全局配置文件和映射配置文件:若是說全局配置聞不見是鏈接數據庫的配置已經環境的設置,那麼映射配置文件就是編寫sql語句的(JDBC是將sql語句和代碼寫在一塊兒而後進行CRUD,Mybatis則是進行了節偶,是功能代碼具備可用性,開發簡單。
全局配置文件的名稱是自定義的,在 JavaProject 項目中須要放到 src 目錄下。全局配置文件的做用是完成一些全局性的配置,如:對 Mybatis 框架的設置、別名設置、環境設置、指定映射配置文件等相關配置。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
</configuration>
複製代碼
properties 標籤中容許內部定義屬性,也能夠是外部的properties 文件定義屬性。不管是內部定義仍是外部定義,均可以使用${name}獲取值。
配置文件中內部定義
<properties>
<property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="jdbc.url" value="jdbc:mysql://localhost:3306/bjsxt"/>
<property name="jdbc.username" value="root"/>
<property name="jdbc.password" value="root"/>
</properties>
複製代碼
配置文件中外部定義
<properties resource="db.properties"></properties>
複製代碼
setting 標籤的配置是配置 MyBatis 框架運行時的一些行爲的,例如緩存、延遲加載、結果集控制、執行器、分頁設置、命名規則等一系列控制性參數,其全部的 setting 配置都放在父標籤 settings 標籤中(也能夠不用配置)。
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
複製代碼
類型別名可爲 Java 類型設置一個縮寫名字。
<typeAliases>
<typeAlias alias="user" type="com.bjsxt.pojo.User" />
</typeAliases>
複製代碼
也能夠指定一個包名,MyBatis 會在包名下面搜索須要的 Java Bean
<typeAliases>
<package name="com.bjsxt.pojo"/>
</typeAliases>
複製代碼
配置鏈接數據庫的環境,能夠配置多個環境,好比:開發、測試、發佈產品的環境
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
複製代碼
transactionManager 節點
事務處理器。在Mybatis中有兩種事務管理器,也就是type = JDBC或type = MANAGED
JDBC:這個配置直接使用了 JDBC 的提交和回滾事務,它依賴從數據源得到的鏈接來管理事務做用域
MANAGED:在Mybatis中不作事務處理,在JavaEE開發的標準中根據開發框架獲取事務
配置數據鏈接源(JDBC鏈接對象的資源,獲取數據鏈接池)
指定映射配置文件
使用相對類路徑指定映射配置文件
<mappers>
<mapper resource="com/bjsxt/mapper/UserMapper.xml"/>
</mappers>
複製代碼
使用 filter:///協議指定映射配置文件
<mappers>
<mapper url="file:///D:\code\mybatis\src\com\bjsxt\mapper\UserMapper.xml"/>
</mappers>
複製代碼
指定映射接口
<mappers>
<mapper class="com.bjsxt.mapper.UserMapper"/>
</mappers>
複製代碼
經過包名指定映射接口(指定映射文件)
<mappers>
<package name="com.bjsxt.mapper"/>
</mappers>
複製代碼
映射配置文件主要是用來編寫 sql 語句的,結果集的映射關係的指定,以及緩存的一些配置等等。
<?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.bjsxt.mapper.UserMapper">
</mapper>
複製代碼
mybatis中能夠爲每一個映射文件起一個惟一的命名空間(namespace),只要這個命名空間的id是惟一,即便不一樣的映射文件的sql語句id同樣也不會產生衝突
<resultMap id="userMapper" type="com.bjsxt.pojo.User">
<id property="userid" column="user_id"/>
<result property="username" column="user_name"/>
</resultMap>
複製代碼
指定查詢結果集與對象的映射關係的標籤
type:類的徹底名, 或者一個類型別名,能夠理解爲數據庫中的錶轉換成了一個對象,該對象裏面的屬性即便數據庫中表的字段名稱,CRUD該表時,將字段對應的數據填充到改對象中。
id:惟一標識。在進行業務處理時,該標籤指定程序獲取執行sql語句,在一個映射文件中是惟一的
指定主鍵中的值,用於標識一個結果映射。
property: 該屬性值至關於在操做sql語句時起的別名
<select id="selectUser" parameterType="int" resultType="u">
select * from users where userid = #{userid}
</select>
複製代碼
parameterType:指定參數類型。該屬性是可選屬性。由於 MyBatis 能夠經過類型處理器(TypeHandler)推斷出具體傳入語句的參數。
resultType:指望從這條語句中返回結果的類全名或別名。
resultMap:使用 resultMap 標籤來處理結果集映射。
在沒有聯網的狀況下,若是讓 dtd 約束繼續起做用,而且出現標籤提示,能夠經過引入本地 dtd 文件來實現,將下載的 dtd 拷貝到本地的一個目錄下
Idea 操做路徑:File---Settings---Languages & Frameworks。其中 URI 複製 dtd 的網絡地址便可。File 選擇 dtd 文件在本地的地址
注意:在 MyBatis 的核心 jar 包中就提供了 mybatis-3-config.dtd
public class Users {
private int userid;
private String username;
private String usresex;
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUsresex() {
return usresex;
}
public void setUsresex(String usresex) {
this.usresex = usresex;
}
}
複製代碼
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/bjsxt
jdbc.username=root
jdbc.password=root
複製代碼
在這裏使用了外部定義的properties屬性
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 引入 properties 文件 -->
<properties resource="db.properties"/>
<!-- 環境的配置 -->
<environments default="development">
<environment id="development">
<!-- 配置事務 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置數據源 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- 引入映射配置文件 -->
<mappers>
<!-- 使用相對路徑方式引入,不一樣的實體類有不一樣的映射配置文件,若是實體類比較多則比較麻煩 -->
<mapper resource="com/bjsxt/mapper/UsersMapper.xml"/>
</mappers>
</configuration>
複製代碼
<?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.bjsxt.mapper.UserMapper">
<!-- 查詢全部用戶 -->
<select id="selectUsersAll" resultType="com.bjsxt.pojo.Users">
select * from users
</select>
</mapper>
複製代碼
public interface UsersDao {
List<Users> selectUsersAll()throws IOException;
}
複製代碼
public class UsersDaoImpl implements UsersDao {
/** * 查詢全部用戶 * @return */
@Override
public List<Users> selectUsersAll()throws IOException {
// 建立 SqlSessionFactory 對象
InputStream inputStream = Resources.getResourceAsStream("mybatis-cfg.xml");
SqlSessionFactory sqlSessionFacotry = new SqlSessionFactoryBuilder().build(inputStream);
// 獲取 SqlSession 對象
SqlSession sqlSession = sqlSessionFacotry.openSession();
// 經過 SqlSession 對象下的 API 完成對數據庫的操做
List<Users> list = sqlSession.selectList("com.bjsxt.mapper.UserMapper.selectUsersAll");
// 關閉 SqlSession 對象
sqlSession.close();
return list;
}
}
複製代碼
在映射配置文件中向 SQL 語句中綁定參數的語法結構爲#{ }和${ }。
#{}和${}的區別(面)
#{ }: 解析爲一個 JDBC 預編譯語句(PreparedStatement)的參數標記符佔位符 ?。使 用該方式可避免 SQL 注入
** { } 在預編譯以前已經被變量替換了,這會存在 SQL 注入問題。
ThreadLocal 提供了線程內存儲變量的能力,這些變量不一樣之處在於每個線程讀取的變量是對應的互相獨立的。經過 get 和 set 方法就能夠獲得當前線程對應的值
若是多個 DML 操做屬於一個事務,由於 commit()和 rollback()都是由 SqlSession 完成的,因此必須保證使用一個 SqlSession。可是多個不一樣的 DML 操做可能在不一樣類的不一樣方法中,每一個方法中要單獨的獲取 SqlSession。好比商城下訂單時,其實涉及商品庫存變化、訂單添加、訂單明細添加、付款、日誌添加等多個 DML 操做,分佈在不一樣類中。如何在多個 DML 操做之間使用同一個 SqlSession 呢,可使用 ThreadLocal 來存儲。保證一個線程中的操做使用的都是一個 SqlSession。
在 Web 項目中用戶的每次請求會啓動一個新的線程,好比點擊」結算」完成購物車結算。在 Java 項目中每次啓動 main()也會自動開啓一個 main 線程
public class MybatisUtils {
private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<>();
private static SqlSessionFactory sqlSessionFactory = null;
static{
// 建立 SqlSessionFactory
InputStream is = null;
try{
is = Resources.getResourceAsStream("mybatis-cfg.xml");
}catch (IOException e){
e.printStackTrace();
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
}
// 獲取 SqlSession
public static SqlSession getSqlSession(){
SqlSession sqlSession = threadLocal.get();
if(sqlSession == null){
sqlSession = sqlSessionFactory.openSession();
threadLocal.set(sqlSession);
}
return sqlSession;
}
// 關閉 SqlSession
public static void closeSqlSession(){
SqlSession sqlSession = threadLocal.get();
if(sqlSession != null){
sqlSession.close();
threadLocal.set(null);
}
}
}
複製代碼
在 Mybatis 中事務提交方式默認爲手動提交,這與 JDBC 是不一樣的。在 JDBC 中事務默認提交方式爲自動提交。
SqlSession sqlSession = sqlSessionFacotry.openSession();
複製代碼
SqlSession sqlSession = sqlSessionFacotry.openSession(true);
複製代碼
Log4j: Log For Java(Java 的日誌) 是 Apache 提供的一個開源的 Java 主流的日誌框架。
Log4j2:
Log4j 定義了 8 個日誌級別(除去 OFF 和 ALL,能夠說分爲 6 個級別),優先級從高到 低依次爲:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL。
在 Log4j 中建議只使用 DEBUG、INFO、WARN、ERROR 四個日誌級別
誤,這種級別你能夠直接中止程序了。
Commons
Logging,
Slf4j,
Logback,
Jul。
Log4j 配置文件名:log4j 配置文件名:log4j.properties,Log4j 配值文件存放位置:項目的 src 的根目錄中
配置根 Logger:
log4j.rootLogger = [level],appenderName,appenderName2,...
複製代碼
level 是日誌記錄的優先級,優先級從低到高分別是 DEBUG,INFO,WARN,ERROR。經過在這裏定義的級別,您能夠控制到應用程序中相應級別的日誌信息的開關,好比在這裏定義了INFO 級別,則應用程序中全部 DEBUG 級別的日誌信息將不被打印出來appenderName 就是指定日誌信息輸出到哪一個地方。可同時指定多個輸出目的地。
Log4j 中的 appender
org.apache.log4j.ConsoleAppender(輸出到控制檯) org.apache.log4j.FileAppender(輸出到文件) org.apache.log4j.DailyRollingFileAppender(天天產生一個日誌文件) org.apache.log4j.RollingFileAppender(文件大小到達指定尺寸的時候產生一個新的文件) org.apache.log4j.WriterAppender(將日誌信息以流格式發送到任意指定的地方) org.apache.log4j.jdbc.JDBCAppender(將日誌信息添加數據庫中)
向控制檯輸出的 appender
# appender.console 輸出到控制檯
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=<%d> %5p (%F:%L) [%t] (%c)- %m%n
log4j.appender.console.Target=System.out
複製代碼
向文件輸出的 appender
### appender.logfile 輸出到日誌文件 ###
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
log4j.appender.logfile.File=SysLog.log
log4j.appender.logfile.MaxFileSize=500KB
log4j.appender.logfile.MaxBackupIndex=7
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=<%d> %p (%F:%L) [%t] %c - %m%n
複製代碼
向數據庫輸出的 appender
log4j.appender.logDB=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.logDB.layout=org.apache.log4j.PatternLayout
log4j.appender.logDB.Driver=com.mysql.jdbc.Driver
log4j.appender.logDB.URL=jdbc:mysql://localhost:3306/bjsxt
log4j.appender.logDB.User=root
log4j.appender.logDB.Password=root
log4j.appender.logDB.Sql=INSERT INTO
logs(project_name,create_date,level,category,file_name,thread_name,line,all_
category,message)values('logDemo','%d{yyyy-MM-ddHH:mm:ss}','%p','%c','%F','%t','%L','%l','%m')
複製代碼
經過包名控制日誌輸出級別
log4j.logger.org.apache=FATAL
log4j.logger.org.apache.commons=ERROR
log4j.logger.org.springframework=ERROR
log4j.logger.com.bjsxt=ERROR
複製代碼
規範
在映射文件中,SQL 語句中的參數須要使用 arg0,arg1...或者 param1,param2...表示參數的順序。此方法可讀性低,且要求參數的順序不能出錯,在開發中不建議使用
List selectUsersOrderParam(String username,String usersex); |
---|
select * from users where username = #{arg0} and usersex= #{arg1} |
select * from users where username = #{param1} and usersex=#{param2} |
在接口方法的參數列表中經過@Param 註解來定義參數名稱,在 SQL 語句中經過註解中所定義的參數名稱完成參數位置的指定。 此方式在參數很少的狀況仍是比較直觀的,推薦使用。
<!-- 根據用戶姓名與性別查詢用戶 , 使用 @Param 註解傳參法 -->
<select id="selectUsersAnnParam" resultType="users">
select * from users where username = #{name} and usersex= #{sex}
</select>
複製代碼
List<Users> selectUsersAnnParam(@Param("name") String username,@Param("sex") String usersex);
複製代碼
在 Mapper 動態代理中也可使用 POJO 做爲傳遞參數的載體,在 SQL 語句中綁定參數時使用 POJO 的屬性名做爲參數名便可。此方式推薦使用。
<!-- 根據用戶姓名與性別查詢用戶 , 使用 POJO 傳參法 -->
<select id="selectUsersPOJOParam" resultType="users">
select * from users where username = #{username} and usersex=#{usersex}
</select>
複製代碼
List<Users> selectUsersPOJOParam(Users users);
複製代碼
在 Mapper 動態代理中也可使用 Map 做爲傳遞參數的載體,在 SQL 語句中綁定參數時使用 Map 的 Key 做爲參數名便可。此方法適合在傳遞多參數時,若是沒有 POJO 能與參數匹配,可使用該方式傳遞參數。推薦使用。
MyBatis 傳遞 map 參數時,若是傳遞參數中沒有對應的 key 值,在執行 sql 語句時默認取的是 null。
<!-- 根據用戶姓名與性別查詢用戶 , 使用 Map 傳參法 -->
<select id="selectUsersMapParam" resultType="users">
select * from users where username = #{keyname} and usersex=#{keysex}
</select>
複製代碼
List<Users> selectUsersMapParam(Map<String,String> map);
複製代碼
咱們可使用符號的實體來表示
<select id="selectUsers" resultType="users">
select * from users where userid > #{userid}
</select>
複製代碼
Mybatis動態sql有什麼用?執行原理?有哪些動態sql?
在 MyBatis 中提供了動態 SQL 功能。將使用 Java 代碼拼接 SQL 語句,改變爲在 XML 映射文件中使用標籤拼接 SQL 語句。
MyBatis 中動態 SQL 是編寫在 mapper.xml 中的,其語法和 JSTL 相似,可是倒是基於強大的 OGNL 表達式實現的。
OGNL (對象導航圖語言(Object Graph Navigation Language),簡稱OGNL,是應用於Java中的一個開源的表達式語言(Expression Language),它被集成在Struts2等框架中,做用是對數據進行訪問,它擁有類型轉換、訪問對象方法、操做集合對象等功能。)
if 標籤單分支判斷語句
<!-- 根據用戶給定的條件進行查詢 -->
<select id="selectUsersByProperty" resultType="users">
select * from users where 1=1
<if test="userid != 0">
and userid = #{userid}
</if>
<if test="username != null and username != ''">
and username = #{username}
</if>
<if test="usersex != null and usersex != ''">
and usersex = #{usersex}
</if>
</select>
複製代碼
從多個條件中選擇一個使用。
<!-- 多選一條件 -->
<select id="selectUsersByChoose" resultType="users">
select * from users where 1=1
<choose>
<when test="username != null and username != ''">
and username = #{username}
</when>
<when test="usersex != null and usersex != ''">
and usersex = #{usersex}
</when>
<otherwise>
and userid = 1
</otherwise>
</choose>
</select>
複製代碼
使用 where 標籤,就不須要提供 where 1=1 這樣的條件了。若是判斷條件不爲空則自動添加 where 關鍵字,而且會自動去掉第一個條件前面的 and 或 or
<!-- 根據用戶給定的條件進行查詢使用 where 標籤實現 -->
<select id="selectUsersByPropertyWhere" resultType="users">
select * from users
<where>
<if test="userid != 0">
and userid = #{userid}
</if>
<if test="username != null and username != ''">
and username = #{username}
</if>
<if test="usersex != null and usersex != ''">
and usersex = #{usersex}
</if>
</where>
</select>
複製代碼
bind 標籤容許咱們在 OGNL 表達式之外建立一個變量,並能夠將其綁定到當前的 SQL語句中。通常應用於模糊查詢,經過 bind 綁定通配符和查詢值。
<!-- 根據用戶姓名模糊查詢 -->
<select id="selectUsersByLikeName" resultType="users">
<bind name="likeName" value="'%'+name+'%'"/>
select * from users where username like #{likeName}
</select>
複製代碼
set 標籤用在 update 語句中。藉助 if 標籤,能夠只對有具體值的字段進行更新。set 標籤會自動添加 set 關鍵字,自動去掉最後一個 if 語句的多餘的逗號。
<!-- 選擇更新 -->
<update id="usersUpdate">
update users
<set>
<if test="username != null and username != ''">
username = #{username},
</if>
<if test="usersex != null and usersex != ''">
usersex = #{usersex},
</if>
</set>
where userid = #{userid}
</update>
複製代碼
foreach 標籤的功能很是強大,咱們能夠將任何可迭代對象如 List、Set 、Map 或者數組對象做爲集合參數傳遞給 foreach 標籤進行遍歷。它也容許咱們指定開頭與結尾的字符串以及集合項迭代之間的分隔符。
迭代 List、Set
<!-- 查詢用戶 ID 爲 1 或者 2 的用戶 -->
<select id="selectUsersByIdUseCollection" resultType="users">
select * from users where userid in
<foreach collection="collection" item="userid" open="(" separator="," close=")">
#{userid}
</foreach>
</select>
複製代碼
迭代數組
<!-- 查詢用戶 ID 爲 1 或者 2 的用戶使用數組傳遞參數 -->
<select id="selectUsersByIdUseArray" resultType="users">
select * from users where userid in
<foreach collection="array" item="userid" open="(" separator="," close=")">
#{userid}
</foreach>
</select>
複製代碼
在執行了一次SQL查詢語句時,查詢結果存儲在內存或者某種緩存介質(Mybatis的緩存介質有哪些)當中,當下次遇到相同的查詢 SQL 時候不在執行該 SQL,而是直接從緩存中獲取結果
MyBatis 緩存方式分爲一級緩存和二級緩存,同時也可配置關於緩存設置。
一級緩存是將結果緩存在 SqlSession 對象中,二級緩存是存儲在 SqlSessionFactory 對象中。默認狀況下,MyBatis 開啓一級緩存,沒有開啓二級緩存。當數據量大的時候能夠藉助一些第三方緩存技術來協助保存 Mybatis 的二級緩存數據。
一級緩存也叫本地緩存,MyBatis 的一級緩存是在會話(SqlSession)層面進行緩存的。在SqlSession中有一個(內存區域)數據結構(HashMap)用於存儲緩存數據。不一樣的SqlSession之間的緩存數據區域(HashMap)是互相不影響的;MyBatis 的一級緩存是默認開啓的,不須要任何的配置。
MyBatis 在開啓一個數據庫會話時,會建立一個新的 SqlSession 對象,SqlSession 對象中會有一個新的 Executor (Executor是什麼?)對象。Executor 對象中持有一個新的PerpetualCache(PerpetualCache是什麼?) 對象;當會話結束時,SqlSession 對象及其內部的 Executor 對象還有 PerpetualCache 對象也一併釋放掉。
若是 SqlSession 調用了 close()方法,會釋放掉一級緩存 PerpetualCache 對象,一級緩存 將不可用。
若是 SqlSession 調用了 clearCache(),會清空 PerpetualCache 對象中的數據,可是該對象 仍可以使用。
若是中間(半路中)sqlSession去執行commit操做(update()、delete()、insert()) ,都會清空SqlSession中的數據,這樣作的目的是更新緩存中的數據(PerpetualCache 對象),避免髒讀
Mybatis 認爲,對於兩次查詢,若是如下條件都徹底同樣,那麼就認爲它們是徹底相同的兩次查詢。
傳入的 statementId(statementId是什麼?)。
查詢時要求的結果集中的結果範圍。
此次查詢所產生的最終要傳遞給 PreparedStatement 的 Sql 語句字符串。
傳遞的參數值
MyBatis 的二級緩存是 Application 級別的緩存,它能夠提升對數據庫查詢的效率,以提升應用的性能。二級緩存是 SqlSessionFactory 上的緩存,能夠是由一個 SqlSessionFactory 建立的不一樣的 SqlSession 之間共享緩存數據。默認並不開啓。SqlSession 在執行 commit()或者 close()的時候將數據放入到二級緩存。
二級緩存的開啓須要進行配置,實現二級緩存的時候,MyBatis 要求緩存的 POJO 必須是可序列化的, 也就是要求實現 Serializable 接口,爲了將緩存數據取出執行反序列化操做,由於二級緩存數據存儲介質多種多樣,不必定只存在內存中,有可能存在硬盤中。在映射配置文件中配置就能夠開啓緩存了。
屬性,設置爲 false。 5. 緩存會使用默認的 Least Recently Used(LRU,最近最少使用的)算法來收回。 6. 根據時間表,好比 No Flush Interval,(CNFI 沒有刷新間隔),緩存不會以任什麼時候間順序 來刷新。
在 Mybatis 中若是使用註解式開發,那麼註解須要添加在 Mapper 接口中的抽象方法上,在註解中給定須要執行的 SQL 語句便可,這樣就能夠不須要映射配置文件。MyBatis 支持純註解方式,支持純映射配置文件方式,也支持註解和映射配置文件混合形式。當只有接口沒有映射配置文件時在 mybatis-cfg.xml 中對於引入映射能夠經過加載指定接口類。也可使用指定加載的包。
實例
@Select("select * from users")
List<Users> selectUsersAll();
複製代碼
@Select("select * from users where username = #{param1} and usersex= #{param2}")
List<Users> selectUsersByNameAndSexOrder(String username,String usersex);
@Select("select * from users where username = #{name} and usersex = #{sex}")
List<Users> selectUsersByNameAndSexOrder2(@Param("name") String username,@Param("sex") String usersex);
複製代碼
#{}裏面的參數名稱要與實體類的屬性名稱一致
@Select("select * from users where username = #{username} and usersex = #{usersex}")
List<Users> selectUsersByNameAndSexPOJO(Users users);
複製代碼
當key不存在時,則返回null
@Select("select * from users where username = #{keyname} and usersex = #{keysex}")
List<Users> selectUsersByNameAndSexMap(Map<String,String> map);
複製代碼
Open Session In View 模式:
Open Session In View 是將一個數據庫會話對象綁定到當前請求線程中,在請求期間一直保持數據庫會話對象處於 Open 狀態,使數據庫會話對象在請求的整個期間均可以使用。直到產生響應後關閉當前的數據庫會話對象