程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 詳解Java的MyBatis框架中靜態SQL的根本用法

詳解Java的MyBatis框架中靜態SQL的根本用法

編輯:關於JAVA

詳解Java的MyBatis框架中靜態SQL的根本用法。本站提示廣大學習愛好者:(詳解Java的MyBatis框架中靜態SQL的根本用法)文章只能為提供參考,不一定能成為您想要的結果。以下是詳解Java的MyBatis框架中靜態SQL的根本用法正文


有些時刻,sql語句where前提中,須要一些平安斷定,例如按某一前提查詢時假如傳入的參數是空,此時查詢出的成果極可能是空的,或許我們須要參數為空時,是查出全體的信息。應用Oracle的序列、mysql的函數生成Id。這時候我們可使用靜態sql。下文均采取mysql語法和函數(例如字符串鏈接函數CONCAT)。

selectKey 標簽
在insert語句中,在Oracle常常應用序列、在MySQL中應用函數來主動生成拔出表的主鍵,並且須要辦法能前往這個生成主鍵。應用myBatis的selectKey標簽可以完成這個後果。上面例子,應用mysql數據庫自界說函數nextval('student'),用來生成一個key,並把他設置到傳入的實體類中的studentId屬性上。所以在履行完此辦法後,邊可以經由過程這個實體類獲得生成的key。

<!-- 拔出先生 主動主鍵--> 
<insert id="createStudentAutoKey" parameterType="liming.student.manager.data.model.StudentEntity" keyProperty="studentId"> 
 <selectKey keyProperty="studentId" resultType="String" order="BEFORE"> 
  select nextval('student') 
 </selectKey> 
 INSERT INTO STUDENT_TBL(STUDENT_ID, 
       STUDENT_NAME, 
       STUDENT_SEX, 
       STUDENT_BIRTHDAY, 
       STUDENT_PHOTO, 
       CLASS_ID, 
       PLACE_ID) 
 VALUES (#{studentId}, 
   #{studentName}, 
   #{studentSex}, 
   #{studentBirthday}, 
   #{studentPhoto, javaType=byte[], jdbcType=BLOB, typeHandler=org.apache.ibatis.type.BlobTypeHandler}, 
   #{classId}, 
   #{placeId}) 
</insert> 

 
挪用接口辦法,和獲得主動生成key

StudentEntity entity = new StudentEntity(); 
entity.setStudentName("拂曉你好"); 
entity.setStudentSex(1); 
entity.setStudentBirthday(DateUtil.parse("1985-05-28")); 
entity.setClassId("20000001"); 
entity.setPlaceId("70000001"); 
this.dynamicSqlMapper.createStudentAutoKey(entity); 
System.out.println("新增先生ID: " + entity.getStudentId()); 

 
selectKey語句屬性設置裝備擺設細節:
屬性 描寫 取值 keyProperty selectKey 語句生成成果須要設置的屬性。 resultType 生成成果類型,MyBatis 許可應用根本的數據類型,包含String 、int類型。 order

1:BEFORE,會先選擇主鍵,然後設置keyProperty,再履行insert語句;

2:AFTER,就先運轉insert 語句再運轉selectKey 語句。

BEFORE

AFTER statementType MyBatis 支撐STATEMENT,PREPARED和CALLABLE 的語句情勢, 對應Statement ,PreparedStatement 和CallableStatement 呼應

STATEMENT

PREPARED

CALLABLE

if標簽
 
if標簽可用在很多類型的sql語句中,我們以查詢為例。起首看一個很通俗的查詢:

<!-- 查詢先生list,like姓名 --> 
<select id="getStudentListLikeName" parameterType="StudentEntity" resultMap="studentResultMap"> 
 SELECT * from STUDENT_TBL ST 
WHERE ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%') 
</select> 

然則此時假如studentName或studentSex為null,此語句極可能報錯或查詢成果為空。此時我們應用if靜態sql語句先輩行斷定,假如值為null或等於空字符串,我們就不停止此前提的斷定,增長靈巧性。
參數為實體類StudentEntity。將實體類中一切的屬性均停止斷定,假如不為空則履行斷定前提。

<!-- 2 if(斷定參數) - 將實體類不為空的屬性作為where前提 --> 
<select id="getStudentList_if" resultMap="resultMap_studentEntity" parameterType="liming.student.manager.data.model.StudentEntity"> 
 SELECT ST.STUDENT_ID, 
   ST.STUDENT_NAME, 
   ST.STUDENT_SEX, 
   ST.STUDENT_BIRTHDAY, 
   ST.STUDENT_PHOTO, 
   ST.CLASS_ID, 
   ST.PLACE_ID 
  FROM STUDENT_TBL ST 
  WHERE 
 <if test="studentName !=null "> 
  ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName, jdbcType=VARCHAR}),'%') 
 </if> 
 <if test="studentSex != null and studentSex != '' "> 
  AND ST.STUDENT_SEX = #{studentSex, jdbcType=INTEGER} 
 </if> 
 <if test="studentBirthday != null "> 
  AND ST.STUDENT_BIRTHDAY = #{studentBirthday, jdbcType=DATE} 
 </if> 
 <if test="classId != null and classId!= '' "> 
  AND ST.CLASS_ID = #{classId, jdbcType=VARCHAR} 
 </if> 
 <if test="classEntity != null and classEntity.classId !=null and classEntity.classId !=' ' "> 
  AND ST.CLASS_ID = #{classEntity.classId, jdbcType=VARCHAR} 
 </if> 
 <if test="placeId != null and placeId != '' "> 
  AND ST.PLACE_ID = #{placeId, jdbcType=VARCHAR} 
 </if> 
 <if test="placeEntity != null and placeEntity.placeId != null and placeEntity.placeId != '' "> 
  AND ST.PLACE_ID = #{placeEntity.placeId, jdbcType=VARCHAR} 
 </if> 
 <if test="studentId != null and studentId != '' "> 
  AND ST.STUDENT_ID = #{studentId, jdbcType=VARCHAR} 
 </if> 
