mybatis中關(guān)于mapper的使用以及注意事項(xiàng)
mybatis中mapper的使用及注意事項(xiàng)
這幾天在公司做項(xiàng)目,到了收尾的階段,但是發(fā)現(xiàn)自己在使用mybatis的時(shí)候給自己留下了很多的坑,于是乎花了兩天的時(shí)間來調(diào)試和重新構(gòu)思自己寫下的mapper.xml文件,總算是有些收獲,在這里分享給大家。
一、何為mapper.xml
mapper.xml是mybatis中的重要的組成部分,也算是核心之一,我們可以看到的就是他是由一些定義好的查詢數(shù)據(jù)庫的語句和一些xml規(guī)范定義好的。
我們?cè)谑褂胢ybatis的時(shí)候可以看到,在這里mapper文件相當(dāng)于是一個(gè)dao層接口的實(shí)現(xiàn),因?yàn)閙apper中定義的查詢,id都必須要和dao層的方法是一致的,這樣才可以進(jìn)行查詢。
這里最能體現(xiàn)mybatis特點(diǎn)的就是這個(gè)mapper配置文件了,因?yàn)閙ybatis能從里面的內(nèi)容讀取映射,生成sql語句進(jìn)行查詢。
二、mapper的寫法和注意事項(xiàng)
我們的mapper有很多種使用方法,這里簡(jiǎn)要說明與總結(jié)一下:
(1)、直接當(dāng)做sql語句使用
我們可以使用mapper中的<select><udpate><insert><delete>標(biāo)簽來拼接我們的sql語句,這里寫的標(biāo)簽為mybatis解析的頭,所以我們對(duì)應(yīng)的sql語句必須寫在對(duì)應(yīng)的標(biāo)簽下面,方可成功。
(2)、加判斷的條件查詢語句
在mapper中,我們可以對(duì)條件加上應(yīng)有的判斷,來進(jìn)行一些分條件的查詢,尤其是在where子句中,這里注意的是,使用判斷,也就是if也是一個(gè)標(biāo)簽為<if test=""></if> 其中在test中為if的判斷條件,這里的判斷就是一些取值的判斷,并沒有其他的作用但是寫法需要注意,可以直接使用Dao接口中傳下來的變量直接進(jìn)行判斷。
如下語句為增加了一個(gè)判斷用于拼接sql語句用的:
<if test='state=="0"'> ? ?AND t_acceptanceform.acceptancestate!='0' </if> <if test='state!=0'> ? ?AND t_acceptanceform.acceptancestate =#{state} </if>
這里就是在where中通過變量不同的條件來選擇不同的語句,使sql語句更加的靈活。
(3)、增加一些變量集合,用于查詢或者返回值
這里所指的變量集合其實(shí)是兩種,一種是map類型的集合,一種是sql中自定義查詢字段集合,我們?cè)谧龇祷刂颠€有mybatis自動(dòng)生成的代碼中常見的就是這種map集合,一般叫做resultmap,他是可以和pojo等類型的實(shí)體類進(jìn)行對(duì)應(yīng)的,用于對(duì)于查詢返回值的接收和發(fā)送,可以被mybatis機(jī)制自動(dòng)轉(zhuǎn)換為一些List集合或者其他的集合之類的東西。
格式:
<resultMap id="" type="" > ? ? <!--id為標(biāo)識(shí)這個(gè)map的唯一標(biāo)志,不能重復(fù),type為對(duì)應(yīng)到的pojo包路徑--> ? ? <id column="" property="" jdbcType="" /> ? ?<!--column是列名,property為對(duì)應(yīng)projo對(duì)象名,type就是數(shù)據(jù)庫中的類型--> ? ? <result column="" property="" jdbcType="" /> </resultMap>
第二個(gè)是<sql>標(biāo)簽為頭的一般查詢結(jié)果集,他的好處是可以自定義,也可以加入一些判斷,我們?cè)谧鰪?fù)雜查詢的時(shí)候一般可以用到他,下面是我寫的一個(gè)例子:
<sql id="outPutOrderDetail"> ?? ??? ?outputrepositorycode, ?? ??? ?outdate, ?? ??? ?consignee, ?? ??? ?ordersno, ?? ??? ?repocode, ?? ??? ?transferpath, ?? ??? ?acceptanceformcode, ?? ??? ?address, ?? ??? ?totalproducts, ?? ??? ?createtime, ?? ??? ?batchcount, ?? ??? ?comments, ?? ??? ?customerid, ? ? ? ? pitposition </sql>
使用的查詢:
<select id="queryOutPutHead" resultType="com.cn.echuxianshengshop.pojo.ext.OutPutOrderDetail"> ?? ?SELECT ?? ? <include refid="outPutOrderDetail"/> ?? ?FROM ?? ?t_outputorderb , t_acceptanceform ,t_orders ?? ?WHERE ?? ? ?ordercode=belongorderid AND ordercode=ordersNo AND outputrepositorycode=#{opCode} </select>
這里再附上軟件自動(dòng)生成的<sql >標(biāo)簽內(nèi)容,沒有仔細(xì)研究過里面的東西,但是用到了for循環(huán)和if,應(yīng)該就是邏輯判斷的一種,和寫條件都是差不多的。
<sql id="Example_Where_Clause" > ? ? <where > ? ? ? <foreach collection="oredCriteria" item="criteria" separator="or" > ? ? ? ? <if test="criteria.valid" > ? ? ? ? ? <trim prefix="(" suffix=")" prefixOverrides="and" > ? ? ? ? ? ? <foreach collection="criteria.criteria" item="criterion" > ? ? ? ? ? ? ? <choose > ? ? ? ? ? ? ? ? <when test="criterion.noValue" > ? ? ? ? ? ? ? ? ? and ${criterion.condition} ? ? ? ? ? ? ? ? </when> ? ? ? ? ? ? ? ? <when test="criterion.singleValue" > ? ? ? ? ? ? ? ? ? and ${criterion.condition} #{criterion.value} ? ? ? ? ? ? ? ? </when> ? ? ? ? ? ? ? ? <when test="criterion.betweenValue" > ? ? ? ? ? ? ? ? ? and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} ? ? ? ? ? ? ? ? </when> ? ? ? ? ? ? ? ? <when test="criterion.listValue" > ? ? ? ? ? ? ? ? ? and ${criterion.condition} ? ? ? ? ? ? ? ? ? <foreach collection="criterion.value" item="listItem" open="(" close=")" separator="," > ? ? ? ? ? ? ? ? ? ? #{listItem} ? ? ? ? ? ? ? ? ? </foreach> ? ? ? ? ? ? ? ? </when> ? ? ? ? ? ? ? </choose> ? ? ? ? ? ? </foreach> ? ? ? ? ? </trim> ? ? ? ? </if> ? ? ? </foreach> ? ? </where> ? </sql>
這里就是mybatis里面用于拼接查詢條件進(jìn)行查詢的一個(gè)拼接判斷,可以好好研究一下。
三、傳值的注意
我們都知道,在mapper中寫查詢的時(shí)候,我們都會(huì)用到一些查詢條件和傳入變量進(jìn)行關(guān)聯(lián)的事情,一般這種都用的是#{變量名}或者是${變量名}來做取值,那么他們到底有什么區(qū)別呢?
1、#{param}會(huì)產(chǎn)生PreparedStatement,并且可以安全地設(shè)置參數(shù)(=?)的值。以為sql語句已經(jīng)預(yù)編譯好了,傳入?yún)?shù)的時(shí)候,不會(huì)重新生產(chǎn)sql語句。安全性高。
2、${parem}則直接將{}號(hào)中的param插入字符串,會(huì)產(chǎn)生sql注入的問題:
例如:
select * from userwhere userName= ${userName}?
輸出的結(jié)果為
select * from userwhere userName= “小明”? ? ?
3、在特定場(chǎng)景下,例如如果在使用諸如order by '{param}',這時(shí)候就可以使用${}
4、#{}方式能夠很大程度防止sql注入,${}方式無法防止sql注入
5、${}方式一般用于傳入數(shù)據(jù)庫對(duì)象,例如傳入表名
字符串替換:
默認(rèn)情況下,使用#{}格式的語法會(huì)導(dǎo)致MyBatis創(chuàng)建預(yù)處理語句屬性并以它為背景設(shè)置安全的值(比如?)。這樣做很安全,很迅速也是首選做法,有時(shí)你只是想直接在SQL語句中插入一個(gè)不改變的字符串。
比如,像ORDER BY,你可以這樣來使用:
ORDER BY ${columnName}
這里MyBatis不會(huì)修改或轉(zhuǎn)義字符串。
重要:接受從用戶輸出的內(nèi)容并提供給語句中不變的字符串,這樣做是不安全的。這會(huì)導(dǎo)致潛在的SQL注入攻擊,因此你不應(yīng)該允許用戶輸入這些字段,或者通常自行轉(zhuǎn)義并檢查。
這里一定要注意的是,可以用#{param}的時(shí)候盡量不要用${param}。
mybatis通用mapper的使用
目前通用mapper只支持對(duì)單表的操作,對(duì)單表的增刪改查,無需在mapper.xml寫對(duì)應(yīng)的sql語句,只需要我們調(diào)用相應(yīng)的接口,對(duì)于快速開發(fā)極為方便。
1.首先在maven項(xiàng)目,在pom.xml中引入mapper的依賴
<dependency> ?? ?<groupId>tk.mybatis</groupId> ?? ?<artifactId>mapper</artifactId> ?? ?<version>3.3.8</version> </dependency>
2.Spring配置文件中加入掃描路徑
<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer"> ?? ?<property name="basePackage" value="com.xinnet.**.mapper" /> ?? ?<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> </bean>
3.實(shí)體類設(shè)置主鍵
@Table(name = "op_virtual_ip") public class VirtualIpBean { ? ? ? //主鍵 ? ? @Id ? ? Long id; ? ? ? ?@Column ? ? ? ?String data; }
4.業(yè)務(wù)mapper接口繼承通用mapper,并只定實(shí)體泛型
import tk.mybatis.mapper.common.Mapper; public interface IVirtualIPMapper extends Mapper<VirtualIpBean> { }
5.業(yè)務(wù)mapper接口的實(shí)際使用
import java.util.Date; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import tk.mybatis.mapper.entity.Example; @Service public class VirtualIpService { ? @Autowired ? IVirtualIPMapper vipMapper; ? public void test(){ ? ? VirtualIpBean vipBean = new VirtualIpBean(); ? ? vipBean.setBeginTime(new Date()); ? ? //(1)mapper基礎(chǔ)接口 ? ? //select接口 ? ? ? List<VirtualIpBean> vipList = vipMapper.select(vipBean);//根據(jù)實(shí)體中的屬性值進(jìn)行查詢,查詢條件使用等號(hào) ? ? VirtualIpBean vip = vipMapper.selectOne(vipBean);//根據(jù)實(shí)體中的屬性進(jìn)行查詢,只能有一個(gè)返回值,有多個(gè)結(jié)果是拋出異常,查詢條件使用等號(hào) ? ? List<VirtualIpBean> vipList2 = vipMapper.selectAll();//查詢?nèi)拷Y(jié)果,select(null)方法能達(dá)到同樣的效果 ? ? VirtualIpBean vip2 = vipMapper.selectByPrimaryKey(1);//根據(jù)主鍵字段進(jìn)行查詢,方法參數(shù)必須包含完整的主鍵屬性,查詢條件使用等號(hào) ? ? int count = vipMapper.selectCount(vipBean);//根據(jù)實(shí)體中的屬性查詢總數(shù),查詢條件使用等號(hào) ? ? //insert接口 ? ? int a = vipMapper.insert(vipBean);//保存一個(gè)實(shí)體,null的屬性也會(huì)保存,不會(huì)使用數(shù)據(jù)庫默認(rèn)值 ? ? int a1 = vipMapper.insertSelective(vipBean);//保存實(shí)體,null的屬性不會(huì)保存,會(huì)使用數(shù)據(jù)庫默認(rèn)值 ? ? //update接口 ? ? int b = vipMapper.updateByPrimaryKeySelective(vipBean);//根據(jù)主鍵更新屬性不為null的值 ? ? int c = vipMapper.updateByPrimaryKey(vipBean);//根據(jù)主鍵更新實(shí)體全部字段,null值會(huì)被更新 ? ? //delete接口 ? ? int d = vipMapper.delete(vipBean);//根據(jù)實(shí)體屬性作為條件進(jìn)行刪除,查詢條件使用等號(hào) ? ? int e = vipMapper.deleteByPrimaryKey(1);//根據(jù)主鍵字段進(jìn)行刪除,方法參數(shù)必須包含完整的主鍵屬性 ? ? //(2)Example方法 ? ? Example example = new Example(VirtualIpBean.class); ? ? example.createCriteria().andEqualTo("id", 1); ? ? example.createCriteria().andLike("val", "1"); ? ? //自定義查詢 ? ? List<VirtualIpBean> vipList3 = vipMapper.selectByExample(example); ? } }
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java redisTemplate阻塞式處理消息隊(duì)列
用redis中的List可以實(shí)現(xiàn)隊(duì)列,這樣可以用來做消息處理和任務(wù)調(diào)度的隊(duì)列。因此,本文將主要為大家介紹如何利用redisTemplate處理消息隊(duì)列,感興趣的小伙伴可以了解一下2021-12-12Spring Boot RabbitMQ 延遲消息實(shí)現(xiàn)完整版示例
本篇文章主要介紹了Spring Boot RabbitMQ 延遲消息實(shí)現(xiàn)完整版示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-05-05spring boot 2.x html中引用css和js失效問題及解決方法
這篇文章主要介紹了spring boot 2.x html中引用css和js失效,需要的朋友可以參考下2018-11-11elasticsearch索引index之Mapping實(shí)現(xiàn)關(guān)系結(jié)構(gòu)示例
這篇文章主要介紹了elasticsearch索引index之Mapping實(shí)現(xiàn)關(guān)系結(jié)構(gòu)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04SpringBoot如何使用applicationContext.xml配置文件
這篇文章主要介紹了SpringBoot使用applicationContext.xml配置文件,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06spring + shiro + cas 實(shí)現(xiàn)sso單點(diǎn)登錄的示例代碼
本篇文章主要介紹了spring + shiro + cas 實(shí)現(xiàn)sso單點(diǎn)登錄的示例代碼,具有一定的參考價(jià)值,有興趣的可以了解一下2017-09-09