MyBatis框架基本操作及進階部分
1、基本操作
- 1 pom.xml
java 7行
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
GAV座標
- 2配置檔案 mybatis-config.xml 連線資料庫 url, driver, username, password
java 2行
<mapper resource="包名/XXMapper.xml" />
- 3 對映檔案 XXMapper.xml
java 8行
<mapper namespace="包名.XXMapper"> // 防止命名衝突 <insert id="insert" parameterType="實體型別"> 插入sql, #{實體屬性值} </insert> <update id="update" parameterType="實體型別"> 更新sql, #{實體屬性值} </update> <delete id="delete" parameterType="基本型別"> 刪除sql, #{任意字串} </delete> <select id="查詢單個" parameterType="查詢條件型別" resultType="實體型別"> 查詢sql </select> <select id="查詢多個" parameterType="查詢條件型別" resultType="實體型別"> 查詢sql </select> </mapper>
- 4 java 程式碼
java 10行
SqlSessionFactory factory = new SqlSessionFactoryBuilder(配置檔案的輸入流); SqlSession sqlSession = factory.openSession(); sqlSession.insert("namespace.id", 引數物件); sqlSession.update("namespace.id", 引數物件); sqlSession.delete("namespace.id", 引數物件); 實體型別 obj = sqlSession.selectOne("namespace.id", 引數物件); // 查詢單個結果 List<實體型別> obj = sqlSession.selectList("namespace.id", 引數物件); // 查詢單個結果 sqlSession.commit(); // 提交事務 sqlSession.close(); // 關閉資源
===============================================================
2、mybatis 進階內容
2.1 新增操作
sql 6行
create table student(
id int primary key auto_increment,
name varchar(20),
age int
);
怎麼獲取自增長的值
xml 11行
<!--
將資料庫插入後生成的id值,同步到java物件上
useGeneratedKeys="是否使用由資料庫生成的主鍵"
keyColumn="主鍵列的名稱"
keyProperty="主鍵要存入哪個屬性"
-->
<insert id="insert" parameterType="com.westos.entity.Student"
useGeneratedKeys="true" keyColumn="id" keyProperty="id">
insert into student (id, name) values (null, #{name})
</insert>
2.2 動態sql1 foreach
刪除操作:一次刪除多條記錄 delete from student where id in(1); delete from student where id in(1, 2); delete from student where id in(1, 2, 3); // java.util.List -> 簡寫為 list
xml 15行
<!-- list (1,2,3)
collection="要遍歷的集合"
item="臨時變數名稱"
open="迴圈之前的符號"
close="迴圈之後的符號"
separator="每個元素的分隔符"
delete from student where id in (1, 2, 3)
-->
<delete id="delete" parameterType="list">
delete from student where id in
<foreach collection="list" item="i" open="(" close=")" separator=",">
#{i}
</foreach>
</delete>
2.3 動態sql2 if
按照姓名模糊查詢,年齡範圍查詢 Map map = ... map.put("name", "張%"); map.put("minAge", 10); map.put("maxAge", 20); select * from student where name=#{name} select * from student where age between #{minAge} and #{maxAge} select * from student where name=#{name} and age between #{minAge} and #{maxAge} select * from student // java.util.Map 簡寫為 map
xml 12行
<select id="selectByCondition" parameterType="map" resultType="com.westos.entity.Student">
select * from student
<where>
<if test="name != null">
and name=#{name}
</if>
<if test="minAge != null && maxAge != null">
and age between #{minAge} and #{maxAge}
</if>
</where>
</select>
動態更新 update student set name=#{}, age=#{} where id=#{} 希望實現修改哪列就在update中出現響應的set語句,而不是出現所有的列 update student set name=#{} wehre id=#{} update student set age=#{} wehre id=#{}
xml 13行
<update id="update" parameterType="com.westos.entity.Student">
update student
<set>
<if test="name != null">
name = #{name},
</if>
<if test="age != 0">
age = #{age},
</if>
</set>
where id = #{id}
</update>
2.4 分頁查詢
limit 下標, 數量 方法1:物理分頁(使用sql語句實現分頁) 缺點:不通用,資料庫不同sql語法有差異: mysql, limit sqlserver, top, row_number() oracle, rownum
xml 8行
<!-- map
.put("m", 下標);
.put("n", 數量);
-->
<select id="selectByPage" parameterType="map" resultType="com.westos.entity.Student">
select * from student limit #{m}, #{n}
</select>
方法2:邏輯分頁(把所有記錄都查出來,用jdbc程式碼實現分頁) 優點:通用,sql程式碼都是查詢所有 效率低,適合資料很少的情況
xml 5行
<!-- 邏輯分頁 -->
<select id="selectLogical" resultType="com.westos.entity.Student">
select * from student
</select>
java 7行
// rowBounds一定要作為第三個引數
List<Student> list = sqlSession.selectList("com.westos.mapper.StudentMapper.selectLogical", null,
new RowBounds(5, 5));
for (Student student : list) {
System.out.println(student);
}
2.5 表和實體類不匹配
create table teacher ( id int primary key auto_increment, first_name varchar(20), last_name varchar(20) );
xml 5行
<!-- 方法1: 可以使用列別名來解決不一致問題 -->
<select id="selectOne" parameterType="int" resultType="com.westos.entity.Teacher">
select id,first_name firstName,last_name lastName from teacher where id = #{id}
</select>
xml 16行
<!-- 方法2: 使用 resultMap 代替 resultType完成對映 -->
<select id="selectOne" parameterType="int" resultMap="aaa">
select id, first_name, last_name from teacher where id = #{id}
</select>
<!-- type="實體物件的型別"
id 標籤用來對映主鍵
result 標籤用來對映其它列
-->
<resultMap id="aaa" type="com.westos.entity.Teacher">
<!-- column="列名" property="屬性名" -->
<id column="id" property="id"></id>
<result column="first_name" property="firstName"></result>
<result column="last_name" property="lastName"></result>
</resultMap>
2.6 連線查詢的對映
商品和類別 select * from product p inner join category c on p.category_id = c.idwhere p.id=1;
xml 18行
<!-- 把連線查詢對映到兩個有關係的實體類上 -->
<select id="selectById" parameterType="int" resultMap="bbb">
select p.id, p.name, p.price, c.id cid, c.name cname
from product p inner join category c on p.category_id = c.id where p.id=#{id}
</select>
<!-- association 關聯 -->
<resultMap id="bbb" type="com.westos.entity.Product">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<result column="price" property="price"></result>
<!-- property="關係屬性名" -->
<association property="category" javaType="com.westos.entity.Category">
<id column="cid" property="id"></id>
<result column="cname" property="name"></result>
</association>
</resultMap>
2.7 mybatis中的快取
-
一級快取 每個sqlsession都有一個一級快取,只要sql語句和引數相同,只有第一次查詢資料庫,並且會把查詢結果放入一級快取 之後的查詢,就直接從一級快取中獲取結果
一級快取的作用範圍,只限於一個sqlsession
-
二級快取 所有sqlSession共享的快取
一級快取無需配置,而二級快取需要配置
二級快取的意義是減少與資料庫的互動,從而提升程式的效能
-
快取失效 只要是執行了增,刪,改的操作,快取就應該失效,仍然從資料庫查詢得到最新結果
-
二級快取適用場景 當資料的查詢遠遠多於修改時, 才有啟用二級快取的必要
2.8 #{}
與 ${}
的區別
區別1:#{}
生成的sql語句是用?佔位符的方式, 可以防止sql注入攻擊${}
生成的sql語句是直接把值進行了字串的拼接, 有注入攻擊漏洞
區別2:${}
可以進行運算 #{}
不能運算
區別3:#{}
在sql語句中只能替換值, 不能是表名,列名,關鍵字${}
可以替換sql語句的任意部分