1. 程式人生 > >mybatis的執行流程 #{}和${} Mysql自增主鍵返回

mybatis的執行流程 #{}和${} Mysql自增主鍵返回

ola save select .org 經驗 sel 占位符 upd 執行

n Mybatis配置

全局配置文件SqlMapConfig.xml,配置了Mybatis的運行環境等信息。

Mapper.xml文件即Sql映射文件,文件中配置了操作數據庫的Sql語句。此文件需要在SqlMapConfig.xml中加載。

n 通過Mybatis環境等配置信息構造SqlSessionFactory,即會話工廠。

n 由會話工廠創建SqlSession即會話,操作數據庫需要通過SqlSession進行。

n Mybatis底層自定義了Executor執行器接口操作數據庫,Executor執行器調用具體的MappedStatement對象執行數據庫操作動作。

n MappedStatement也是

Mybatis一個底層封裝對象,它包裝了Mybatis配置信息及Sql映射信息等。Mapper.xml文件中一個Sql對應一個Mapped Statement對象,Sqlid即是Mapped statementid

n Executor通過MappedStatement在執Sql前將輸入的java對象映射至Sql中,輸入參數映射的意思就是Jdbc編程中對PreparedStatement設置參數。Executor通過MappedStatement在執行Sql後將輸

出結果映射至Java對象中,輸出結果映射過程相當於Jdbc編程中對結果的解析處理過程。

技術分享圖片

1.1.1.1. #{}
${}

n 關於#{}

1#{}等同於PreparedStatement中的占位符?,會自動傳入的字符串數據加一對單引號,可以避免Sql註入

比如 select * from user where username = #{username} ,傳入的username為小,那麽最後打印出來的就是

select * from user where username = ‘小張’

2#{}可以接收簡單類型值或Pojo屬性值 如果parameterType傳輸單個簡單類型值,#{}括號中可以是任意名稱。

n 關於${}:

1${}將傳入的數據直接顯示生成在Sql,只是簡單的拼接。如:

order by ${id},如果傳入的值是id,則解析成的Sqlorder by id

如果上面的例子使用${},則成了select * from user where username = 小張

2${}可以接收簡單類型值或Pojo屬性值,如果parameterType傳輸單個簡單類型值,${}括號中只能是“value”這個字符串

n 總結:

1$方式一般用於傳入數據庫對象,例如傳入表名order by 的字段

2一般能用#的就別用$.

1.1.1.1. Mysql自增主鍵返回

查詢Mysql自增idSql

SELECT LAST_INSERT_ID()

通過修改UserMapper.xml映射文件,可以將Mysql自增主鍵返回:

如下添加selectKey 標簽

<!-- 保存用戶 -->

<insert id="saveUser" parameterType="com.itheima.mybatis.pojo.User">

<!-- selectKey 標簽實現主鍵返回 -->

<!-- keyProperty:主鍵對應的pojo中的哪一個屬性 -->

<!-- order:設置在執行insert語句前執行查詢id的sql,孩紙在執行insert語句之後執行查詢id的sql -->

<!-- resultType:設置返回的id的類型 -->

<selectKey keyProperty="id" order="AFTER"

resultType="Integer">

SELECT LAST_INSERT_ID()

</selectKey>

INSERT INTO USER

(username,birthday,sex,address) VALUES