</select> 

應用時比擬靈巧, new一個如許的實體類,我們須要限制誰人前提,只須要附上響應的值就會where這個前提,相反不去賦值便可以不在where中斷定。

public void select_test_2_1() { 
 StudentEntity entity = new StudentEntity(); 
 entity.setStudentName(""); 
 entity.setStudentSex(1); 
 entity.setStudentBirthday(DateUtil.parse("1985-05-28")); 
 entity.setClassId("20000001"); 
 //entity.setPlaceId("70000001"); 
 List<StudentEntity> list = this.dynamicSqlMapper.getStudentList_if(entity); 
 for (StudentEntity e : list) { 
  System.out.println(e.toString()); 
 } 
} 
 

 
if + where 的前提斷定
       當where中的前提應用的if標簽較多時,如許的組合能夠會招致毛病。我們以在3.1中的查詢語句為例子,當java代碼按以下辦法挪用時:

@Test 
public void select_test_2_1() { 
 StudentEntity entity = new StudentEntity(); 
 entity.setStudentName(null); 
 entity.setStudentSex(1); 
 List<StudentEntity> list = this.dynamicSqlMapper.getStudentList_if(entity); 
 for (StudentEntity e : list) { 
  System.out.println(e.toString()); 
 } 
} 

假如下面例子,參數studentName為null,將不會停止STUDENT_NAME列的斷定,則會直接導“WHERE AND”症結字過剩的毛病SQL。
 
這時候我們可使用where靜態語句來處理。這個“where”標簽會曉得假如它包括的標簽中有前往值的話,它就拔出一個‘where'。另外,假如標簽前往的內容是以AND 或OR 開首的,則它會剔除失落。
下面例子修正為:

<!-- 3 select - where/if(斷定參數) - 將實體類不為空的屬性作為where前提 --> 
<select id="getStudentList_whereIf" resultMap="resultMap_studentEntity" parameterType="liming.student.manager.data.model.StudentEntity"> 
 SELECT ST.STUDENT_ID, 
   ST.STUDENT_NAME, 
   ST.STUDENT_SEX, 
   ST.STUDENT_BIRTHDAY, 
   ST.STUDENT_PHOTO, 
   ST.CLASS_ID, 
   ST.PLACE_ID 
  FROM STUDENT_TBL ST 
 <where> 
  <if test="studentName !=null "> 
   ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName, jdbcType=VARCHAR}),'%') 
  </if> 
  <if test="studentSex != null and studentSex != '' "> 
   AND ST.STUDENT_SEX = #{studentSex, jdbcType=INTEGER} 
  </if> 
  <if test="studentBirthday != null "> 
   AND ST.STUDENT_BIRTHDAY = #{studentBirthday, jdbcType=DATE} 
  </if> 
  <if test="classId != null and classId!= '' "> 
   AND ST.CLASS_ID = #{classId, jdbcType=VARCHAR} 
  </if> 
  <if test="classEntity != null and classEntity.classId !=null and classEntity.classId !=' ' "> 
   AND ST.CLASS_ID = #{classEntity.classId, jdbcType=VARCHAR} 
  </if> 
  <if test="placeId != null and placeId != '' "> 
   AND ST.PLACE_ID = #{placeId, jdbcType=VARCHAR} 
  </if> 
  <if test="placeEntity != null and placeEntity.placeId != null and placeEntity.placeId != '' "> 
   AND ST.PLACE_ID = #{placeEntity.placeId, jdbcType=VARCHAR} 
  </if> 
  <if test="studentId != null and studentId != '' "> 
   AND ST.STUDENT_ID = #{studentId, jdbcType=VARCHAR} 
  </if> 
 </where> 
