MyBatis學習總結(02)
今日大綱
- 動態sql
- 快取
- 介面繫結
- 或者叫動態代理
ResultType
1、動態sql
相當於條件查詢,在程式碼中使用if語句來拼裝sql語句,它會造成資源浪費,而且,不易於維護。If、switch語句是Java程式碼之罪。
在寫sql語句的時候,直接進行拼裝。
特殊字元轉義
< < 小於
> > 大於
& & 和號
' ' 省略號
" " 引號
< if>標籤:
標籤,相當於程式碼中的if(){}else{}
它幫我們做資料判斷
<select id="getUsers" resultType="user">
select * from t_user
where 1=1
<if test="name != null and name !='' ">
and name = #{name}
</if>
<if test="pwd !=null and pwd !='' ">
and pwd =#{pwd}
</if>
<if test="age > 23">
and name ='王思聰'
</if>
</select>
< where>標籤
標籤就想到與sql語句中where條件,當where標籤內的if判斷條件執行,才執行where標籤,如果if不執行,where也不執行,所以 1=1 就省略掉了。
Where標籤,會自動判斷sql語句,如果第一個and開始的,就省略掉,一般情況下,在if判斷條件中都加and關鍵字。
<select id="getUsers" resultType="user">
select * from t_user
<where>
<if test="name != null and name !='' ">
and name = #{name}
</if>
<if test="pwd !=null and pwd !='' ">
and pwd =#{pwd}
</if>
<if test="age > 23">
and name ='王思聰'
</if>
</where>
</select>
< choose>標籤
標籤就相當於程式碼中switch,標籤:當條件滿足的時候執行when標籤內容,當所有的when標籤內容不滿足時,執行預設標籤中的內容。
<select id="getUsers1" resultType="user">
select * from t_user
<where>
<choose>
<when test="name != null and name !=''">
and name= #{name}
</when>
<otherwise>
and age > 23
</otherwise>
</choose>
</where>
</select>
< sql >和< include >
標籤:用於定義sql語句
標籤:用於引用標籤定義的sql語句,這個引用可以在sql語句的任何位置
<sql id="select">
id,name,pwd
</sql>
<sql id="from">
from t_user
</sql>
<select id="getUsers2" resultType="user">
<!-- select * from t_user t where t.id in(select id from t_user1 where name =?)
sql:語句的拆分,一般不用於單表操作,一般用於多表操作
include:引用sql語句,可以在任何位置
-->
select
<include refid="select"/>
<include refid="from"/>
</select>
< bind>標籤
標籤用於給引數追加資料,隨便新增
<select id="getUserByName" resultType="user">
<!-- bind:給引數追加內容,寫的方式 '%'+name+'%'
現在講引數進行追加,然後再進行資料判斷
如果引數為空:會報錯
-->
<bind name="name" value="name+'123'"/>
select * from t_user
<where>
<if test="name != null and name!='' ">
name like #{name}
</if>
</where>
</select>
< set>標籤
標籤主要用於update語句。相對於update語句中set關鍵字,它會自動消除多餘的”,”
<!-- set 標籤應用-->
<update id="updateUser">
<!-- update t_user set name=? and pwd=? where id =? -->
update t_user
<set>
<if test="name != null and name !=''">
name = #{name},
</if>
<if test="pwd != null and pwd !='' ">
pwd = #{pwd}
</if>
</set>
<where>
id=#{id}
</where>
</update>
< foreach>標籤
< foreach>標籤,主要用迴圈遍歷,
Select * from t_user where id in(name),name就可以使用foreach
<!-- foreach應用 -->
<select id="findUsers" resultType="user">
select * from t_user
<where>
id in
<!--
collection:集合物件
open:指的是以什麼開始
close:指的是以什麼結尾,與open成對出現
separator:指的資料以什麼進行分割
item:指的遍歷的資料項
mybatis的會自動給string資料新增'',不需要我們手動新增
-->
<foreach collection="list" open="(" separator="," close=")" item="ids">
#{ids}
</foreach>
</where>
</select>
<select id="findUsersByName" resultType="user">
select * from t_user
<where>
name in
<foreach collection="list" open="(" separator="," close=")" item="names">
#{names}
</foreach>
</where>
</select>
< trim>標籤
< trim>標籤在mybatis裡面是去除and|or|,
<select id="queryUsers" resultType="user">
select * from t_user
<!--
prefix:字首
suffix:字尾
prefixOverrides:字首結束,去掉and|or關鍵字
suffixOverrides:字尾結束,去掉and|or關鍵字
<where><set>本身自帶了去掉and|or|,的功能
-->
<trim prefix="WHERE" prefixOverrides="AND|OR">
<if test="name != null and name !='' ">
and name = #{name}
</if>
<if test="pwd !=null and pwd !='' ">
and pwd =#{pwd}
</if>
<if test="age > 23">
and name ='王思聰'
</if>
</trim>
</select>
簡單型別傳遞引數
<!-- 簡單型別引數傳遞:現在一次傳遞多個引數
如果是多個簡單型別的引數使用[param引數下標從1開始]
在佔位符中的name值是:[param引數下標從1開始],不是引數名稱
-->
<select id="findUsersByParam" resultType="user">
select * from t_user
<where>
<if test="param1 != null and param1 !='' ">
and name = #{param1}
</if>
<if test="param2 !=null and param2 !='' ">
and pwd =#{param2}
</if>
<if test="param3 > 23">
and name ='王思聰'
</if>
</where>
</select>
<!-- 簡單型別引數傳遞:一次傳遞一個引數
作為判斷條件的時候:使用_parameter來進行判斷
佔位符中應用還是引數名稱
-->
<select id="findUsersByParam1" resultType="user">
select * from t_user
<where>
<if test="_parameter != null and _parameter != ''">
name = #{name}
</if>
</where>
</select>
介面類:
public interface UserMapper {
List<User> getUsers(Map<String, Object> map);
List<User> getUsers1(User user);
List<User> getUsers2();
List<User> getUserByName(User user);
int updateUser(User user);
List<User> findUsers(List<Integer> ids);
List<User> findUsersByName(List<String> names);
List<User> queryUsers(User user);
List<User> findUsersByParam(String name,String pwd, Integer age);
List<User> findUsersByParam1(String name);
}
測試類:
package com.bjsxt.test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.bjsxt.mapper.UserMapper;
import com.bjsxt.pojo.User;
import com.bjsxt.utils.MybatisUtil;
public class TestMybatis {
private SqlSession session ;
@Before
public void getSession(){
session = MybatisUtil.getSession();
}
@After
public void closeSession(){
MybatisUtil.closeSession();
}
/**
*
* @Description: foreach應用
* @author mao
* @date 2017年10月11日
*/
@Test
public void findUsers(){
UserMapper mapper = session.getMapper(UserMapper.class);
List<Integer> ids = new ArrayList<>();
ids.add(2);
ids.add(3);
ids.add(6);
ids.add(7);
List<User> findUsers = mapper.findUsers(ids);
for (User user : findUsers) {
System.out.println(user);
}
}
@Test
public void findUsersByName(){
UserMapper mapper = session.getMapper(UserMapper.class);
List<String> names = new ArrayList<>();
names.add("王二麻子");
names.add("張三丰");
List<User> findUsersByName = mapper.findUsersByName(names);
for (User user : findUsersByName) {
System.out.println(user);
}
}
@Test
public void queryUsers(){
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
user.setName("王二麻子");
List<User> queryUsers = mapper.queryUsers(user);
for (User user2 : queryUsers) {
System.out.println(user2);
}
}
/**
*
* @Description: 簡單型別引數傳遞:多個簡單型別
* @author mao
* @date 2017年10月11日
*/
@Test
public void findUsersByParam(){
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> findUsersByParam = mapper.findUsersByParam("王二麻子", "12345", 22);
for (User user : findUsersByParam) {
System.out.println(user);
}
}
@Test
public void findUsersByParam1(){
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> findUsersByParam1 = mapper.findUsersByParam1("王二麻子");
for (User user : findUsersByParam1) {
System.out.println(user);
}
}
@Test
public void getUsers(){
/**
* 模糊查詢
* 字元拼接查詢
* 使用程式碼進行模糊查詢,它效率很低
* if(){}else{}稱之為程式碼之罪
* mybatis提供了動態sql,可以在sql中直接使用一些判斷條件
*/
StringBuffer sb = new StringBuffer();
sb.append("select * from t_user where 1=1 ");
User user = new User();
if(user.getName() !=null){
sb.append(" and name= XXX");
}
if(user.getPwd() != null){
sb.append(" and pwd=XXX");
}
//執行sql
}
@Test
public void getUserDymic(){
UserMapper mapper = session.getMapper(UserMapper.class);
Map<String, Object> map = new HashMap<>();
map.put("name", "王二麻子");
// map.put("pwd", "12345");
// map.put("age", 26);
List<User> users = mapper.getUsers(map);
for (User user : users) {
System.out.println(user);
}
}
@Test
public void getUsers1(){
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
//user.setName("王二麻子");
List<User> users1 = mapper.getUsers1(user);
for (User user2 : users1) {
System.out.println(user2);
}
}
@Test
public void getUsers3(){
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> users2 = mapper.getUsers2();
for (User user : users2) {
System.out.println(user);
}
}
@Test
public void getUserByName(){
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
user.setName("張");
List<User> userByName = mapper.getUserByName(user);
for (User user2 : userByName) {
System.out.println(user2);
}
}
@Test
public void updateUser(){
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
user.setName("張666");
//user.setPwd("456");
user.setId(3);
int updateUser = mapper.updateUser(user);
session.commit();
System.out.println(updateUser);
}
}
Sql拼接:
1.Java程式碼
2.Mybatis提供的動態sql
3.不使用Java程式碼和mybatis提供的動態sql:主要用報表
報表:經過封裝後,還是jsp或者html,直接操作資料庫,在報表工具中直接寫的是sql語句。
<!-- 不使用Java程式碼 和 mybatis的標籤拼接sql查詢資料庫資料 -->
<select id="getUsersByParams" resultType="user">
select * from t_user
where
(#{name} is null or name= #{name})
and (#{pwd} is null or pwd = #{pwd})
</select>
測試:
public void getUsers6(){
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
user.setName("王二麻子");
List<User> usersByParams = mapper.getUsersByParams(user);
for (User user2 : usersByParams) {
System.out.println(user2);
}
}
快取:
就是將資料放到記憶體中,電商專案,它的很多資料都是放在快取中的。提高查詢效率。但是mybatis的快取做的不好,有大量資料冗餘。
一級快取
一級快取:SqlSession,預設開啟的,直接使用。
查詢一條資料,又查詢同樣的一條資料,執行sql語句,查詢第一條資料的時候,已經將資料放到一級快取裡面,在Sqlsession 沒有關閉的情況下,查詢同樣的一條資料是從是快取獲取,不執行sql語句。
是依據 對映檔案中標籤中id屬性值進行快取(statementid進行快取的)
@Test
public void getUserById(){
UserMapper mapper = session.getMapper(UserMapper.class);
Map<String, Object> map = new HashMap<>();
map.put("id", 3);
User userById = mapper.getUserById(map);
System.out.println(userById);
Map<String, Object> map1 = new HashMap<>();
map1.put("id", 3);
User userById1 = mapper.getUserById2(map1);
System.out.println(userById1);
}
配置檔案:
<select id="getUserById" resultType="user">
select * from t_user where id = #{id}
</select>
<select id="getUserById2" resultType="user">
select * from t_user where id = #{id}
</select>
二級快取
二級快取:SqlSessionFactory,開啟需要在對映檔案中進行配置
MyBatis 包含一個非常強大的查詢快取特性,它可以非常方便地配置和定製。MyBatis 3 中的快取實現的很多改進都已經實現了,使得它更加強大而且易於配置。
預設情況下是沒有開啟快取的,除了區域性的 session 快取,可以增強變現而且處理迴圈依賴也是必須的。要開啟二級快取,你需要在你的 SQL 對映檔案中新增一行:
對映語句檔案中的所有 select 語句將會被快取。
對映語句檔案中的所有 insert,update 和 delete 語句會重新整理快取。
快取會使用 Least Recently Used(LRU,最近最少使用的)演算法來收回。
根據時間表(比如 no Flush Interval,沒有重新整理間隔), 快取不會以任何時間順序 來重新整理。
快取會儲存列表集合或物件(無論查詢方法返回什麼)的 1024 個引用。
快取會被視為是 read/write(可讀/可寫)的快取,意味著物件檢索不是共享的,而且可以安全地被呼叫者修改,而不干擾其他呼叫者或執行緒所做的潛在修改。
<?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:相當於包的概念
要保證在一個對映檔案中,保證statementid為唯一
-->
<mapper namespace="com.bjsxt.mapper.UserMapper">
<!--
<if>標籤:相當於java程式碼中的if語句
if:簡單型別傳遞
if標籤:Java程式碼中的if判斷條件 使用的是 && ||
在if標籤中使用的是 and
-->
<select id="getUsers" resultType="user">
select * from t_user
where 1=1
<if test="_parameter != null and _parameter !='' ">
and name like #{name}
</if>
</select>
<!-- if語句的:物件和集合型別傳遞 -->
<select id="getUsers1" resultType="user">
select * from t_user
where 1=1
<if test="name != null and name !='' ">
and name like #{name}
</if>
</select>
<!-- if語句:多個判斷條件,
where標籤:去掉sql語句的where關鍵字
mybatis會自動的進行判斷,再進行刪除
它會自動判斷,它內部的語句第一個 關鍵字是否是and 如果是,自動的去掉
所以,一般使用where標籤,它內部的所有if判斷條件都新增and關鍵字
-->
<select id="getUsers2" resultType="user">
select * from t_user
<where>
<if test="name != null and name !='' ">
and name like #{name}
</if>
<if test="age > 33">
and age > 33
</if>
</where>
</select>
<!--
choose標籤:就相當於Java程式碼中的switch語句,當一個條件成立的話,後面的所有判斷條件都不執行
switch(falg){
case falg:xxx; ==> when
case falg:xxx; ==> when
default: ==》otherwise
XXX;
}
-->
<select id="getUsers3" resultType="user">
select * from t_user
<where>
<choose>
<when test="name != null and name != ''">
and name like #{name}
</when>
<when test="age > 33">
and age > 33
</when>
<otherwise>
and pwd ='zhangsanf'
</otherwise>
</choose>
</where>
</select>
<!--
bind標籤:相當於字串拼接,它可以在引數的前後新增內容
name屬性值:引數名稱
value屬性值:對引數進行改造
-->
<select id="getUsers4" resultType="user">
<bind name="name" value="'%'+name+'%'"/>
<!--
先進行資料新增,再進行資料判斷,
引數為空,會報錯,bind報錯
-->
select * from t_user
<where>
<if test="name != null and name != ''">
and name like #{name}
</if>
</where>
</select>
<!--
set標籤:它就相當於 update語句set關鍵字,set關鍵字對自動去掉,號
-->
<update id="updateUser">
<!-- update t_user set name=#{name} , age =#{age} where id=#{id} -->
update t_user
<set>
<if test="name != null and name != ''">
name=#{name},
</if>
<if test="age != null">
age=#{age},
</if>
</set>
<where>
<if test="id != null">
id=#{id}
</if>
</where>
</update>
<!-- foreach標籤:相當於Java程式碼中的for迴圈
需求:查詢該集合中主鍵的值
collection:指的是集合物件,對應的傳遞過來的引數集合型別
open:以什麼開始
separator:資料以什麼分割
close:以什麼結尾,與open成單出現
item:引數名稱,對應傳遞過來的引數名稱
如果遍歷的是string型別,mybatis會自動的新增''號,不需要我們手動新增
-->
<select id="getUsers5" resultType="user">
select * from t_user
<where>
id in
<foreach collection="list" open="(" separator="," close=")" item="ids">
#{ids}
</foreach>
</where>
</select>
<select id="getUsers6" resultType="user">
select * from t_user
<where>
name in
<foreach collection="list" open="(" separator="," close=")" item="names">
#{names}
</foreach>
</where>
</select>
<!--
trim標籤:
-->
<select id="getUsers7" resultType="user">
select * from t_user
<!--
prefix:字首
prefixOverrides:字首以什麼結束
suffix:後置
suffixOverrides:後置以什麼結束
-->
<trim prefix="WHERE" prefixOverrides="AND|OR">
<if test="name != null and name != ''">
and name like #{name}
</if>
<if test="age > 33">
and age > 33
</if>
</trim>
</select>
<!--
<sql>標籤:在外部定義sql語句
<include>標籤:在內部引用sql語句
可以拼裝成一個完成的sql語句,
一般當sql語句量很大得時候,進行使用
-->
<sql id="select">
select id,name,pwd,age
</sql>
<sql id="from">
from t_user
</sql>
<select id="getUser8" resultType="user">
<include refid="select"/>
<include refid="from"/>
</select>
<update id="updateUser3">
update t_user set
name = #{0},age=#{1}
where id= #{2}
</update>
</mapper>
介面:
public interface UserMapper {
List<User> getUsers(String name);
List<User> getUsers1(User User);
List<User> getUsers2(Map<String, Object> map);
List<User> getUsers3(Map<String, Object> map);
int updateUser(Map<String, Object> map);
int updateUser3(String name,Integer age,Integer id);
}
實現類:
/**
*
* @Description:介面代理
* @author mao
* @date 2017年10月30日
*/
@Test
public void getUsers(){
//IUserDao userDao = new UserDaoImpl();
/**
* mybatis的通過getMapper來實現自動建立mapper介面的實現類
* mapper.getUsers==》mybatis的session.selectList();
*/
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> users = mapper.getUsers("%張%");
// List<User> users = session.selectList("getUsers","%張%");
for (User user : users) {
System.out.println(user);
}
}
/**
*
* @Description:
* @author mao
* @date 2017年10月30日
*/
@Test
public void getUsers1(){
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
user.setName("%張%");
List<User> users1 = mapper.getUsers1(user);
for (User user2 : users1) {
System.out.println(user2);
}
}
/**
*
* @Description:介面實現修改
* @author mao
* @date 2017年10月30日
*/
@Test
public void updataUser(){
UserMapper mapper = session.getMapper(UserMapper.class);
Map<String, Object> map = new HashMap<>();
map.put("name", "陳二狗");
map.put("age", 33);
map.put("id", 100);
int updateUser = mapper.updateUser(map);
System.out.println(updateUser);
session.commit();
}
/**
*
* @Description:傳遞多個簡單型別引數
* 在statement中接收引數使用:引數的下標或者param1
* 引數下邊從0開始
* param[args] :[args]使用1開始;例如:param1
* @author mao
* @date 2017年10月30日
*/
@Test
public void updateUser1(){
UserMapper mapper = session.getMapper(UserMapper.class);
int updateUser3 = mapper.updateUser3("田876", 33, 100);
System.out.println(updateUser3);
session.commit();
}
/**
*
*/
@Test
public void getUsers2(){
List<User> selectList = session.selectList("com.bjsxt.mapper.UserMapper.getUsers","%張%");
for (User user : selectList) {
System.out.println(user);
}
}
}
ResultType
對映檔案中的statement中的resultType;
resultType:物件型別、簡單型別、集合型別
配置檔案:
<!--
namespace:相當於包的概念
要保證在一個對映檔案中,保證statementid為唯一
-->
<mapper namespace="com.bjsxt.mapper.UserMapper">
<select id="getUsers" resultType="user">
select * from t_user
</select>
<!--resultType返回簡單型別 -->
<select id="getUsers1" resultType="int">
select id,name,pwd from t_user
</select>
<!--resultType返回集合型別 -->
<select id="getUsers2" resultType="map">
select id,name,pwd from t_user where name like #{_parameter}
</select>
</mapper>
介面:
public interface UserMapper {
List<User> getUsers();
List<Integer> getUsers1();
List<Map<Object, Object>> getUsers2(String name);
}
實現類:
/**
*
* @Description:resultType返回值為物件型別
* @author mao
* @date 2017年10月30日
*/
@Test
public void getUsers(){
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> users = mapper.getUsers();
for (User user : users) {
System.out.println(user);
}
}
/**
*
* @Description:resultType返回簡單型別
* 1.在statement中的resultType中設定返回值型別
* 2.在sql語句中 ,如果查詢欄位有多個,要保證第一個欄位與返回值型別一致
* @author mao
* @date 2017年10月30日
*/
@Test
public void getUsers1(){
UserMapper mapper = session.getMapper(UserMapper.class);
List<Integer> users1 = mapper.getUsers1();
for (Integer integer : users1) {
System.out.println(integer);
}
}
/**
*
* @Description:resultType返回map集合型別
* 1.介面中定義的方法返回值是Map集合
* @author mao
* @date 2017年10月30日
*/
@Test
public void getUsers2(){
UserMapper mapper = session.getMapper(UserMapper.class);
List<Map<Object, Object>> users2 = mapper.getUsers2("%張%");
for (Map<Object, Object> map : users2) {
System.out.println(map);
}
}