首先討論一下基本的概念~:
(1)MyBatis 是支持定製化 SQL、存儲過程以及高級映射的優秀的持久層框架。
(2)MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。
(3)MyBatis可以使用簡單的XML或註解用於配置和原始映射,將接口和Java的POJO(Plain Old Java Objects,普通的Java對象)映射成數據庫中的記錄.
(4)是半自動化持久層框架,就是操作一個單表,也要自己寫sql語句 Hibernate是全自動的sql就不容易做特殊優化
(5)jdbc編程—當我們使用jdbc持久化的時候,sql語句被硬編碼到java代碼中。這樣耦合度太高。代碼不易於維護。在實際項目開發中會經常添加sql或者修改sql,這樣我們就只能到java代碼中去修改。
分隔~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
使用:
需要導入jar包:
log4j-1.2.17.jar 日記
mybatis-3.4.1.jar mybatis的
mysql-connector-java-5.1.7-bin.jar mysql驅動
添加配置文件:
mybatis-config.xml 核心配置文件 名字暫時可以隨便取
log4j.properties 日記配置文件
1寫一個.xml文件 充當核心配置文件
<?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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<!-- dataSource 數據源
POOLED 表示使用數據庫連接池
-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<!-- 引入sql語句對應的配置文件 -->
<mappers>
<mapper resource="com/xxx/pojo/UserMapper.xml" />
</mappers>
</configuration>
2 log4j.properties
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
3寫數據庫表單對應的javaBean對象 xxx (我用了User類)
4寫xxxMapper.xml來映射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">
<!--
namespace 是名稱空間 屬性一般情況下。
一種定義規則:
一種是使用對流的javaBean的全類名
一種是使用Mapper接口的全類名
-->
<mapper namespace="com.xxx.pojo.User">
<!--
select 定義select查詢語句
id 給你要定義的sql語句,設置一個唯一的id值。
resultType 查詢完返回的類型
parameterType 設置參數的類型(例如在delete update insert語句中使用)
#{id} 這是一個佔位符
-->
<select id="selectUserById" resultType="com.xxx .pojo.User"> //注意這裏resultType對單個對象和集合都適用
select id,last_name lastName,sex from t_user where id = #{id}
</select>
</mapper>
5利用org.apache.ibatis.io.Resources讀取核心配置文件
(1)Resources.getResourceAsStream("前面寫的核心配置文件"); //返回一個輸入流
(2)new SqlSessionFactoryBuilder().build(輸入流); //通過SqlSessionFactoryBuilder 創建SqlSessionFactory實例 注意此實例在一個項目中只有一個實例!~~~~~~
(3)關閉輸入流
(4)通過SqlSessionFactory調用openSession方法創建SqlSession對象 (相當於Connection對象)
(6)SqlSession調用selectOne執行select查詢語句返回一個對象(名稱空間值+sql映射配置文件select標籤id值,參數)
selectList
insert 等更新需要自己commit
(5)關閉SqlSession
我們可以自己寫DAO接口以及實現類 然偶胡在構造器或者set方法中將sqlSessionFactory賦值進去,即可以把上面5(4)的方法通過自己寫的dao來調用~
**
插入之後返回主鍵值
**
方法(1)insert標籤:useGeneratedKeys=“true” keyProperty="id"配置返回的值賦給對象裏的id
方法(2)selectKey標籤 用來定義sql語句 在其他語句之前或之後執行(此時看log會發現執行了兩條語句~)
在insert標籤內部寫:
<selectKey order=“BEFORE”>SELECT LAST_INSERT_ID()</selectKey>
order屬性設置selectKey語句執行的順序 在這裏要用after
keyProperty配置返回的值賦給對象裏的id
**
Mapper接口方式實現增刪改查
**
可以不用自己寫實現類 只需要寫接口就可以用
要求:(1)Mapper.java類名和Mapper.xml配置文件名一樣
(2)放在同一個包下
1 <mapper namespace=“接口全類名”
2 標籤id必須跟接口方法名相同 parameterType和resultType也必須完全一樣
3 SqlSession調用getMapper方法 參數傳入接口類名.class
Mybatis接口實現的原理:JDK動態代理
1通過mapperProxyFactory.newInstance(sqlSession)創建代理對象
底層就是Proxy.newProxyInstance返回的代理對象
會判斷調用的sql是什麼方法 例如如果是select 再判斷是不是返回多個還是單個 還是map 還是油表 如果是單個 就執行sqlSession.selectOne
**
利用核心配置文件properties
**
resource寫上自己寫的jdbc文件 裏面的內容會起作用 而不是在主配置文件裏的properties起做用
**
mybatis的核心配置setting
**
<settings><setting name... value...></setting>
1 mapUnderscoreToCamelCase自動開啓數據庫列名的映射的駝峯標示(下劃線變駝峯) 默認爲false
**
mybatis的核心配置typeAliases別名
**
<typeAliases>
<typeAlias type="全類名" alias="別名" 定義一個別名 以後這個類在配置文件中就可以用別名標示了
<package name="包名"> 自動掃描指定包下的所有類 別名就是類名首字母小寫
</typeAliases>
若果兩個包下面有相同的類名 就可以使用@Alias("別名")來定義別名
**
類處理器typeHandlers
**
Mybatis和PreparedStatement中都會使用類型處理器將獲取到的值以合適的方式轉換成爲java類型
類型處理器 Java 類型 JDBC 類型
BooleanTypeHandler java.lang.Boolean, boolean 數據庫兼容的 BOOLEAN
ByteTypeHandler java.lang.Byte, byte 數據庫兼容的 NUMERIC 或 BYTE
ShortTypeHandler java.lang.Short, short 數據庫兼容的 NUMERIC 或 SHORT INTEGER
IntegerTypeHandler java.lang.Integer, int 數據庫兼容的 NUMERIC 或 INTEGER
LongTypeHandler java.lang.Long, long 數據庫兼容的 NUMERIC 或 LONG INTEGER
FloatTypeHandler java.lang.Float, float 數據庫兼容的 NUMERIC 或 FLOAT
DoubleTypeHandler java.lang.Double, double 數據庫兼容的 NUMERIC 或 DOUBLE
BigDecimalTypeHandler java.math.BigDecimal 數據庫兼容的 NUMERIC 或 DECIMAL
StringTypeHandler java.lang.String CHAR, VARCHAR
ClobReaderTypeHandler java.io.Reader -
ClobTypeHandler java.lang.String CLOB, LONGVARCHAR
NStringTypeHandler java.lang.String NVARCHAR, NCHAR
NClobTypeHandler java.lang.String NCLOB
BlobInputStreamTypeHandler java.io.InputStream -
ByteArrayTypeHandler byte[] 數據庫兼容的字節流類型
BlobTypeHandler byte[] BLOB, LONGVARBINARY
DateTypeHandler java.util.Date TIMESTAMP
DateOnlyTypeHandler java.util.Date DATE
TimeOnlyTypeHandler java.util.Date TIME
SqlTimestampTypeHandler java.sql.Timestamp TIMESTAMP
SqlDateTypeHandler java.sql.Date DATE
SqlTimeTypeHandler java.sql.Time TIME
ObjectTypeHandler Any OTHER 或未指定類型
EnumTypeHandler Enumeration Type VARCHAR-任何兼容的字符串類型,存儲枚舉的名稱(而不是索引)
EnumOrdinalTypeHandler Enumeration Type 任何兼容的 NUMERIC 或 DOUBLE 類型,存儲枚舉的索引(而不是名稱)。
**
mybatis核心配置之environments環境
**
1可以配置多個環境 映射多個數據庫 在environments裏面配置多個environment 更改id 就好
2transactionManager 有兩個參數 jdbc(有事務) MANAGED這個配置沒做什麼
如果用的spring+myabits這個2transactionManager就沒意義 因爲會被spring的配置覆蓋掉
**我們也可以自定義事務管理器:
(1)實現TransactionFactory
(2)實現Transaction 並且在 TransactionFactory方法中返回
然後把自定義的事務管理器的全類名放在transactionManager的type屬性當中 就可以實現自己的事務管理器 我們可以在自己的類中寫自己的方法~
**
mybatis核心配置之databaseIdProvider
**
讓mybatis支持多種數據庫
<databaseIdProvider type="DB_VENDOR">
<property name="SQL Server" value="sqlserver" />
<property name="MySQL" value="mysql" />
<property name="DB2" value="db2" />
<property name="Oracle" value="oracle" />
</databaseIdProvider>
在Mapper.xml中的sql語句標籤可以配置databaseId屬性 在我們使用不同數據庫的時候 就會動態的找尋相對應的語句執行~
**
mybatis核心配置之映射器mappers
**
作用:引入sql語句對應的mapper配置文件
1利用類路徑下的資源路徑:<mapper resource="">這裏寫的是xml文件
2使用mapper接口的方式 <mapper class="接口全類名"> 這裏寫的是全類名 可以通過指定類掃描mapper配置文件
3使用包名 <package name="包名"> 搜索所有包名下的配置文件
**
使用註解的方式映射sql語句
**
此時就不需要使用Mapper.xml來映射sql語句了
在接口的方法上寫:
(1)@Select (value=“”) @Update (value=“”) @Delete (value=“”) @Insert (value=“”)
insert語句可以再寫一個註解: @SelectKey(before=false,statement=“select last_insert_id()”,keyProperty=“id”,resultType=Integer。class)來將生成的id返回
(2)mappers 改成<mapper class="接口全類名"> 這裏寫的是全類名 可以通過指定類掃描mapper配置文件
**
Mybatis sql映射文件參數傳遞
**
(1)一個普通數據類型 寫變量名 #{變量名}
(2)多個普通數據類型 用#{param1} #{param2} #{param3}
或者用註解的方式@param("")然後就可以用#{前面寫的名字}來使用了
(3)傳遞的是一個對象(包括map對象)用#{屬性名或者key名}
(4)傳遞多個pojo對象 使用#{param1.屬性名} #{param2.屬性名}
**
{} 和 ${}的區別
**
#{}是佔位符?
xml中配置的是#{}會解析成 ?
${}是原樣輸出參數的值 並且需要做字符串拼接的操作
xml中的配置: '${xxx}'
若果需要模糊查詢 我們一般使用:concat('%',#{參數},'%')
**
自定義結果集
**
用來解決查詢的pojo對象中包含pojo對象或者pojo對象集合的情況~ 此時需要使用resultMap自定義返回的結果
resultMap上的屬性
type :返回的對象全類名
id的值是resultMap的值
裏面的標籤:
id 專門用來映射id主鍵列
result 映射非主鍵列 可以使用集聯映射來給pojo中的pojo賦值 column是查詢出來的字段名 property是bean對象的屬性
association標籤專門映射pojo中的一個bean對象: property是pojo對象中bean對象的屬性名 javaType是pojo對象中bean對象的全類名
association中再使用id 和result賦值
collection 專門用來映射集合 property表示映射的集合的屬性名 ofType表示集合中的類型
**
一對一分佈查詢
**
有時候我們查詢結果後只運用了某個子段 所以全部查詢出來就是很浪費的 這時候可以用分佈查詢
代碼顯示地使用了哪個子段的表才查哪個
我們需要把表分成虛擬的主表和從表進行查詢 所以需要寫兩個mapper接口和映射xml 分別查詢兩個表的子段 在一對一的情況下 就是第一個pojo對象爲主表 pojo裏面的pojo對象爲從表 分兩步進行查詢 不使用到pojo裏的pojo對象就不進行查詢
使用:
association :
select屬性寫上第二個mapper.xml的名稱空間.標籤id 即第二批次執行的查詢語句
column傳入在第一個主表中查詢出來的pojo 中的pojo的id值
此時就可以分成兩個語句進行查詢
還需要使用延遲加載 :
延遲加載在一定程序上可以減少很多沒有必要的查詢。給數據庫服務器提升性能上的優化。
要啓用延遲加載,需要在mybatis-config.xml配置文件中,添加如下兩個全局的settings配置。
<!-- 打開延遲加載的開關 -->
<setting name="lazyLoadingEnabled" value="true" />
<!-- 將積極加載改爲消極加載 按需加載 -->
<setting name="aggressiveLazyLoading" value="false"/>
懶加載功能,mybatis3.2.8版本,需要同時引入兩個jar包
cglib-2.2.2 asm-3.3.1
全部配置好後 執行第一個查詢語句的時候就會查主表 在使用到第二個表的字段的時候纔會再次進行查詢
**
一對多分步查詢
**
查詢的代碼方法跟上面一對一的一樣 只不過查詢的是集合;
**
一對多雙向關聯
**
顧名思義 就是一個A對象裏面有一個集合對象 集合對象裏面的每一個B對象又有開頭的A對象
所以在第一個懶加載裏面調用了第二個對象的懶加載 第二個對象的懶加載又調用了第一個的懶加載
這裏會產生一個問題:就是注意不要調用A.toString()否則會出錯stackoverflowerror
需要用什麼的時候 就把這個屬性拿出來 手動調用
**
動態sql
**
if 可以動態的根據你的值來決定,是否需要動態的添加查詢條件
where 可以幫我們在多個動態語句中,有效的去掉前面的多餘的and 或 or 之類的多餘關鍵字 還可以動態的判斷中間是否包含查詢條件。如果沒有連where關鍵字也不會出現。
trim 可以動態在包含的語句前面和後面添加內容。也可以去掉前面或者後面給定的內容
prefix 前面添加內容
suffix 後面添加內容
suffixOverrides 去掉的後面內容
prefixOverrides 去掉的前面內容
choose when otherwise 可以執行多路選擇判斷,但是隻會有一個分支會被執行。 類似switch case 語句
set 刪除條件後面的逗號
foreach標籤 用來遍歷集合
collection遍歷的數據源
open屬性設置遍歷的開始內容
close屬性設置遍歷的結束內容
item屬性是當前遍歷到的數據
separator屬性設置遍歷的每個元素之間的間隔符
**
mybatis 緩存
**
緩存:緩存指的是將經常訪問的數據保存到一個高速的數據存儲區,其實就是內存~ 緩存的目的當然就是爲了快速訪問
一級緩存(默認開啓的): 指的是將數據保存在SqlSession中(同一個SqlSession)
只有在SqlSession中沒有的才發送sql語句到數據庫進行查詢 查詢回來後直接放在一級緩存中
---------------一級緩存的管理:
緩存失效的四種情況:
1.不在同一個SqlSession對象中
2.執行語句的參數不同。緩存中也不存在數據。
3.執行增,刪,改,語句,會清空掉緩存(兩次查詢中間做了增刪改查的操作~)
4.手動清空緩存數據 (調用session對象的clearCache())
二級緩存(默認不開啓的!~): 指的是將數據保存以mapper中(同一個sqlSessionFactory)
因爲是從sqlSessionFactory中創建出來的SqlSession對象 所以下段話很容易理解:
1先從二級緩存中查詢(sqlSessionFactory對象)
2再從一級緩存中查詢
3都沒有才到數據庫中查詢 並且放到一級緩存中
4SqlSession關閉的時候把數據保存到二級緩存中~
當SqlSession執行相關的緩存失效情況時候(例如執行添加刪除等操作) 就會清空一級和二級緩存~
這就意味着多個sqlSessionFactory下的SqlSession對象只要有一個查詢回來數據就會保存在sqlSessionFactory中 其後的sqlSession對象查詢相同數據會直接去二級緩存查詢 不會像上面一樣重新查詢數據庫了(但是不同的一級緩存sqlSession需要在其他sqlSession查詢前關閉)
開啓二級緩存:
myBatis的二級緩存默認是不開啓的。我們需要在mybatis的核心配置文件中配置setting選項 和 在Mapper的配置文件中加入cache標籤。並且需要被二級緩存的對象必須要實現java的序列化接口。
二級緩存的使用步驟:
1、在mybatis-config.xml中配置選項
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
2、在Mapper.xml中去添加一個cache標籤
3、對象必須要實現java的序列化接口 (因爲涉及到了序列化和反序列化)
底層:是CachingExecutor內部的query方法會創建一個CacheKey對象(查詢語句加參數 所以參數不同會導致緩存失效 因爲key不同)
TransactionCacheManager二級緩存事務管理器以上述CacheKey爲參數查詢 查詢不到一級執行器SimpleExecutor就會調用一級緩存localCache查詢 也沒有就調用queryFromDatabse查詢數據庫~
**
mybatis的逆向工程:
**
可以快速根據表生成對應的 bean對象 對應的mapper接口 mapper接口對應的映射文件
1寫一個xml配置文件
(圖片來自網絡 侵刪)
2寫一個java類 運行:
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
File configFile = new File("你的配置文件.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,
callback, warnings);
myBatisGenerator.generate(null);
去除全部註釋:
<commentGenerator>
<property name="suppressAllComments" value="true" />
</commentGenerator>