</select> 

if + set 的更新語句
當update語句中沒有應用if標簽時,假如有一個參數為null,都邑招致毛病。
當在update語句中應用if標簽時,假如後面的if沒有履行,則或招致逗號過剩毛病。應用set標簽可以將靜態的設置裝備擺設SET 症結字,和剔除追加到前提末尾的任何不相干的逗號。
 
應用if+set標簽修正後,假如某項為null則不停止更新,而是堅持數據庫原值。以下示例:

<!-- 4 if/set(斷定參數) - 將實體類不為空的屬性更新 --> 
<update id="updateStudent_if_set" parameterType="liming.student.manager.data.model.StudentEntity"> 
 UPDATE STUDENT_TBL 
 <set> 
  <if test="studentName != null and studentName != '' "> 
   STUDENT_TBL.STUDENT_NAME = #{studentName}, 
  </if> 
  <if test="studentSex != null and studentSex != '' "> 
   STUDENT_TBL.STUDENT_SEX = #{studentSex}, 
  </if> 
  <if test="studentBirthday != null "> 
   STUDENT_TBL.STUDENT_BIRTHDAY = #{studentBirthday}, 
  </if> 
  <if test="studentPhoto != null "> 
   STUDENT_TBL.STUDENT_PHOTO = #{studentPhoto, javaType=byte[], jdbcType=BLOB, typeHandler=org.apache.ibatis.type.BlobTypeHandler}, 
  </if> 
  <if test="classId != '' "> 
   STUDENT_TBL.CLASS_ID = #{classId} 
  </if> 
  <if test="placeId != '' "> 
   STUDENT_TBL.PLACE_ID = #{placeId} 
  </if> 
 </set> 
 WHERE STUDENT_TBL.STUDENT_ID = #{studentId};  
</update> 

if + trim取代where/set標簽
       trim是更靈巧的行止過剩症結字的標簽,他可以理論where和set的後果。
 
trim取代where

<!-- 5.1 if/trim取代where(斷定參數) - 將實體類不為空的屬性作為where前提 --> 
<select id="getStudentList_if_trim" resultMap="resultMap_studentEntity"> 
 SELECT ST.STUDENT_ID, 
   ST.STUDENT_NAME, 
   ST.STUDENT_SEX, 
   ST.STUDENT_BIRTHDAY, 
   ST.STUDENT_PHOTO, 
   ST.CLASS_ID, 
   ST.PLACE_ID 
  FROM STUDENT_TBL ST 
 <trim prefix="WHERE" prefixOverrides="AND|OR"> 
  <if test="studentName !=null "> 
   ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName, jdbcType=VARCHAR}),'%') 
  </if> 
  <if test="studentSex != null and studentSex != '' "> 
   AND ST.STUDENT_SEX = #{studentSex, jdbcType=INTEGER} 
  </if> 
  <if test="studentBirthday != null "> 
   AND ST.STUDENT_BIRTHDAY = #{studentBirthday, jdbcType=DATE} 
  </if> 
  <if test="classId != null and classId!= '' "> 
   AND ST.CLASS_ID = #{classId, jdbcType=VARCHAR} 
  </if> 
  <if test="classEntity != null and classEntity.classId !=null and classEntity.classId !=' ' "> 
   AND ST.CLASS_ID = #{classEntity.classId, jdbcType=VARCHAR} 
  </if> 
  <if test="placeId != null and placeId != '' "> 
   AND ST.PLACE_ID = #{placeId, jdbcType=VARCHAR} 
  </if> 
  <if test="placeEntity != null and placeEntity.placeId != null and placeEntity.placeId != '' "> 
   AND ST.PLACE_ID = #{placeEntity.placeId, jdbcType=VARCHAR} 
  </if> 
  <if test="studentId != null and studentId != '' "> 
   AND ST.STUDENT_ID = #{studentId, jdbcType=VARCHAR} 
  </if> 
 </trim>  
</select> 

 
trim取代set

