一.MyBatis框架初使用
- 使用底層的selectOne()方法
- 導入Mybatis的jar包
- 創建一個全局配置文件 mybatis-config.xml ,根據全局配置文件,創建了一個
SqlSessionFactory對象. - 創建一個sql映射文件, EmployeeMapper.xml,該配置文件中配置了sql語句.
- 將sql映射文件註冊到全局配置文件中
- 從SqlSessionFactory中獲取SqlSession對象. sqlSession代表和數據庫的一次會話.
- 然後調用selectOne(“sql語句的唯一標識”,執行sql的參數)完成查詢操作.
- 最後將SqlSession對象關閉.釋放資源.
將sql映射文件註冊到全局配置文件中:
<mappers>
<!--<mapper resource="EmployeeMapper.xml"/>-->引入一個sql映射配置文件
<!--批量引入-->
<package name="com.atguigu.mybatis.dao"/>該包下方的配置文件全部引入
</mappers>
2.目錄結構
二.Mapper接口開發
Mapper接口的好處:
1.接口中定義的方法明確的類型約束(方法參數的類型 方法返回值的類型)
2.接口本身:
接口本身就是抽象.抽出了規範.不強制要求如何做具體的實現.可以使用jdbc,hibernate,Mybatis.
接口將規範與具體的實現分離.
Mapper接口開發, MyBatis會爲接口生成代理實現類。代理對象完成具體的增刪改查操作.
最底層還是使用selectOne,update等方法來完成的.
Mapper接口開發需要注意:
1.Mapper接口要與sql映射文件動態綁定. sql映射文件的namespace指定成接口的全類名.
<mapper namespace="com.atguigu.mybatis.dao.EmployeeMapper"></mapper>
2.Mapper接口方法與sql映射文件的sql語句綁定。 sql語句的id值指定成接口中的方法名.
<!--
select: 配置查詢的sql語句
id:sql語句的唯一標識,不能重複,當添加上databaseId="XXX"時,即使用不同的數據庫,此時id允許重複
resultType:當前sql查詢到的數據想讓MyBatis封裝的javaBean對象的類型.
#{id}: 從傳遞過來的參數中取出id值.
-->
<!-- public Employee getEmpById(Integer id );-->
<!--sql語句的id值指定成方法名,目的是將sql語句與方法綁定-->
<select id="getEmpById" resultType="com.atguigu.mybatis.beans.Employee">
select id,last_name,gender,email from tb1_employee where id = #{id}
</select>
三.全局配置文件
1.properties
<!--
properties: Mybatis可以是用properties來引入外部properties類型的文件.
resource: 引入類路徑下的資源
url: 引入網絡路徑或者是磁盤路徑下的資源
-->
<properties resource="db.properties" ></properties>在db.properties中配置數據庫的驅動,用戶名等
2.settings
<!--
settings: 包含了很多重要的設置項
setting: 用來設置每一個設置項
name:設置項的名稱
value:設置項的值
-->
<settings>
<!-- 自動映射下劃線到駝峯命名 (數據庫中常用下劃線命名,JavaBean類中用大寫命名)
DB: last_name autoMapping:lastName -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
3.typeAliases
<!--
typeAliases:別名處理,爲java 類型註冊別名
typeAlias: 爲某個java類指定別名
type: 指定java的類型(包名+ 類名
alias: 指定具體的別名。 如果alias不顯示的指定,則默認的別名是類名的首字母小
寫.
別名不區分大小寫。
package: 批量取別名.
name:指定包名。 爲該包下的所的類取默認的別名。
批量取別名可能會出現別名衝突的情況. 例如指定的包下與子包下相同的類.
可以使用@Alias("別名")在類上標註具體的別名.
-->
<typeAliases>
<package name="com.atguigu.mybatis.beans"/>
<!-- <typeAlias type="com.atguigu.mybatis.beans.Employee" alias="emp" /> -->
</typeAliases>
4.environments
<!--
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">此處default配置那個id標識,使用的就是哪一個數據庫
<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>
<!--使用oracle數據庫-->
<environment id="oracle">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${orcl.driver}" />
<property name="url" value="${orcl.url}" />
<property name="username" value="${orcl.username}" />
<property name="password" value="${orcl.password}" />
</dataSource>
</environment>
</environments>
5.databaseIdProvider
<!--
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
<!--
mappers: 引入sql映射文件
mapper: 引入單個的sql映射文件
resource: 引入類路徑下的sql映射文件
url:引入網絡路徑或者是磁盤路徑下的sql映射文件.
package: 批量引入sql映射文件
要求:
1.sql映射文件的名字與 Mapper接口的名字一致.
2.Sql映射文件與Mapper接口必須在同一目錄下.
name:指定包名
-->
<mappers>
<!--<mapper resource="EmployeeMapper.xml"/>-->
<!--批量引入-->
<package name="com.atguigu.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:具體傳入的參數值
<!--測試傳遞多個參數的編寫方式:public Employee getEmpByIdAndLastName(Integer id,String lastName);
select * from tb1_employee where id=#{param1} and last_name=#{param2}
當接口處明確標出Param時,這裏可以使用對應的值來進行傳參
public Employee getEmpByIdAndLastName(@Param("id")Integer id , @Param("lastName")String lastName);
-->
<select id="getEmpByIdAndLastName" resultType="com.atguigu.mybatis.beans.Employee">
select * from tb1_employee where id=#{id} and last_name=#{lastName}標明時可以使用對應值
</select>
異常: ### Cause: org.apache.ibatis.binding.BindingException: Parameter 'id' not found.
Available parameters are [1, 0, param1, param2]
解決: 取值使用#{param1/ 0} #{param2 / 1 }
1.命名參數**: 明確的指定多個參數封裝map的時候所使用的key。 @Param(“key”)
取值: #{@Param指定的key/paramN}
2.POJO: 如果參數很多,正好又是業務邏輯的數據模型中的屬性,直接傳入POJO
取值: #{POJO的屬性名}
3.Map: 如果參數很多,不是業務邏輯的數據模型中的屬性,可以封裝成map傳入.
取值: #{map中的key}
map.put(“aa”,1001);
map.put(“bb”,“Tom”);
映射配置中:
select * from tb1_employee where id=#{aa} and last_name=#{bb}取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;
}
參數值的獲取方式
1.#{}: 可以獲取map中的值 或者是POJO對象屬性的值。 還可以直接獲取普通類型的參數.
2.${}: 可以獲取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表查.