Mybatis(1)
阿新 • • 發佈:2018-11-02
一、MyBatis的HelloWorld
1. 使用底層的selectOne()方法
/** * helloWorld的小結: * * 1.匯入Mybatis的jar包 * 2.建立一個全域性配置檔案 mybatis-config.xml ,根據全域性配置檔案,建立了一個 SqlSessionFactory物件. * 3.建立一個sql對映檔案, EmployeeMapper.xml,該配置檔案中配置了sql語句. * 4.將sql對映檔案註冊到全域性配置檔案中 * 5.從SqlSessionFactory中獲取SqlSession物件. sqlSession代表和資料庫的一次會話. * 然後呼叫selectOne("sql語句的唯一標識",執行sql的引數)完成查詢操作. * 6.最後將SqlSession物件關閉.釋放資源. */
2. 使用Mapper介面開發
/** * Mapper介面的好處: * 1.介面中定義的方法明確的型別約束(方法引數的型別 方法返回值的型別) * 2.介面本身: * 介面本身就是抽象.抽出了規範.不強制要求如何做具體的實現.可以使用jdbc, hibernate,Mybatis. * 介面將規範與具體的實現分離. * Mapper介面開發, MyBatis會為介面生成代理實現類。代理物件完成具體的增刪改查操作. * 最底層還是使用selectOne,update等方法來完成的. * * Mapper介面開發需要注意: * 1.Mapper介面要與sql對映檔案動態繫結. sql對映檔案的namespace指定成介面的全類名. * 2.Mapper介面方法與sql對映檔案的sql語句繫結。 sql語句的id值指定成介面中的方法名. */
二、全域性配置檔案
1.properties
<!-- 1.properties: Mybatis可以是用properties來引入外部properties型別的檔案. resource: 引入類路徑下的資源 url: 引入網路路徑或者是磁碟路徑下的資源 --> <properties resource="db.properties" ></properties>
2.settings
<!--
2.settings: 包含了很多重要的設定項
setting: 用來設定每一個設定項
name:設定項的名稱
value:設定項的值
-->
<settings>
<!-- 自動對映下劃線到駝峰命名 DB: last_name autoMapping lastName -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
3.typeAliases
<!--
3.typeAliases:別名處理,為java 型別註冊別名
typeAlias: 為某個java類指定別名
type: 指定java的型別(包名+ 類名
alias: 指定具體的別名。 如果alias不顯示的指定,則預設的別名是類名的首字母小
寫.
別名不區分大小寫。
package: 批量取別名.
name:指定包名。 為該包下的所的類取預設的別名。
批量取別名可能會出現別名衝突的情況. 例如指定的包下與子包下相同的類.
可以使用@Alias("別名")在類上標註具體的別名.
-->
<typeAliases>
<package name="com.xypuxing.mybatis.beans"/>
<!-- <typeAlias type="com.xypuxing.mybatis.beans.Employee" alias="emp" /> -->
</typeAliases>
4.environments
<!--
4.environments: 環境們。 使用default來指定具體使用的環境.
environment:配置具體的環境.
id: 當前環境的標識
transactionManager:事務管理器
type: 配置具體的事務管理器的型別
JDBC: JdbcTransactionFactory
MANAGED:ManagedTransactionFactory
最終: 事務管理要交給Spring. 使用Spring的宣告式事務.
dataSource:資料來源
type: 執行資料來源的型別.
UNPOOLED:不是用連線池 UnpooledDataSourceFactory
POOLED:使用連線池 PooledDataSourceFactory
JNDI:從web伺服器中獲取資料來源. JndiDataSourceFactory
最終: 資料來源交給Spring管理
-->
<environments default="mysql">
<environment id="mysql">
<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>
5.databaseIdProvider
<!--
5.databaseIdProvider:
Mybatis用來支援多資料庫廠商。Mybatis可以根據不同的資料庫執行不同的sql語句
DB_VENDOR: VendorDatabaseIdProvider 作用就是得到資料庫廠商的標識名.
Connection.getMetaData().getDataBaseProductName();
常見的資料庫廠商的標識名:
MySQL: MySQL
Oracle: Oracle
SQL Server: SQL Server
-->
<databaseIdProvider type="DB_VENDOR">
<!-- 為資料庫廠商的標識名起別名 -->
<property name="MySQL" value="mysql"/>
<property name="Oracle" value="oracle"/>
<property name="SQL Server" value="sqlserver"/>
</databaseIdProvider>
6.mappers
<!--
6.mappers: 引入sql對映檔案
mapper: 引入單個的sql對映檔案
resource: 引入類路徑下的sql對映檔案
url:引入網路路徑或者是磁碟路徑下的sql對映檔案.
package: 批量引入sql對映檔案
要求:
1.sql對映檔案的名字與 Mapper介面的名字一致.
2.Sql對映檔案與Mapper介面必須在同一目錄下.
name:指定包名
-->
<mappers>
<!-- <mapper resource="mybatis/config/EmployeeMapper.xml"/> -->
<package name="com.xypuxing.mybatis.dao"/>
</mappers>
三、sql對映檔案
1.增刪改查
<insert id="" parameterType="" databaseId="" >
<update>
<delete>
<select id="" parameterType="" resultType="" databaseId="">
如果想要獲取到增刪改對資料的影響條數,可以直接在介面的方法中宣告返回值型別即可.
2.主鍵自增以及主鍵值的返回
a.對於支援自增主鍵的資料庫(Mysql),可以使用useGeneratedKeys="true" keyProperty="javaBean的屬性"
b.對於不支援自增主鍵的資料庫(oracle),使用selectKey的子標籤完成主鍵值得返回.
selectKey的用法:
BEFORE: selectKey在插入語句之前執行
AFTER: selectKey在插入語句之後執行
c.Oracle資料庫的自增策略:
使用序列模擬自增. 可以從序列中查詢 nextval currval.
3.引數傳遞:
單個引數(普通型別(基本型別/包裝型別+String)): Mybatis不會做特殊的處理
取值: #{引數名(隨便寫)} 取出引數值
多個引數:MyBatis會做特殊處理. 多個引數會被封裝成一個Map。
封裝map的規則:
key: param1 ,param2 , param3 ..... paramN / 0 1 2 ....N-1
value:具體傳入的引數值
異常: ### Cause: org.apache.ibatis.binding.BindingException: Parameter 'id' not found.
Available parameters are [1, 0, param1, param2]
解決: 取值使用#{param1/ 0} #{param2 / 1 }
命名引數**: 明確的指定多個引數封裝map的時候所使用的key。 @Param("key")
取值: #{@Param指定的key/paramN}
POJO: 如果引數很多,正好又是業務邏輯的資料模型中的屬性,直接傳入POJO
取值: #{POJO的屬性名}
Map: 如果引數很多,不是業務邏輯的資料模型中的屬性,可以封裝成map傳入.
取值: #{map中的key}
引數處理的原始碼分析:
names={0=id,1=lastName}
args=[1001,Tom]
public Object getNamedParams(Object[] args) {
final int paramCount = names.size();
if (args == null || paramCount == 0) {
return null;
} else if (!hasParamAnnotation && paramCount == 1) {
return args[names.firstKey()];
} else {
final Map<String, Object> param = new ParamMap<Object>();
int i = 0;
for (Map.Entry<Integer, String> entry : names.entrySet()) {
param.put(entry.getValue(), args[entry.getKey()]);
// add generic param names (param1, param2, ...)
final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1);
// ensure not to overwrite parameter named with @Param
if (!names.containsValue(genericParamName)) {
param.put(genericParamName, args[entry.getKey()]);
}
i++;
}
return param;
}
引數值的獲取方式:
#{}: 可以獲取map中的值 或者是POJO物件屬性的值。 還可以直接獲取普通型別的引數.
${}: 可以獲取map中的值 或者是POJO物件屬性的值
區別:
#{}:是以預編譯的形式將引數設定到sql語句中. PreparedStatement 防止sql注入.
${}:取出的值直接拼裝到sql語句中.會有安全問題.
使用場景:
大部分情況下推薦使用#{},原生的jdbc不支援佔位符的地方可以使用${}來進行動態的賦值.
eg: select xxxxx from where 條件 order by 排序欄位 排序方式 limit ?,?;
分表:
select * from 2016_salary ;
select * from 2017_salary ;
select * from ${year}_salary ;
使用者選擇2016年,則從2016_salary表查.