<!-- 5.2 if/trim取代set(斷定參數) - 將實體類不為空的屬性更新 --> 
<update id="updateStudent_if_trim" parameterType="liming.student.manager.data.model.StudentEntity"> 
 UPDATE STUDENT_TBL 
 <trim prefix="SET" suffixOverrides=","> 
  <if test="studentName != null and studentName != '' "> 
   STUDENT_TBL.STUDENT_NAME = #{studentName}, 
  </if> 
  <if test="studentSex != null and studentSex != '' "> 
   STUDENT_TBL.STUDENT_SEX = #{studentSex}, 
  </if> 
  <if test="studentBirthday != null "> 
   STUDENT_TBL.STUDENT_BIRTHDAY = #{studentBirthday}, 
  </if> 
  <if test="studentPhoto != null "> 
   STUDENT_TBL.STUDENT_PHOTO = #{studentPhoto, javaType=byte[], jdbcType=BLOB, typeHandler=org.apache.ibatis.type.BlobTypeHandler}, 
  </if> 
  <if test="classId != '' "> 
   STUDENT_TBL.CLASS_ID = #{classId}, 
  </if> 
  <if test="placeId != '' "> 
   STUDENT_TBL.PLACE_ID = #{placeId} 
  </if> 
 </trim> 
 WHERE STUDENT_TBL.STUDENT_ID = #{studentId} 
</update> 

choose (when, otherwise)
 
有時刻我們其實不想運用一切的前提,而只是想從多個選項當選擇一個。而應用if標簽時,只需test中的表達式為true,就會履行if標簽中的前提。MyBatis供給了choose 元素。if標簽是與(and)的關系,而choose比傲天是或(or)的關系。
choose標簽是按次序斷定其外部when標簽中的test前提出否成立,假如有一個成立,則choose停止。當choose中一切when的前提都不滿則時,則履行otherwise中的sql。相似於Java 的switch 語句,choose為switch,when為case,otherwise則為default。
例以下面例子,異樣把一切可以限制的前提都寫上,方面應用。choose會從上到下選擇一個when標簽的test為true的sql履行。平安斟酌,我們應用where將choose包起來,放置症結字多於毛病。

<!-- 6 choose(斷定參數) - 按次序將實體類第一個不為空的屬性作為where前提 --> 
<select id="getStudentList_choose" resultMap="resultMap_studentEntity" parameterType="liming.student.manager.data.model.StudentEntity"> 
 SELECT ST.STUDENT_ID, 
   ST.STUDENT_NAME, 
   ST.STUDENT_SEX, 
   ST.STUDENT_BIRTHDAY, 
   ST.STUDENT_PHOTO, 
   ST.CLASS_ID, 
   ST.PLACE_ID 
  FROM STUDENT_TBL ST 
 <where> 
  <choose> 
   <when test="studentName !=null "> 
    ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName, jdbcType=VARCHAR}),'%') 
   </when > 
   <when test="studentSex != null and studentSex != '' "> 
    AND ST.STUDENT_SEX = #{studentSex, jdbcType=INTEGER} 
   </when > 
   <when test="studentBirthday != null "> 
    AND ST.STUDENT_BIRTHDAY = #{studentBirthday, jdbcType=DATE} 
   </when > 
   <when test="classId != null and classId!= '' "> 
    AND ST.CLASS_ID = #{classId, jdbcType=VARCHAR} 
   </when > 
   <when test="classEntity != null and classEntity.classId !=null and classEntity.classId !=' ' "> 
    AND ST.CLASS_ID = #{classEntity.classId, jdbcType=VARCHAR} 
   </when > 
   <when test="placeId != null and placeId != '' "> 
    AND ST.PLACE_ID = #{placeId, jdbcType=VARCHAR} 
   </when > 
   <when test="placeEntity != null and placeEntity.placeId != null and placeEntity.placeId != '' "> 
    AND ST.PLACE_ID = #{placeEntity.placeId, jdbcType=VARCHAR} 
   </when > 
   <when test="studentId != null and studentId != '' "> 
    AND ST.STUDENT_ID = #{studentId, jdbcType=VARCHAR} 
   </when > 
   <otherwise> 
   </otherwise> 
  </choose> 
 </where> 