(#{username},#{birthday},#{sex},#{address})

</insert>

LAST_INSERT_ID():Mysql的函數,返回auto_increment自增列新記錄id值。

效果如下圖所示:

技術分享圖片

返回的id22,能夠正確的返回id

1.1.1. 修改用戶

根據用戶id修改用戶名

使用的Sql

UPDATE USER SET USERNAME = ‘趙雲‘ WHERE ID= 1

1.1.1.1. 映射文件

UserMapper.xml配置文件中添加如下內容:

<!-- 更新用戶 -->

<update id="updateUserById" parameterType="com.itheima.mybatis.pojo.User">

UPDATE USER SET

USERNAME = #{username} WHERE ID = #{id}

</update>

1.1. Mybatis解決原生jdbc編程的問題

1、 頻繁創建、釋放數據庫連接造成系統資源浪費,影響系統性能。使用數據庫連接池技術可以解決此問題。

解決:SqlMapConfig.xml中配置數據連接池,使用連接池管理數據庫連接。

2、 Sql語句寫在代碼中造成代碼不易維護,實際應用中Sql變化的可能較大,Sql變動需要改變java代碼。

解決:Sql語句配置在XXXXmapper.xml文件中與Java代碼分離。

3、 Sql語句傳參數麻煩,因為Sql語句的where條件不一定,可能多也可能少,占位符需要和參數一一對應(硬編碼)。

解決:Mybatis自動將Java對象映射至Sql語句,通過statement中的parameterType定義輸入參數的類型。

4、 對結果集解析麻煩(查詢列硬編碼),Sql變化會導致解析代碼變化,且解析前需要遍歷,如果能將數據庫記錄封裝成Pojo對象解析比較方便。

解決:Mybatis自動將Sql執行結果映射至Java對象,通過statement中的resultType定義輸出結果的類型。

1.1. Mapper動態代理方式

1.1.1. 開發規範

Mapper動態代理開發方式只需要程序員開發Mapper接口(相當於Dao接口),Mybatis框架會根據接口定義創建接口的動態代理對象,代理對象的方法同Dao接口實現類中的方法。

Mapper接口開發需要遵循以下4個規範:

n Mapper映射文件中的namespacemapper接口的類路徑相同。

n Mapper接口方法名和Mapper映射文件中定義的每個Sqlid相同

n Mapper接口方法的輸入參數類型和Mapper映射文件中定義的每個SqlParameterType的類型相同

n Mapper接口方法的輸出參數類型和Mapper映射文件中定義的每個SqlresultType的類型相同

1. MybatisHibernate區別

1Hibernate是一個完全的ORM框架,Mybatis是一個不完全的ORM框架

Hibernate自動化程度高,只需配置OR映射關系,不需要寫Sql語句,怎麽執行由框架底層控制。

Mybatis雖然將SqlJava對象做了關系映射,但需要程序員自己寫Sql。

2Hibernate學習門檻高,Mybatis學習門檻較低

Hibernate學習門檻高,精通門檻更高,設計O/R映射和Hibernate調優都需要很強的經驗和能力 一對多 多對多配置麻煩

Mybatis比較容易上手和掌握,重點關註Sql語句即可;

3Hibernate靈活度差但數據庫無關性好,Mybatis靈活度高,但犧牲了數據庫無關性

Hibernate不能幹預具體Sql的執行,但數據庫無關性好,切換不同數據庫時只需要切換數據庫類型即可。

Mybatis可嚴格控制Sql的執行性能,靈活度高,適合於軟件的需求變化快而且多的軟件,但靈活的前提是犧牲了數據庫的無關性,如果要實現支持多種數據庫的軟件則需要自定義多套Sql映射文件,工作量大。

選型原則

總之,滿足需求的前提下,只要做出維護性、擴展性好的軟件架構都是好架構,框架只有合適的才是最好的。

選型建議

訪問量小性能要求不高的內網項目,推薦使用全自動的Hibernate框架,可以提高開發效率。

訪問量大性能要求高的內網項目或者互聯網項目,推薦使用Mybatis框架

1.1.1. 使用resultMap

由於上邊的mapper.xmlsql查詢列(user_id)Order類屬性(userId)不一致,所以查詢結果不能映射到pojo中。

需要定義resultMap,把orderResultMapsql查詢列(user_id)Order類屬性(userId)對應起來

改造OrderMapper.xml,如下:

<?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:命名空間,用於隔離sql,還有一個很重要的作用,Mapper動態代理開發的時候使用,需要指定Mapper的類路徑 -->

<mapper namespace="cn.itcast.mybatis.mapper.OrderMapper">

<!-- resultMap最終還是要將結果映射到pojo上,type就是指定映射到哪一個pojo -->

<!-- id:設置ResultMap的id -->

<resultMap type="order" id="orderResultMap">

<!-- 定義主鍵 ,非常重要。如果是多個字段,則定義多個id -->

<!-- property:主鍵在pojo中的屬性名 -->

<!-- column:主鍵在數據庫中的列名 -->

<id property="id" column="id" />

<!-- 定義普通屬性 -->

<result property="userId" column="user_id" />

<result property="number" column="number" />

<result property="createtime" column="createtime" />

<result property="note" column="note" />

</resultMap>

<!-- 查詢所有的訂單數據 -->

<select id="queryOrderAll" resultMap="orderResultMap">

SELECT id, user_id,

number,

createtime, note FROM `order`

</select>

</mapper>

mybatis中的一對多 多對一關聯

1.1.1. 方法二:使用resultMap

使用resultMap,定義專門的resultMap用於映射一對一查詢結果。

1.1.1.1. 改造pojo

Order類中加入User屬性,user屬性中用於存儲關聯查詢的用戶信息,因為訂單關聯查詢用戶是一對一關系,所以這裏使用單個User對象存儲關聯查詢的用戶信息。

改造Order如下圖:

技術分享圖片

1.1.1.2. Mapper.xml

這裏resultMap指定orderUserResultMap,如下:

<resultMap type="order" id="orderUserResultMap">

<id property="id" column="id" />

<result property="userId" column="user_id" />

<result property="number" column="number" />

<result property="createtime" column="createtime" />

<result property="note" column="note" />

<!-- association :配置一對一屬性 -->

<!-- property:order裏面的User屬性名 --> user

<!-- javaType:屬性類型 --> User類的全路徑

<association property="user" javaType="user">

<!-- id:聲明主鍵,表示user_id是關聯查詢對象的唯一標識-->

<id property="id" column="user_id" />

<result property="username" column="username" />

<result property="address" column="address" />

</association>

</resultMap>

<!-- 一對一關聯,查詢訂單,訂單內部包含用戶屬性 -->

<select id="queryOrderUserResultMap" resultMap="orderUserResultMap">

SELECT

o.id,

o.user_id,

o.number,

o.createtime,

o.note,

u.username,

u.address

FROM

`order` o

LEFT JOIN `user` u ON o.user_id = u.id

</select>

1.1.1.3. Mapper接口

編寫UserMapper如下圖:

技術分享圖片

1.1. 一對多查詢

案例:查詢所有用戶信息及用戶關聯的訂單信息。

用戶信息和訂單信息為一對多關系。

sql語句:

SELECT

u.id,

u.username,

u.birthday,

u.sex,

u.address,

o.id oid,

o.number,

o.createtime

FROM

`user` u

LEFT JOIN `order` o ON u.id = o.user_id

1.1.1. 修改pojo

User類中加入List<Order> orders屬性,如下圖:

技術分享圖片

1.1.2. Mapper.xml

UserMapper.xml添加sql,如下:

<resultMap type="user" id="userOrderResultMap">

<id property="id" column="id" />

<result property="username" column="username" />

<result property="birthday" column="birthday" />

<result property="sex" column="sex" />

<result property="address" column="address" />

javaType屬性類型

ofType裏面的泛型

<!-- 配置一對多的關系 -->

<collection property="orders" javaType="list" ofType="order">

<!-- 配置主鍵,是關聯Order的唯一標識 -->

<id property="id" column="oid" />

<result property="number" column="number" />

<result property="createtime" column="createtime" />

<result property="note" column="note" />

</collection>

</resultMap>

<!-- 一對多關聯,查詢訂單同時查詢該用戶下的訂單 -->

<select id="queryUserOrder" resultMap="userOrderResultMap">

SELECT

u.id,

u.username,

u.birthday,

u.sex,

u.address,

o.id oid,

o.number,

o.createtime,

o.note

FROM

`user` u

LEFT JOIN `order` o ON u.id = o.user_id

</select>

1.1.3. Mapper接口

編寫UserMapper接口,如下圖:

技術分享圖片

mybatis的執行流程 #{}和${} Mysql自增主鍵返回