mybatis中關(guān)于mapper的使用以及注意事項(xiàng)
mybatis中mapper的使用及注意事項(xiàng)
這幾天在公司做項(xiàng)目,到了收尾的階段,但是發(fā)現(xiàn)自己在使用mybatis的時候給自己留下了很多的坑,于是乎花了兩天的時間來調(diào)試和重新構(gòu)思自己寫下的mapper.xml文件,總算是有些收獲,在這里分享給大家。
一、何為mapper.xml
mapper.xml是mybatis中的重要的組成部分,也算是核心之一,我們可以看到的就是他是由一些定義好的查詢數(shù)據(jù)庫的語句和一些xml規(guī)范定義好的。
我們在使用mybatis的時候可以看到,在這里mapper文件相當(dāng)于是一個dao層接口的實(shí)現(xiàn),因?yàn)閙apper中定義的查詢,id都必須要和dao層的方法是一致的,這樣才可以進(jìn)行查詢。
這里最能體現(xiàn)mybatis特點(diǎn)的就是這個mapper配置文件了,因?yàn)閙ybatis能從里面的內(nèi)容讀取映射,生成sql語句進(jìn)行查詢。
二、mapper的寫法和注意事項(xiàng)
我們的mapper有很多種使用方法,這里簡要說明與總結(jié)一下:
(1)、直接當(dāng)做sql語句使用
我們可以使用mapper中的<select><udpate><insert><delete>標(biāo)簽來拼接我們的sql語句,這里寫的標(biāo)簽為mybatis解析的頭,所以我們對應(yīng)的sql語句必須寫在對應(yīng)的標(biāo)簽下面,方可成功。
(2)、加判斷的條件查詢語句
在mapper中,我們可以對條件加上應(yīng)有的判斷,來進(jìn)行一些分條件的查詢,尤其是在where子句中,這里注意的是,使用判斷,也就是if也是一個標(biāo)簽為<if test=""></if> 其中在test中為if的判斷條件,這里的判斷就是一些取值的判斷,并沒有其他的作用但是寫法需要注意,可以直接使用Dao接口中傳下來的變量直接進(jìn)行判斷。
如下語句為增加了一個判斷用于拼接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中自定義查詢字段集合,我們在做返回值還有mybatis自動生成的代碼中常見的就是這種map集合,一般叫做resultmap,他是可以和pojo等類型的實(shí)體類進(jìn)行對應(yīng)的,用于對于查詢返回值的接收和發(fā)送,可以被mybatis機(jī)制自動轉(zhuǎn)換為一些List集合或者其他的集合之類的東西。
格式:
<resultMap id="" type="" > ? ? <!--id為標(biāo)識這個map的唯一標(biāo)志,不能重復(fù),type為對應(yīng)到的pojo包路徑--> ? ? <id column="" property="" jdbcType="" /> ? ?<!--column是列名,property為對應(yīng)projo對象名,type就是數(shù)據(jù)庫中的類型--> ? ? <result column="" property="" jdbcType="" /> </resultMap>
第二個是<sql>標(biāo)簽為頭的一般查詢結(jié)果集,他的好處是可以自定義,也可以加入一些判斷,我們在做復(fù)雜查詢的時候一般可以用到他,下面是我寫的一個例子:
<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>這里再附上軟件自動生成的<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)行查詢的一個拼接判斷,可以好好研究一下。
三、傳值的注意
我們都知道,在mapper中寫查詢的時候,我們都會用到一些查詢條件和傳入變量進(jìn)行關(guān)聯(lián)的事情,一般這種都用的是#{變量名}或者是${變量名}來做取值,那么他們到底有什么區(qū)別呢?
1、#{param}會產(chǎn)生PreparedStatement,并且可以安全地設(shè)置參數(shù)(=?)的值。以為sql語句已經(jīng)預(yù)編譯好了,傳入?yún)?shù)的時候,不會重新生產(chǎn)sql語句。安全性高。
2、${parem}則直接將{}號中的param插入字符串,會產(chǎn)生sql注入的問題:
例如:
select * from userwhere userName= ${userName}?輸出的結(jié)果為
select * from userwhere userName= “小明”? ? ?
3、在特定場景下,例如如果在使用諸如order by '{param}',這時候就可以使用${}
4、#{}方式能夠很大程度防止sql注入,${}方式無法防止sql注入
5、${}方式一般用于傳入數(shù)據(jù)庫對象,例如傳入表名
字符串替換:
默認(rèn)情況下,使用#{}格式的語法會導(dǎo)致MyBatis創(chuàng)建預(yù)處理語句屬性并以它為背景設(shè)置安全的值(比如?)。這樣做很安全,很迅速也是首選做法,有時你只是想直接在SQL語句中插入一個不改變的字符串。
比如,像ORDER BY,你可以這樣來使用:
ORDER BY ${columnName}這里MyBatis不會修改或轉(zhuǎn)義字符串。
重要:接受從用戶輸出的內(nèi)容并提供給語句中不變的字符串,這樣做是不安全的。這會導(dǎo)致潛在的SQL注入攻擊,因此你不應(yīng)該允許用戶輸入這些字段,或者通常自行轉(zhuǎn)義并檢查。
這里一定要注意的是,可以用#{param}的時候盡量不要用${param}。
mybatis通用mapper的使用
目前通用mapper只支持對單表的操作,對單表的增刪改查,無需在mapper.xml寫對應(yīng)的sql語句,只需要我們調(diào)用相應(yīng)的接口,對于快速開發(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)行查詢,查詢條件使用等號
? ? VirtualIpBean vip = vipMapper.selectOne(vipBean);//根據(jù)實(shí)體中的屬性進(jìn)行查詢,只能有一個返回值,有多個結(jié)果是拋出異常,查詢條件使用等號
? ? List<VirtualIpBean> vipList2 = vipMapper.selectAll();//查詢?nèi)拷Y(jié)果,select(null)方法能達(dá)到同樣的效果
? ? VirtualIpBean vip2 = vipMapper.selectByPrimaryKey(1);//根據(jù)主鍵字段進(jìn)行查詢,方法參數(shù)必須包含完整的主鍵屬性,查詢條件使用等號
? ? int count = vipMapper.selectCount(vipBean);//根據(jù)實(shí)體中的屬性查詢總數(shù),查詢條件使用等號
? ? //insert接口
? ? int a = vipMapper.insert(vipBean);//保存一個實(shí)體,null的屬性也會保存,不會使用數(shù)據(jù)庫默認(rèn)值
? ? int a1 = vipMapper.insertSelective(vipBean);//保存實(shí)體,null的屬性不會保存,會使用數(shù)據(jù)庫默認(rèn)值
? ? //update接口
? ? int b = vipMapper.updateByPrimaryKeySelective(vipBean);//根據(jù)主鍵更新屬性不為null的值
? ? int c = vipMapper.updateByPrimaryKey(vipBean);//根據(jù)主鍵更新實(shí)體全部字段,null值會被更新
? ? //delete接口
? ? int d = vipMapper.delete(vipBean);//根據(jù)實(shí)體屬性作為條件進(jìn)行刪除,查詢條件使用等號
? ? 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é)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring Boot RabbitMQ 延遲消息實(shí)現(xiàn)完整版示例
本篇文章主要介紹了Spring Boot RabbitMQ 延遲消息實(shí)現(xiàn)完整版示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05
spring boot 2.x html中引用css和js失效問題及解決方法
這篇文章主要介紹了spring boot 2.x html中引用css和js失效,需要的朋友可以參考下2018-11-11
elasticsearch索引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-04
SpringBoot如何使用applicationContext.xml配置文件
這篇文章主要介紹了SpringBoot使用applicationContext.xml配置文件,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06
spring + shiro + cas 實(shí)現(xiàn)sso單點(diǎn)登錄的示例代碼
本篇文章主要介紹了spring + shiro + cas 實(shí)現(xiàn)sso單點(diǎn)登錄的示例代碼,具有一定的參考價值,有興趣的可以了解一下2017-09-09