</select> 

 
foreach
關於靜態SQL 異常必需的,主是要迭代一個聚集,平日是用於IN 前提。List 實例將應用“list”做為鍵,數組實例以“array” 做為鍵。
foreach元素長短常壯大的,它許可你指定一個聚集,聲明聚集項和索引變量,它們可以用在元素體內。它也許可你指定開放和封閉的字符串,在迭代之間放置分隔符。這個元素是很智能的,它不會有時地附加過剩的分隔符。
留意:你可以傳遞一個List實例或許數組作為參數對象傳給MyBatis。當你這麼做的時刻,MyBatis會主動將它包裝在一個Map中,用稱號在作為鍵。List實例將會以“list”作為鍵,而數組實例將會以“array”作為鍵。
這個部門是對關於XML設置裝備擺設文件和XML映照文件的而評論辯論的。下一部門將具體評論辯論Java API,所以你可以獲得你曾經創立的最有用的映照。

1.參數為array示例的寫法
 
接口的辦法聲明:

public List<StudentEntity> getStudentListByClassIds_foreach_array(String[] classIds); 

 
靜態SQL語句:

<!— 7.1 foreach(輪回array參數) - 作為where中in的前提 --> 
<select id="getStudentListByClassIds_foreach_array" resultMap="resultMap_studentEntity"> 
 SELECT ST.STUDENT_ID, 
   ST.STUDENT_NAME, 
   ST.STUDENT_SEX, 
   ST.STUDENT_BIRTHDAY, 
   ST.STUDENT_PHOTO, 
   ST.CLASS_ID, 
   ST.PLACE_ID 
  FROM STUDENT_TBL ST 
  WHERE ST.CLASS_ID IN 
  <foreach collection="array" item="classIds" open="(" separator="," close=")"> 
  #{classIds} 
  </foreach> 
</select> 

 
測試代碼,查詢先生中,在20000001、20000002這兩個班級的先生:

@Test 
public void test7_foreach() { 
  String[] classIds = { "20000001", "20000002" }; 
  List<StudentEntity> list = this.dynamicSqlMapper.getStudentListByClassIds_foreach_array(classIds); 
  for (StudentEntity e : list) { 
    System.out.println(e.toString()); 
  } 
} 

2.參數為list示例的寫法
接口的辦法聲明:

public List<StudentEntity> getStudentListByClassIds_foreach_list(List<String> classIdList); 

 
靜態SQL語句:

<!-- 7.2 foreach(輪回List<String>參數) - 作為where中in的前提 --> 
<select id="getStudentListByClassIds_foreach_list" resultMap="resultMap_studentEntity"> 
 SELECT ST.STUDENT_ID, 
   ST.STUDENT_NAME, 
   ST.STUDENT_SEX, 
   ST.STUDENT_BIRTHDAY, 
   ST.STUDENT_PHOTO, 
   ST.CLASS_ID, 
   ST.PLACE_ID 
  FROM STUDENT_TBL ST 
  WHERE ST.CLASS_ID IN 
  <foreach collection="list" item="classIdList" open="(" separator="," close=")"> 
  #{classIdList} 
  </foreach> 
</select> 

 
測試代碼,查詢先生中,在20000001、20000002這兩個班級的先生:

@Test 
public void test7_2_foreach() { 
 ArrayList<String> classIdList = new ArrayList<String>(); 
 classIdList.add("20000001"); 
 classIdList.add("20000002"); 
 List<StudentEntity> list = this.dynamicSqlMapper.getStudentListByClassIds_foreach_list(classIdList); 
 for (StudentEntity e : list) { 
  System.out.println(e.toString()); 
 } 
} 

3.本身把參數封裝成Map的類型

<select id="dynamicForeach3Test" resultType="Blog"> 
 select * from t_blog where title like "%"#{title}"%" and id in 
 <foreach collection="ids" index="index" item="item" open="(" separator="," close=")"> 
  #{item} 
 </foreach> 
</select> 

上述collection的值為ids,是傳入的參數Map的key,對應的Mapper代碼:

public List<Blog> dynamicForeach3Test(Map<String, Object> params); 

  對應測試代碼:

@Test 
public void dynamicForeach3Test() { 
 SqlSession session = Util.getSqlSessionFactory().openSession(); 
 BlogMapper blogMapper = session.getMapper(BlogMapper.class); 
 final List<Integer> ids = new ArrayList<Integer>(); 
 ids.add(1); 
 ids.add(2); 
 ids.add(3); 
 ids.add(6); 
 ids.add(7); 
 ids.add(9); 
 Map<String, Object> params = new HashMap<String, Object>(); 
 params.put("ids", ids); 
 params.put("title", "中國"); 
 List<Blog> blogs = blogMapper.dynamicForeach3Test(params); 
 for (Blog blog : blogs) 
  System.out.println(blog); 
 session.close(); 
} 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved