mybatis的基本語句的應用
大家好今晚整理有關mybatis的添加刪除修改更新的操作
一、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}。
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 | 驅動器決定 |
二、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">
推薦使用這種用法。
另外,還可以使用selectKey元素。下面例子,使用MySQL數據庫nextval(‘student’)為自定義函數,用來生成一個key。
<!-- 插入學生 自動主鍵--> <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語句屬性配置細節:
屬性 | 描述 | 取值 | 默認 |
---|---|---|---|
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 |
批量插入
方法一:
<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>
三、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>
四、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>
五、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>
六、parameters
上面很多地方已經用到了參數,比如查詢、修改、刪除的條件,插入,修改的數據等,MyBatis可以使用Java的基本數據類型和Java的復雜數據類型。如:基本數據類型,String,int,date等。
但是使用基本數據類型,只能提供一個參數,所以需要使用Java實體類,或Map類型做參數類型。通過#{}可以直接得到其屬性。
1、基本類型參數
根據入學時間,檢索學生列表:
<!-- 查詢學生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()); }
2、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()); }
3、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());
}
4、多參數的實現
如果想傳入多個參數,則需要在接口的參數上添加@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()); }
七、#{}與${}的區別
默認情況下,使用#{}語法,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
mybatis的基本語句的應用