mybatis的執行流程 #{}和${} Mysql自增主鍵返回
n Mybatis配置
全局配置文件SqlMapConfig.xml,配置了Mybatis的運行環境等信息。
Mapper.xml文件即Sql映射文件,文件中配置了操作數據庫的Sql語句。此文件需要在SqlMapConfig.xml中加載。
n 通過Mybatis環境等配置信息構造SqlSessionFactory,即會話工廠。
n 由會話工廠創建SqlSession即會話,操作數據庫需要通過SqlSession進行。
n Mybatis底層自定義了Executor執行器接口操作數據庫,Executor執行器調用具體的MappedStatement對象執行數據庫操作動作。
n MappedStatement也是
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中,只是簡單的拼接。如:
如果上面的例子使用${},則成了select * from user where username = 小張
2、${}可以接收簡單類型值或Pojo屬性值,如果parameterType傳輸單個簡單類型值,${}括號中只能是“value”這個字符串
n 總結:
1、$方式一般用於傳入數據庫對象,例如傳入表名、order by 的字段
2、一般能用#的就別用$.
1.1.1.1. Mysql自增主鍵返回
查詢Mysql自增id的Sql:
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值。
效果如下圖所示:
返回的id為22,能夠正確的返回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映射文件中的namespace與mapper接口的類路徑相同。
n Mapper接口方法名和Mapper映射文件中定義的每個Sql的id相同
n Mapper接口方法的輸入參數類型和Mapper映射文件中定義的每個Sql的ParameterType的類型相同
n Mapper接口方法的輸出參數類型和Mapper映射文件中定義的每個Sql的resultType的類型相同
1. Mybatis與Hibernate區別
1)Hibernate是一個完全的ORM框架,Mybatis是一個不完全的ORM框架
Hibernate自動化程度高,只需配置OR映射關系,不需要寫Sql語句,怎麽執行由框架底層控制。
Mybatis雖然將Sql與Java對象做了關系映射,但需要程序員自己寫Sql。
2)Hibernate學習門檻高,Mybatis學習門檻較低
Hibernate學習門檻高,精通門檻更高,設計O/R映射和Hibernate調優都需要很強的經驗和能力。 一對多 多對多配置麻煩
Mybatis比較容易上手和掌握,重點關註Sql語句即可;
3)Hibernate靈活度差但數據庫無關性好,Mybatis靈活度高,但犧牲了數據庫無關性
Hibernate不能幹預具體Sql的執行,但數據庫無關性好,切換不同數據庫時只需要切換數據庫類型即可。
Mybatis可嚴格控制Sql的執行性能,靈活度高,適合於軟件的需求變化快而且多的軟件,但靈活的前提是犧牲了數據庫的無關性,如果要實現支持多種數據庫的軟件則需要自定義多套Sql映射文件,工作量大。
選型原則
總之,滿足需求的前提下,只要做出維護性、擴展性好的軟件架構都是好架構,框架只有合適的才是最好的。
選型建議
訪問量小性能要求不高的內網項目,推薦使用全自動的Hibernate框架,可以提高開發效率。
訪問量大性能要求高的內網項目或者互聯網項目,推薦使用Mybatis框架
1.1.1. 使用resultMap
由於上邊的mapper.xml中sql查詢列(user_id)和Order類屬性(userId)不一致,所以查詢結果不能映射到pojo中。
需要定義resultMap,把orderResultMap將sql查詢列(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自增主鍵返回