1、select
<!-- 查詢學生,根據id --> <select id="getStudent" parameterType="String" resultMap="studentResultMap"> SELECT ST.STUDENT_ID, ST.STUDENT_NAME, ST.STUDENT_SEX, ST.STUDENT_BIRTHDAY, ST.CLASS_ID FROM STUDENT_TBL ST WHERE ST.STUDENT_ID = #{studentID} </select>
這條語句就叫作‘getStudent,有一個String參數,並返回一個StudentEntity類型的對象。
注意參數的標識是:#{studentID}。sql
select 語句屬性配置細節:數據庫
屬性 | 描述 | 取值 | 默認 |
---|---|---|---|
id | 在這個模式下惟一的標識符,可被其它語句引用 | ||
parameterType | 傳給此語句的參數的完整類名或別名 | ||
resultType | 語句返回值類型的整類名或別名。注意,若是是集合,那麼這裏填寫的是集合的項的整類名或別名,而不是集合自己的類名。(resultType 與resultMap 不能並用) | ||
resultMap | 引用的外部resultMap 名。結果集映射是MyBatis 中最強大的特性。許多複雜的映射均可以輕鬆解決。(resultType 與resultMap 不能並用) | ||
flushCache | 若是設爲true,則會在每次語句調用的時候就會清空緩存。select 語句默認設爲false | true/false | false |
useCache | 若是設爲true,則語句的結果集將被緩存。select 語句默認設爲false | true/false | false |
timeout | 設置驅動器在拋出異常前等待迴應的最長時間,默認爲不設值,由驅動器本身決定 | 正整數 | 未設置 |
fetchSize | 設置一個值後,驅動器會在結果集數目達到此數值後,激發返回,默認爲不設值,由驅動器本身決定 | 正整數 | 驅動器決定 |
statementType | statement,preparedstatement,callablestatement。預準備語句、可調用語句 | STATEMENT、PREPARED、CALLABLE | PREPARED |
resultSetType | forward_only、scroll_sensitive、scroll_insensitive 只轉發,滾動敏感,不區分大小寫的滾動 | FORWARD_ONLY、SCROLL_SENSITIVE、SCROLL_INSENSITIVE | 驅動器決定 |
2、insert
一個簡單的insert語句:緩存
<!-- 插入學生 --> <insert id="insertStudent" parameterType="StudentEntity"> INSERT INTO STUDENT_TBL (STUDENT_ID, STUDENT_NAME, STUDENT_SEX, STUDENT_BIRTHDAY, CLASS_ID) VALUES (#{studentID}, #{studentName}, #{studentSex}, #{studentBirthday}, #{classEntity.classID}) </insert>
insert可使用數據庫支持的自動生成主鍵策略,設置useGeneratedKeys=」true」,而後把keyProperty 設成對應的列,就搞定了。好比說上面的StudentEntity 使用auto-generated 爲id 列生成主鍵.安全
<insert id="insertStudent" parameterType="StudentEntity" useGeneratedKeys="true" keyProperty="studentID">
推薦使用這種用法。mybatis
另外,還可使用selectKey元素。下面例子,使用MySQL數據庫nextval(‘student’)爲自定義函數,用來生成一個key。app
<!-- 插入學生 自動主鍵--> <insert id="insertStudentAutoKey" parameterType="StudentEntity"> <selectKey keyProperty="studentID" resultType="String" order="BEFORE"> select nextval('student') </selectKey> INSERT INTO STUDENT_TBL (STUDENT_ID, STUDENT_NAME, STUDENT_SEX, STUDENT_BIRTHDAY, CLASS_ID) VALUES (#{studentID}, #{studentName}, #{studentSex}, #{studentBirthday}, #{classEntity.classID}) </insert>
insert語句屬性配置細節:less
屬性 | 描述 | 取值 | 默認 |
---|---|---|---|
id | 在這個模式下惟一的標識符,可被其它語句引用 | ||
parameterType | 傳給此語句的參數的完整類名或別名 | ||
flushCache | 若是設爲true,則會在每次語句調用的時候就會清空緩存。select 語句默認設爲false | true/false | false |
useCache | 若是設爲true,則語句的結果集將被緩存。select 語句默認設爲false | true/false | false |
timeout | 設置驅動器在拋出異常前等待迴應的最長時間,默認爲不設值,由驅動器本身決定 | 正整數 | 未設置 |
fetchSize | 設置一個值後,驅動器會在結果集數目達到此數值後,激發返回,默認爲不設值,由驅動器本身決定 | 正整數 | 驅動器決定 |
statementType | statement、preparedstatement、callablestatement。預準備語句、可調用語句 | STATEMENT、PREPARED、CALLABLE | PREPARED |
useGeneratedKeys | 告訴MyBatis 使用JDBC 的getGeneratedKeys 方法來獲取數據庫本身生成的主鍵(MySQL、SQLSERVER 等關係型數據庫會有自動生成的字段)。默認:false | true/false | false |
keyProperty | 標識一個將要被MyBatis設置進getGeneratedKeys的key 所返回的值,或者爲insert 語句使用一個selectKey子元素。 |
selectKey語句屬性配置細節:函數
屬性 | 描述 | 取值 |
---|---|---|
keyProperty | selectKey 語句生成結果須要設置的屬性。 | |
resultType | 生成結果類型,MyBatis 容許使用基本的數據類型,包括String 、int類型。 | |
order | 能夠設成BEFORE 或者AFTER,若是設爲BEFORE,那它會先選擇主鍵,而後設置keyProperty,再執行insert語句;若是設爲AFTER,它就先運行insert 語句再運行selectKey 語句,一般是insert 語句中內部調用數據庫(像Oracle)內嵌的序列機制。 | BEFORE/AFTER |
statementType | 像上面的那樣, MyBatis 支持STATEMENT,PREPARED和CALLABLE 的語句形式, 對應Statement ,PreparedStatement 和CallableStatement 響應 | STATEMENT、PREPARED、CALLABLE |
批量插入
方法一:post
<insert id="add" parameterType="EStudent"> <foreach collection="list" item="item" index="index" separator=";"> INSERT INTO TStudent(name,age) VALUES(#{item.name}, #{item.age}) </foreach> </insert>
上述方式至關語句逐條INSERT語句執行,將出現以下問題:
1. mapper接口的add方法返回值將是最一條INSERT語句的操做成功的記錄數目(就是0或1),而不是全部INSERT語句的操做成功的總記錄數目
2. 當其中一條不成功時,不會進行總體回滾。
方法二:
<insert id="insertStudentAutoKey" parameterType="java.util.List"> INSERT INTO STUDENT_TBL (STUDENT_NAME, STUDENT_SEX, STUDENT_BIRTHDAY, CLASS_ID) VALUES <foreach collection="list" item="item" index="index" separator=","> ( #{item.studentName},#{item.studentSex},#{item.studentBirthday},#{item.classEntity.classID}) </foreach> </insert>
3、update
一個簡單的update:
<!-- 更新學生信息 --> <update id="updateStudent" parameterType="StudentEntity"> UPDATE STUDENT_TBL SET STUDENT_TBL.STUDENT_NAME = #{studentName}, STUDENT_TBL.STUDENT_SEX = #{studentSex}, STUDENT_TBL.STUDENT_BIRTHDAY = #{studentBirthday}, STUDENT_TBL.CLASS_ID = #{classEntity.classID} WHERE STUDENT_TBL.STUDENT_ID = #{studentID}; </update>
update語句屬性配置細節:
屬性 | 描述 | 取值 | 默認 |
---|---|---|---|
id | 在這個模式下惟一的標識符,可被其它語句引用 | ||
parameterType | 傳給此語句的參數的完整類名或別名 | ||
flushCache | 若是設爲true,則會在每次語句調用的時候就會清空緩存。select 語句默認設爲false | true/false | false |
useCache | 若是設爲true,則語句的結果集將被緩存。select 語句默認設爲false | true/false | false |
timeout | 設置驅動器在拋出異常前等待迴應的最長時間,默認爲不設值,由驅動器本身決定 | 正整數 | 未設置 |
fetchSize | 設置一個值後,驅動器會在結果集數目達到此數值後,激發返回,默認爲不設值,由驅動器本身決定 | 正整數 | 驅動器決定 |
statementType | statement、preparedstatement、callablestatement。預準備語句、可調用語句 | STATEMENT、PREPARED、CALLABLE | PREPARED |
批量更新
情景一:更新多條記錄爲多個字段爲不一樣的值
方法一:
<update id="updateBatch" parameterType="java.util.List"> <foreach collection="list" item="item" index="index" open="" close="" separator=";"> update course <set> name=${item.name} </set> where id = ${item.id} </foreach> </update>
比較普通的寫法,是經過循環,依次執行update語句。
方法二:
UPDATE TStudent SET Name = R.name, Age = R.age from ( SELECT 'Mary' as name, 12 as age, 42 as id union all select 'John' as name , 16 as age, 43 as id ) as r where ID = R.id
情景二:更新多條記錄的同一個字段爲同一個值
<update id="updateOrders" parameterType="java.util.List"> update orders set state = '0' where no in <foreach collection="list" item="id" open="(" separator="," close=")"> #{id} </foreach> </update>
4、delete
一個簡單的delete:
<!-- 刪除學生 --> <delete id="deleteStudent" parameterType="StudentEntity"> DELETE FROM STUDENT_TBL WHERE STUDENT_ID = #{studentID} </delete>
delete語句屬性配置細節同update
批量刪除:
<!-- 經過主鍵集合批量刪除記錄 --> <delete id="batchRemoveUserByPks" parameterType="java.util.List"> DELETE FROM LD_USER WHERE ID in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </delete>
5、sql元素
Sql元素用來定義一個能夠複用的SQL 語句段,供其它語句調用。好比:
<!-- 複用sql語句 查詢student表全部字段 --> <sql id="selectStudentAll"> SELECT ST.STUDENT_ID, ST.STUDENT_NAME, ST.STUDENT_SEX, ST.STUDENT_BIRTHDAY, ST.CLASS_ID FROM STUDENT_TBL ST </sql>
這樣,在select的語句中就能夠直接引用使用了,將上面select語句改爲:
<!-- 查詢學生,根據id --> <select id="getStudent" parameterType="String" resultMap="studentResultMap"> <include refid="selectStudentAll"/> WHERE ST.STUDENT_ID = #{studentID} </select>
6、parameters
上面不少地方已經用到了參數,好比查詢、修改、刪除的條件,插入,修改的數據等,MyBatis可使用Java的基本數據類型和Java的複雜數據類型。如:基本數據類型,String,int,date等。
可是使用基本數據類型,只能提供一個參數,因此須要使用Java實體類,或Map類型作參數類型。經過#{}能夠直接獲得其屬性。
一、基本類型參數
根據入學時間,檢索學生列表:
<!-- 查詢學生list,根據入學時間 --> <select id="getStudentListByDate" parameterType="Date" resultMap="studentResultMap"> SELECT * FROM STUDENT_TBL ST LEFT JOIN CLASS_TBL CT ON ST.CLASS_ID = CT.CLASS_ID WHERE CT.CLASS_YEAR = #{classYear}; </select>
List<StudentEntity> studentList = studentMapper.getStudentListByClassYear(StringUtil.parse("2007-9-1")); for (StudentEntity entityTemp : studentList) { System.out.println(entityTemp.toString()); }
二、Java實體類型參數
根據姓名和性別,檢索學生列表。使用實體類作參數:
<!-- 查詢學生list,like姓名、=性別,參數entity類型 --> <select id="getStudentListWhereEntity" parameterType="StudentEntity" resultMap="studentResultMap"> SELECT * from STUDENT_TBL ST WHERE ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%') AND ST.STUDENT_SEX = #{studentSex} </select>
StudentEntity entity = new StudentEntity(); entity.setStudentName("李"); entity.setStudentSex("男"); List<StudentEntity> studentList = studentMapper.getStudentListWhereEntity(entity); for (StudentEntity entityTemp : studentList) { System.out.println(entityTemp.toString()); }
三、Map參數
根據姓名和性別,檢索學生列表。使用Map作參數:
<!-- 查詢學生list,=性別,參數map類型 --> <select id="getStudentListWhereMap" parameterType="Map" resultMap="studentResultMap"> SELECT * from STUDENT_TBL ST WHERE ST.STUDENT_SEX = #{sex} AND ST.STUDENT_SEX = #{sex} </select>
Map<String, String> map = new HashMap<String, String>(); map.put("sex", "女"); map.put("name", "雪"); List<StudentEntity> studentList = studentMapper.getStudentListWhereMap(map);
for (StudentEntity entityTemp : studentList) { System.out.println(entityTemp.toString()); }
四、多參數的實現
若是想傳入多個參數,則須要在接口的參數上添加@Param註解。給出一個實例:
接口寫法:
public List<StudentEntity> getStudentListWhereParam(@Param(value = "name") String name, @Param(value = "sex") String sex, @Param(value = "birthday") Date birthdar, @Param(value = "classEntity") ClassEntity classEntity);
sql寫法:
<!-- 查詢學生list,like姓名、=性別、=生日、=班級,多參數方式 --> <select id="getStudentListWhereParam" resultMap="studentResultMap"> SELECT * from STUDENT_TBL ST <where> <if test="name!=null and name!='' "> ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{name}),'%') </if> <if test="sex!= null and sex!= '' "> AND ST.STUDENT_SEX = #{sex} </if> <if test="birthday!=null"> AND ST.STUDENT_BIRTHDAY = #{birthday} </if> <if test="classEntity!=null and classEntity.classID !=null and classEntity.classID!='' "> AND ST.CLASS_ID = #{classEntity.classID} </if> </where> </select>
進行查詢:
List<StudentEntity> studentList = studentMapper.getStudentListWhereParam("","",StringUtil.parse("1985-05-28"), classMapper.getClassByID("20000002")); for (StudentEntity entityTemp : studentList) { System.out.println(entityTemp.toString()); }
7、#{}與${}的區別
默認狀況下,使用#{}語法,MyBatis會產生PreparedStatement語句中,而且安全的設置PreparedStatement參數,這個過程當中MyBatis會進行必要的安全檢查和轉義。
示例1:
執行SQL:Select * from emp where name = #{employeeName}
參數:employeeName=>Smith
解析後執行的SQL:Select * from emp where name = ?
執行SQL:Select * from emp where name = ${employeeName}
參數:employeeName傳入值爲:Smith
解析後執行的SQL:Select * from emp where name =Smith
說明:
1. #
將傳入的數據都當成一個字符串,會對自動傳入的數據加一個雙引號。如:order by #{user_id},若是傳入的值是111,那麼解析成sql時的值爲order by 「111」, 若是傳入的值是id,則解析成的sql爲order by 「id」.
2. $
將傳入的數據直接顯示生成在sql中。如:order by ${user_id},若是傳入的值是111,那麼解析成sql時的值爲order by 111, 若是傳入的值是id,則解析成的sql爲order by id.
綜上所述,${}
方式會引起SQL注入的問題、同時也會影響SQL語句的預編譯,因此從安全性和性能的角度出發,能使用#{}的狀況下就不要使用${}。
${}在什麼狀況下使用呢?
有時候可能須要直接插入一個不作任何修改的字符串到SQL語句中。這時候應該使用${}語法。
好比,動態SQL中的字段名,如:ORDER BY ${columnName}
<select id="queryMetaList" resultType="Map" statementType="STATEMENT"> Select * from emp where name = ${employeeName} ORDER BY ${columnName} </select>
因爲${}
僅僅是簡單的取值,因此之前sql注入的方法適用此處,若是咱們order by語句後用了${},那麼不作任何處理的時候是存在sql注入危險的。
2019-03-3022:43:43