版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
JavaWeb編程技術本章首先介紹MyBatis配置文件各種元素的含義及配置,然后學習映射文件的各種元素的使用,之后介紹MyBaits關聯(lián)映射,最后介紹動態(tài)SQL語句的定義和使用。MyBatis的配置文件MyBatis的映射文件MyBatis的關聯(lián)映射構建動態(tài)SQL語句第15章配置文件和映射文件MyBatis應用程序開始運行時要讀取配置文件,配置文件用來配置MyBatis運行的各種信息。MyBatis通過映射文件描述持久化類和數(shù)據庫表之間的映射關系。配置文件MyBatis配置文件的一些設置對MyBatis的特性有巨大影響。配置文件默認文件名為mybatis-config.xml。配置文件的根元素是<configuration>,其子元素如下所示:properties,配置有關屬性。settings,設置運行時全局參數(shù)。typeAliases,為Java類型設置短的別名。typeHandlers,創(chuàng)建類型處理器。objectFactory,設置自定義對象工廠。plugins,配置使用的插件。environments,配置運行環(huán)境,如事務管理器、數(shù)據源等。databaseIdProvider,配置數(shù)據庫支持多廠商特性。mappers,配置映射器。15.1<enviroments>元素15.1.1清單15.1中的<environments>元素定義了如何配置環(huán)境。<environmentsdefault="development"><environmentid="development"><transactionManagertype="JDBC"><propertyname="closeConnection"value="false"/></transactionManager><dataSourcetype="POOLED"><propertyname="driver"value="${driver}"/><propertyname="url"value="${url}"/><propertyname="username"value="${username}"/><propertyname="password"value="${password}"/></dataSource></environment></environments><enviroments>元素15.1.1MyBatis可以配置成適應多種環(huán)境,這種機制有助于將SQL映射應用于多種數(shù)據庫之中。例如,開發(fā)、測試和生產環(huán)境需要有不同的配置。
不過要記?。罕M管可以配置多個環(huán)境,每個SqlSessionFactory實例只能選擇一個環(huán)境。所以,如果想連接兩個數(shù)據庫,就需要創(chuàng)建兩個SqlSessionFactory實例,每個數(shù)據庫對應一個環(huán)境。為了指定創(chuàng)建哪種環(huán)境,只要將它作為可選的參數(shù)傳遞給SqlSessionFactoryBuilder即可??梢越邮墉h(huán)境配置的兩個方法簽名是:SqlSessionFactoryfactory=sqlSessionFactoryBuilder.build(reader,environment);SqlSessionFactoryfactory=sqlSessionFactoryBuilder.build(reader,environment,properties);<properties>元素15.1.2<properties>元素用于配置MyBatis有關屬性,比如數(shù)據庫的連接信息。這些屬性都是可外部配置且可動態(tài)替換的,既可在典型的Java屬性文件中配置,也可通過子元素<property>配置,例如:屬性文件perties中的屬性可以在整個配置文件中使用來替換需要動態(tài)配置的屬性值。例如,下面在數(shù)據源配置<dataSource>元素中配置數(shù)據庫連接屬性。<propertiesresource="com/boda/example/perties"><propertyname="username"value="dev_user"/><propertyname="password"value="123456a"/></properties><dataSourcetype="POOLED">
<propertyname="driver"value="${driver}"/><propertyname="url"value="${url}"/><propertyname="username"value="${username}"/><propertyname="password"value="${password}"/></dataSource><settings>元素15.1.3<settings>元素用于設置MyBatis運行時的全局參數(shù),例如開啟二級緩存、開啟延遲加載等。雖然不配置<settings>元素,MyBatis也可以正常運行,但是熟悉<settings>的配置內容以及它們的作用十分必要。下面是幾個常用參數(shù)的配置。<settings><settingname="cacheEnabled"value="true"/><settingname="lazyLoadingEnabled"value="true"/><settingname="multipleResultSetsEnabled"value="true"/><settingname="useColumnLabel"value="true"/><settingname="useGeneratedKeys"value="false"/>
<settingname="logImpl"value="LOG4J2"/></settings><typeAliases>元素15.1.4<typeAliases>元素用來為Java類型設置一個短的別名。它的主要作用是減少類完全限定名的冗余。使用<typeAliases>元素配置別名的方法如下。<typeAliases><typeAliasalias="Student"type="com.boda.domain.Student"/><typeAliasalias="Tutor"type="com.boda.domain.Tutor"/><typeAliasalias="Course"type="com.boda.domain.Course"/></typeAliases><typeHandlers>元素15.1.5在MyBatis為PreparedStatement設置參數(shù)或從ResultSet檢索一個值時,都會用類型處理器(TypeHandler)將獲取的值以合適的方式轉換為Java類型。表15-3列出了MyBatis常用的默認類型處理器。注意,目前MyBatis已支持JSR-310(日期-時間API)。<objectFactory>元素15.1.6MyBatis每次創(chuàng)建結果對象的新實例時,都會使用一個對象工廠(ObjectFactory)實例來完成。
默認的對象工廠需要做的僅僅是實例化目標類,要么通過默認構造方法,要么在參數(shù)映射存在的時候通過參數(shù)構造方法來實例化。如果想覆蓋對象工廠的默認行為,則可以通過創(chuàng)建自己的對象工廠來實現(xiàn)。<databaseIdProvider>元素15.1.7MyBatis可以根據不同的數(shù)據庫廠商執(zhí)行不同的語句,這種多廠商的支持是基于映射語句中的databaseId屬性。MyBatis會加載不帶databaseId屬性和帶有匹配當前數(shù)據庫databaseId屬性的所有語句。如果同時找到帶有databaseId和不帶databaseId的相同語句,則后者會被舍棄。為支持多廠商特性只要像下面這樣在mybatis-config.xml文件中加入databaseIdProvider即可:<databaseIdProvidertype="DB_VENDOR"/><mappers>元素5.1.8<mappers>元素用來配置映射器,它告訴MyBatis到哪里去找映射文件??梢允褂孟鄬τ陬惵窂降馁Y源引用,或完全限定資源定位符(包括file:///的URL),或類名和包名等。例如:<!--使用相對于類路徑的資源引用--><mappers><mapperresource="com/boda/mapper/AuthorMapper.xml"/><mapperresource="com/boda/mapper/BlogMapper.xml"/><mapperresource="com/boda/mapper/PostMapper.xml"/></mappers><!—使用URL完全限定路徑--><mappers><mapperurl="file:///var/mappers/AuthorMapper.xml"/><mapperurl="file:///var/mappers/BlogMapper.xml"/></mappers><!--使用映射器接口類--><mappers><mapperclass="com.boda.mapper.TutorMapper"/><mapperclass="com.boda.mapper.AddressMapper"/><mapperclass="com.boda.mapper.StudentMapper"/></mappers><!--注冊一個包中所有接口作為映射器--><mappers><packagename="com.boda.mapper"/></mappers>映射文件15.2
MyBatis使用映射文件描述持久化類和數(shù)據庫表之間的映射關系。映射文件的根元素是<mapper>,其namespace屬性用來指定一個命名空間名,namespace的值習慣上設置為“包名+映射文件名”,這樣可以保證namespace的值是唯一的。映射文件中<mapper>元素包含的子元素有:<select>,映射SQL查詢語句。<insert>,映射SQL插入語句。<delete>,映射SQL刪除語句。<update>,映射SQL更新語句。<cache>,給定命名空間的緩存配置。<cache-ref>,其他命名空間緩存配置的引用。<sql>,可被其他語句引用的可重用語句塊。<resultMap>,最復雜也是最強大的元素,描述如何從數(shù)據庫結果集中加載對象。<select>元素15.2.1<select>元素用于定義一個SQL查詢語句,該查詢語句供SqlSession對象的查詢方法執(zhí)行數(shù)據庫查詢。下面<select>元素根據學生stud_id查詢學生信息。<selectid="findStudentById"parameterType="Integer"resultType="com.boda.domain.Student">SELECTstud_idAS
studId,name,gender,birthday,phoneFROMstudentsWHEREstud_id=#{studId}</select><select>元素15.2.1注意,#{studId}用于指定一個名為studId的參數(shù)。這將使MyBatis創(chuàng)建一個預處理語句,語句中參數(shù)用一個“?”來標識,并將參數(shù)值傳遞到預處理語句中。以上語句執(zhí)行時會生成如下JDBC代碼。Stringsql="SELECTstud_idASstudId,name,gender,birthday,phoneFROMstudentsWHEREstud_id=?";PreparedStatementps=conn.prepareStatement(sql);ps.setInt(1,studId);<select>元素15.2.1MyBatis將執(zhí)行查詢語句并將查詢結果映射到結果對象中,這就是MyBatis節(jié)省時間的地方。下面代碼是為該SQL語句創(chuàng)建的Mapper接口。packagecom.boda.mapper;publicinterfaceStudentMapper{StudentfindStudentById(IntegerstudId);}StudentMapper接口中定義了findStudentById()方法。注意,該方法名必須與<select>元素映射的id屬性值相同。在測試類MyBatisTest中編寫findStudentByIdTest()方法,查詢stud_id值為20221002的學生信息,代碼如下。@TestpublicvoidfindStudentByIdTest(){SqlSessionsession=MyBatisUtil.getSession();StudentMappermapper=session.getMapper(StudentMapper.class);try{ Studentstudent=mapper.findStudentById(20220009); if(student!=null)System.out.println(student);elseSystem.out.println("查無此記錄");}catch(Exceptione){ System.out.println(e);}finally{mit();session.close();}}<select>元素15.2.1有時查詢結果并不能(或不需要)映射到一個POJO對象,這時可以將resultType屬性設置為map或hashmap,使得查詢結果返回一個HashMap對象,查詢結果字段名作為Map的鍵名,字段值作為Map的值,在程序中對結果Map對象進行迭代即可。<selectid="selectSumSalary"resultType="hashmap">SELECTid,name,salary*12assumsalaryFROMemployees</select><select>元素15.2.1假設在EmployeeMapper接口中定義了selectSumSalary()方法。在測試類MyBatisTest中編寫selectSumSalaryTest()方法,查詢所有員工id、name和sumsalary,它是salary*12的結果,代碼如下。publicvoidselectSumSalaryTest(){SqlSessionsession=MyBatisUtil.getSession();EmployeeMappermapper=session.getMapper(EmployeeMapper.class);try{
List<Map<String,Object>>result=mapper.selectSumSalary(); if(result!=null){for(Map<String,Object>hm:result){ System.out.println(hm);}}elseSystem.out.println("查無此記錄");}catch(Exceptione){System.out.println(e);}finally{ mit();session.close();}}參數(shù)傳遞15.2.2在有些SQL語句(包括SELECT、INSERT、UPDATE和DELETE)中可以使用參數(shù),參數(shù)可以是簡單的類型(如,int、double),也可以是復雜的類型(如,JavaBean或Map等)。語句的參數(shù)類型使用parameterType屬性指定。下面映射語句帶一個int型的簡單參數(shù)。<selectid="selectUser"parameterType="int"
resultType="com.boda.domain.User">SELECTuser_id,user_name,user_passwordFROMuserswhereuser_id=#{id}</select>參數(shù)傳遞15.2.2參數(shù)是MyBatis非常強大的元素,也可以為SQL語句傳遞一個復雜的對象,比如:這里為INSERT語句傳遞一個User類型的參數(shù),MyBatis會查找User對象的id、username和password屬性,然后將它們的值傳入PreparedStatement語句的對應參數(shù)中。<insertid="insertUser"parameterType="com.boda.domain.User">INSERTINTOusers(user_id,user_name,user_password)VALUES(#{id},#{username},#{password})</insert>在傳遞參數(shù)時還可以指定參數(shù)的具體類型,如下所示。#{amount,javaType=int,jdbcType=NUMERIC}<insert>元素15.2.3<insert>元素用于定義SQL插入語句,在執(zhí)行完定義的SQL語句后,會返回一個表示插入記錄數(shù)的整數(shù)。下面的<insert>元素配置在students表中插入一行,如下所示:這里,語句id值為insertStudent,它唯一標識INSERT語句。parameterType屬性值應該是完全限定的類名或類型別名。<insertid="insertStudent"parameterType="com.boda.domain.Student">INSERTINTOstudents(stud_id,name,gender,birthday,phone)VALUES(#{studId},#{name},#{gender},#{birthday},#{phone})</insert><insert>元素15.2.3假設在StudentMapper接口中定義了如下insertStudent()方法:就可以像下面這樣調用insertStudent映射語句:publicinterfaceStudentMapper{intinsertStudent(Studentstudent);}StudentMappermapper=sqlSession.getMapper(StudentMapper.class);intcount=mapper.insertStudent(student);<insert>元素15.2.3<insert>元素用于定義SQL插入語句,在執(zhí)行完定義的SQL語句后,會返回一個表示插入記錄數(shù)的整數(shù)。下面的<insert>元素配置在students表中插入一行,如下所示:這里,語句id值為insertStudent,它唯一標識INSERT語句。parameterType屬性值應該是完全限定的類名或類型別名。<insertid="insertStudent"parameterType="com.boda.domain.Student">INSERTINTOstudents(stud_id,name,gender,birthday,phone)VALUES(#{studId},#{name},#{gender},#{birthday},#{phone})</insert><update>元素15.2.4<update>元素用于定義SQL更新語句,它的使用比較簡單,它的屬性與<select>元素屬性基本相同。下面的更新語句根據studId值更新students表的name、gender、birthday和phone字段值,新值通過一個Student對象提供。這里的參數(shù)名是傳遞來的持久對象的屬性名,它們可以與表的字段名不同,可以只更新部分字段值。與<insert>元素一樣,<update>元素定義的更新語句在執(zhí)行完后,也會返回一個表示所影響的記錄行數(shù)的整數(shù)值。<updateid="updateStudent"parameterType="com.boda.domain.Student">UPDATEstudentsSETname=#{name},gender=#{gender},birthday=#{birthday},phone=#{phone}WHEREstud_id=#{studId}</update><update>元素15.2.4假設在StudentMapper接口中定義了如下updateStudent(Studentstudent)方法:publicinterfaceStudentMapper{intupdateStudent(Studentstudent);}<update>元素15.2.4在測試類MyBatisTest中編寫updateStudentTest()方法,更新studId值為20221020的學生姓名name值修改為“張小明”,gender修改為“女”,出生日期birthday修改為“2000-05-10”,電話phone修改為“987654321”,代碼如下。publicvoidupdateStudentTest(){ SqlSessionsession=MyBatisUtil.getSession();StudentMappermapper=session.getMapper(StudentMapper.class);try{Studentstudent=newStudent(20221020,"張明宇","女",LocalDate.of(2000,05,10),"987654321"); introws=mapper.updateStudent(student);if(rows==1)System.out.println("記錄更新成功");elseSystem.out.println("記錄更新失敗");}finally{ mit();session.close();}}<delete>元素15.2.5<delete>元素用于定義SQL刪除語句,它的使用也比較簡單,它的屬性與<select>元素屬性基本相同。下面的<delete>元素定義了刪除語句,它根據studId值刪除students表中的記錄。這里的參數(shù)studId可以通過Student對象傳遞,也可以通過Map對象傳遞。假設在StudentMapper接口中定義了如下deleteStudent(Map<String,Integer>param)方法:<deleteid="deleteStudent"parameterType="map">DELETEFROMstudentsWHEREstud_id=#{studId}</delete>publicinterfaceStudentMapper{intdeleteStudent(Map<String,Integer>param);}<delete>元素15.2.5
在測試類MyBatisTest中編寫deleteStudentTest()方法,刪除studId值為20221020的學生,代碼如下。publicvoiddeleteStudentTest(){SqlSessionsession=MyBatisUtil.getSession();StudentMappermapper=session.getMapper(StudentMapper.class);try{Map<String,Integer>params=newHashMap<>();params.put("studId",20221020); introws=mapper.deleteStudent(params);if(rows==1)System.out.println("成功刪除"+rows+"條記錄");elseSystem.out.println("刪除記錄失敗");}finally{ mit();session.close();}}<resultMap>元素15.2.6<resultMap>元素用于定義一個結果集映射,它的作用是將SELECT語句的結果映射到JavaBean的屬性。可以定義ResultMap,之后就可以在其他的SELECT語句中引用該<resultMap>。
該元素是功能最強大的元素,用它可以映射簡單的SELECT語句,也可以映射帶一對一關聯(lián)和一對多關聯(lián)的復雜SELECT語句。15.2.61.簡單的ResultMap下面是一個簡單的ResultMap,它將一個簡單查詢的結果映射到Student這個JavaBean上。<resultMapid="studentResult"type="com.boda.domain.Student"><idproperty="studId"column="stud_id"/><resultproperty="name"column="name"/><resultproperty="gender"column="gender"/><resultproperty="birthday"column="birthday"/><resultproperty="phone"column="phone"/></resultMap>這里,id屬性指定這個resultMap的唯一標識,type屬性指定這個resultMap實際返回的類型,它可以是完整的類名,也可以是別名。property屬性指定結果JavaBean類的屬性名,column屬性指定數(shù)據庫表的字段名。15.2.6有了這個ResultMap,我們就可以在<select>元素中使用resultMap屬性而不是resultType來引用這個studentResult映射。當為<select>元素配置resultMap屬性時,MyBatis使用屬性映射的列來填充JavaBean屬性。下面兩個<select>元素中使用了studentResult映射。<selectid="findAllStudents"resultMap="studentResult">SELECT*FROMSTUDENTS</select><selectid="findStudentById"parameterType="int"resultMap="studentResult">SELECT*FROMSTUDENTSWHEREstud_id=#{studId}</select>15.2.62.擴展的ResultMap可以從另一個<resultMap>查詢擴展一個<resultMap>查詢,從而繼承該列,從被擴展的列進行屬性映射。假設已經定義了id為studentResult的映射,如果我們需要查詢學生及地址信息,就可以擴展studentResult映射實現(xiàn),這需要使用extends屬性,如下代碼所示。<resultMapid="studentWithAddressResult"type="com.boda.domain.Student"
extends="studentResult"><resultproperty="address.addrId"column="addr_id"/><resultproperty="address.city"column="city"/><resultproperty="address.street"column="street"/><resultproperty="address.zipcode"column="zipcode"/></resultMap>15.2.6現(xiàn)在如果要將查詢Student結果與查詢Address結果映射到一起,就可以使用resultMap與studentWithAddressResult一起使用,如下所示:<selectid="selectStudentWithAddress"parameterType="int"resultMap="studentWithAddressResult">SELECTstud_id,name,gender,birthday,phone,a.addr_id,city,street,zipcodeFROMstudentssleftouterjoinaddressaons.addr_id=a.addr_idWHEREstud_id=#{studId}</select><sql>元素15.2.7<sql>元素用于定義一個可復用的SQL代碼片段,它可以包含在其他語句中。下面代碼定義一個名為empColumns的SQL片段,然后在<select>元素中引用它。在其他元素中使用<include>元素引用SQL片段,它用refid屬性指定所引用的SQL片段的id。<sqlid="empColumns">id,name,title,salary</sql><selectid="selectEmployee"resultType="com.boda.domain.Employee">SELECT<includerefid="empColumns"/>FROMemployees</select><sql>元素15.2.7還可定義參數(shù)化SQL片段,通過${param_name}指定參數(shù),在include元素中使用property子元素指定參數(shù)值,例如。該SQL片段就可被包含在另一個語句中,如下所示。<sqlid="userColumns">${alias}.id,${alias}.username,${alias}.password</sql><selectid="selectUsers"resultType="map">SELECT<includerefid="userColumns"><propertyname="alias"value="t1"/></include>,<includerefid="userColumns"><propertyname="alias"value="t2"/></include>FROMsome_tablet1CROSSJOINsome_tablet2</select>
<cache>元素15.2.8MyBatis提供了緩存機制來緩存查詢數(shù)據,以提高查詢的性能。MyBatis的緩存分為一級緩存和二級緩存。1.一級緩存一級緩存是SqlSession級別的緩存,是基于HashMap的本地緩存。不同的SqlSession之間的緩存數(shù)據區(qū)域互不影響。一級緩存的作用域是會話范圍,當同一個SqlSession執(zhí)行兩次相同的SQL語句時,第一次執(zhí)行完后會將查詢的數(shù)據寫到緩存,第二次查詢時直接從緩存獲取不用去數(shù)據庫查詢。當SqlSession執(zhí)行INSERT、UPDATE、DELETE操做并提交到數(shù)據庫時,會清空緩存,保證緩存中的信息是最新的。
<cache>元素15.2.82.二級緩存二級緩存是Mapper級別的緩存,同樣是基于HashMap進行存儲,多個SqlSession可以共用二級緩存,其作用域是mapper的同一個namespace。不同的SqlSession兩次執(zhí)行相同的namespace下的sql語句,會執(zhí)行相同的sql,第二次查詢只會查詢第一次查詢時讀取數(shù)據庫后寫到緩存的數(shù)據,不會再去數(shù)據庫查詢。MyBatis默認開啟一級緩存,要開啟二級緩存,只需在SQL映射文件中寫入如下代碼:<cache/>MyBatis關聯(lián)映射15.3
在SQL的查詢語句中,如果查詢結果來自多個表的數(shù)據,需要使用連接查詢。這種關聯(lián)在Java程序中需要通過對象的關聯(lián)實現(xiàn)。
在MyBatis中,這種關聯(lián)通過<association>和<collection>元素實現(xiàn),前者實現(xiàn)一對一關聯(lián),后者實現(xiàn)一對多關聯(lián)。一對一關聯(lián)映射15.3.1一對一關聯(lián)在實際應用中比較常見,例如學生(Student)與學生的地址(Address)之間就具有一對一的關聯(lián)關系,如圖15-7所示。一對一關聯(lián)映射15.3.1下面通過實例說明如何實現(xiàn)這種關聯(lián)映射。(1)創(chuàng)建數(shù)據表。在數(shù)據庫中創(chuàng)建address表和students表,同時插入兩條數(shù)據。執(zhí)行的SQL語句如清單15.2所示。清單15.2創(chuàng)建address表和students表及插入數(shù)據CREATETABLEaddress(addr_idINTPRIMARYKEYAUTO_INCREMENT,--IDcityVARCHAR(20),--城市streetVARCHAR(20),--街道zipcodeVARCHAR(6)--郵編);#插入兩條數(shù)據INSERTINTOaddressVALUES(1,'廣州','黃埔區(qū)5號','510700');INSERTINTOaddressVALUES(2,'北京','海淀區(qū)28號','100089');#創(chuàng)建students表,其中addr_id引用address表的addr_id列,是外鍵CREATETABLEstudents(stud_idINTEGERAUTO_INCREMENTPRIMARYKEY,--IDnameVARCHAR(20)NOTNULL,--姓名genderVARCHAR(4),--性別birthdayDATE,--出生日期phoneVARCHAR(14),--電話
addr_idINT,--外鍵,引用address表的addr_idFOREIGNKEY(addr_id)REFERENCESaddress(addr_id));#插入兩條數(shù)據INSERTINTOstudentsVALUES(20220008,'張大海','男','1983-10-20','8899123',1);INSERTINTOstudentsVALUES(20220009,'李清泉','女','1990-12-31','1305045168',2);一對一關聯(lián)映射15.3.1(2)在項目的com.boda.domain包中創(chuàng)建Address和Student實體類,為了建立Student和Address之間的一對一關聯(lián),在Student類中定義了引用Address類的屬性(address)及setter和getter方法。代碼如清單15.3和清單15.4所示。清單15.3Address.java清單15.4修改Student.java,添加address屬性及方法Address.java清單15.3@Data@NoArgsConstructor@AllArgsConstructorpublicclassAddressimplementsSerializable{privateIntegeraddrId;privateStringcity;privateStringstreet;@Override publicStringtoString(){ return"地址:"+city+street+zipcode; }}修改Student.java,添加address屬性及方法清單15.4publicclassStudentimplementsSerializable{…privateAddressaddress;
publicAddressgetAddress(){ returnaddress;}publicvoidsetAddress(Addressaddress){ this.address=address;}
@OverridepublicStringtoString(){ return"學生[studId="+studId+",name="+name+",gender="+gender+",birthday="+birthday+",phone="+phone+"]“+"\n"+address;}}一對一關聯(lián)映射15.3.1(3)在com.boda.mapper包中創(chuàng)建Address類和Student類的映射文件AddressMapper.xml和StudentMapper.xml,并在兩個映射文件中編寫一對一關聯(lián)映射查詢的配置信息,如清單15.5和清單15.6所示。清單15.5AddressMapper.xml清單15.6StudentMapper.xmlAddressMapper.xml清單15.5<mappernamespace="com.boda.mapper.AddressMapper"><!--定義addressResult結果映射--><resultMapid="addressResult"type="com.boda.domain.Address"><idproperty="addrId"column="addr_id"/><resultproperty="city"column="city"/><resultproperty="street"column="street"/><resultproperty="zipcode"column="zipcode"/></resultMap><!--根據addrId查詢地址信息--><selectid="selectAddressById"parameterType="Integer“
resultMap="addressResult">SELECT*FROMaddressWHEREaddr_id=#{addrId}</select></mapper>StudentMapper.xml清單15.6<mappernamespace="com.boda.mapper.StudentMapper"><!--定義一個resultMap進行關聯(lián)查詢--><resultMapid="studentResultWithAddress"type="com.boda.domain.Student"><idproperty="studId"column="stud_id"/><resultproperty="name"column="name"/><resultproperty="gender"column="gender"/>…
<associationproperty="address"column="addr_id"javaType="com.boda.domain.Address"select="com.boda.mapper.AddressMapper.selectAddressById"/></resultMap><!--定義一個SELECT語句,根據指定studId查詢表數(shù)據。--><selectid="selectStudentById"parameterType="Integer"resultMap="studentResultWithAddress">SELECT*FROMstudentsWHEREstud_id=#{studId}</select></mapper>一對一關聯(lián)映射15.3.1(4)在核心配置文件mybatis-config.xml中,引入Mapper映射文件并定義別名,如程序所示。<mappers><mapperresource="com/boda/mapper/AddressMapper.xml"/><mapperresource="com/boda/mapper/StudentMapper.xml"/></mappers>一對一關聯(lián)映射15.3.1(5)在com.boda.mapper包中,創(chuàng)建Address類和Student類的Mapper映射器接口,代碼如下所示。清單15.7AddressMapper.javapublicinterfaceAddressMapper{//根據addrId查詢Address方法AddressselectAddressById(intaddrId);}一對一關聯(lián)映射15.3.1清單15.8StudentMapper.javapackagecom.boda.mapper;importcom.boda.doamin.Student;publicinterfaceStudentMapper{//根據studId查詢Student方法StudentselectStudentById(intstudId);}一對一關聯(lián)映射15.3.1(6)在com.boda.test包的MyBatisTest類中,編寫測試方法selectStudentByIdTest(),代碼如下所示。@TestpublicvoidselectStudentByIdTest(){SqlSessionsession=MyBatisUtil.getSession();try{StudentMappermapper=session.getMapper(StudentMapper.class);Studentstudent=mapper.selectStudentById(20221002);System.out.println(student);//輸出查詢到的學生信息}finally{mit();session.close();}}一對多關聯(lián)映射15.3.2一對多關聯(lián)最常見,例如一名教師(Tutor)可講授多門課程(Course)就是典型的一對多聯(lián)系,如圖15-9所示。下面以教師和課程為例說明如何進行一對多關聯(lián)的映射。一對多關聯(lián)映射15.3.2MyBatis在處理一對多關聯(lián)時使用<resultMap>的<collection>子元素。<collection>子元素的大部分屬性與<association>元素的屬性相同,但其還包含一個名為ofType的特殊屬性。ofType屬性與javaType屬性對應,它用于指定持久化對象中集合類屬性所包含的元素類型。<collection>元素的使用也非常簡單,同樣可以參考如下兩個示例進行配置,具體代碼如下。<!--方式一:嵌套查詢--><collectionproperty="courses"ofType="com.boda.domain.Course"select="com.boda.mapper.TutorMapper.selectTutorById"><!--方式二:嵌套結果--><collectionproperty="courses"ofType="com.boda.domain.Course"><idproperty="tutorId"column="tutor_id"/><resultproperty="name"column="name"/><resultproperty="title"column="title"/><resultproperty="email"column="email"/></collection>一對多關聯(lián)映射15.3.2(1)在數(shù)據庫中創(chuàng)建兩個表,分別為tutors和courses,用于存儲教師和課程數(shù)據,同時在表中插入幾條數(shù)據,執(zhí)行的SQL語句如下。清單15.9創(chuàng)建tutors表和courses表及插入數(shù)據。CREATETABLEtutors(tutor_idINTPRIMARYKEYAUTO_INCREMENT,nameVARCHAR(10),titleVARCHAR(10),emailVARCHAR(20));#創(chuàng)建名為courses課程表CREATETABLEcourses(course_idINTPRIMARYKEYAUTO_INCREMENT,nameVARCHAR(20),start_dateDATE,end_dateDATE,tutor_idINTREFERENCEStutors(tutor_id));一對多關聯(lián)映射15.3.2(2)在com.boda.domain包中,創(chuàng)建Course和Tutor類,代碼如清單15.10和15.11所示。清單15.10Course.java清單15.11Tutor.javapublicclassTutor{privateIntegertutorId;privateStringname;privateStringtitle;privateStringemail;privateList<Course>courses;//教師講授的課程列表一對多關聯(lián)映射15.3.2(3)在com.boda.mapper包中,創(chuàng)建Tutor類的映射文件TutorMapper.xml,并在文件中編寫一對多關聯(lián)映射查詢的配置,代碼如清單15.12所示。本例采用嵌套結果的方式進行映射。清單15.12TutorMapper.xml一對多關聯(lián)映射15.3.2(4)將映射文件TutorMapper.xml添加到核心配置文件mybatis-config.xml中,其代碼如下所示。<mapperresource="com/boda/mapper/TutorMapper.xml"/>(5)在com.boda.mapper包中,創(chuàng)建Tutor類的Mapper映射器接口,代碼如下所示。清單15.13TutorMapper.javapublicinterfaceTutorMapper{//根據tutorId查詢Tutor對象TutorselectTutorById(inttutorId);}一對多關聯(lián)映射15.3.2(6)在測試類com.boda.test.MyBatisTest中編寫測試方法selectTutorByIdTest(),代碼如下所示。@TestpublicvoidselectTutorByIdTest(){SqlSessionsession=MyBatisUtil.getSession();TutorMappermapper=session.getMapper(TutorMapper.class);try{Tutortutor=mapper.selectTutorById(2); //輸出指定教師的任課信息System.out.println(tutor); System.out.println(tutor.getCourses()); }finally{mit(); session.close();}}動態(tài)SQL15.4MyBatis允許在映射SQL語句中使用動態(tài)功能,它是通過標簽元素實現(xiàn)的。如果用戶使用過JSTL,這些動態(tài)SQL語句標簽就很容易理解,常用元素如表15-8所示。元素說明<if>判斷語句,用于單條件分支判斷<choose>、<when>和<otherwise>用于多條件分支判斷。相當于Java的switch…case結構<where>、<set>和<trim>用于指定SQL的條件以及UPDATE語句的SET以及特殊字符問題<foreach>循環(huán)語句,常用于in語句等列舉條件中<bind>從OGNL表達式中創(chuàng)建一個變量,并將其綁定到上下文,常用于模糊查詢的語句<if>元素15.4.1在動態(tài)SQL中最常見的情況就是在SQL的WHERE子句中有條件地包含一部分內容,例如:<selectid="findActiveEmployee"resultType="Employee">SELECT*FROMemployeeWHEREstate=’ACTIVE’<iftest="title!=null">ANDtitleLIKE#{title}</if></select><if>元素15.4.1也可以使用<if>提供多個條件,如下所示:<selectid="findActiveEmployee"resultType="Employee">SELECT*FROMemployeeWHEREstate=’ACTIVE’<iftest="title!=null">ANDtitleLIKE#{title}</if><iftest="salary!=null">ANDsalary>#{salary}</if></select><if>元素15.4.1下面通過實例說明動態(tài)SQL語句的使用。按下列步驟創(chuàng)建項目及有關文件。(1)首先在數(shù)據庫中創(chuàng)建employees表,并向表中插入若干記錄,代碼如下。CREATETABLEemployees(
idINTPRIMARYKEYAUTO_INCREMENT,--員工id
nameVARCHAR(10),--姓名
titleVARCHAR(10),--職務
ageINT,--年齡
salaryDECIMAL(8,2),--工資
statusVARCHAR(10)--狀態(tài));<if>元素15.4.1(2)在com.boda.domain包中創(chuàng)建Employee實體類,代碼如下。清單15.14Employee.javapublicclassEmployee{privateIntegerid;privateStringname;privateStringtitle;privateintage;privatedoublesalary;privateStringstatus;}<if>元素15.4.1(3)在com.boda.mapper包中,創(chuàng)建EmployeeMapper.xml映射文件,使用<if>元素定義一個SQL查詢語句,如下所示。<mappernamespace="com.boda.mapper.EmployeeMapper"><selectid="findActiveEmployee"resultType="com.boda.domain.Employee">SELECT*FROMemployeesWHEREstatus='ACTIVE'<iftest="title!=null">ANDtitleLIKE#{title}</if><iftest="salary!=null">ANDsalary>#{salary}</if></select></mapper><if>元素15.4.1(4)將映射文件EmployeeMapper.xml路徑添加到配置文件mybatis-config.xml中。<mapperresource="com/boda/mapper/EmployeeMapper.xml"/>(5)在com.boda.mapper包中,創(chuàng)建EmployeeMapper.java映射器接口,其中定義selectEmployeeOnCondition()方法。清單15.15EmployeeMapper.javaimportcom.boda.domain.Employee;publicinterfaceEmployeeMapper{//根據條件查詢員工信息 publicList<Employee>findActiveEmployee(Objectparam);}<if>元素15.4.1在測試類MyBatisTest中,編寫測試方法findActiveEmployeeOTest(),代碼如下所示。@TestpublicvoidfindActiveEmployeeTest(){SqlSessionsession=MyBatisUtil.getSession();Map<String,String>param=newHashMap<>();
param.put("status","ACTIVE");try{ EmployeeMappermapper=session.getMapper(EmployeeMapper.class); List<Employee>employee
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 英漢交互口譯課程設計
- 體育行業(yè)助理的日常工作內容和能力要求
- 內科護士工作心得
- 情境教學法在班級中的應用計劃
- 建筑行業(yè)客服工作思考
- 酒店管理技術要點概述
- 旅游景區(qū)衛(wèi)生凈化
- 2024年甜甜的秘密教案
- 2024年認識數(shù)學的教案
- 2024年認識空氣教案
- 網絡切片技術概述
- 2024年度醫(yī)院各科室醫(yī)務人員述職報告之皮膚科課件
- 《急性心梗的自救》課件
- 中成藥手冊完整版本
- 2023-2024學年成都市金牛區(qū)九年級上英語(一診)期末考試題(含答案)
- 2023年MC主管年終業(yè)務工作總結
- 廣東省物業(yè)管理條例2024:業(yè)主大會與業(yè)主委員會組織規(guī)定
- 員工賠償金保密協(xié)議
- 空靈鼓社團教學計劃
- (法律資料)城管執(zhí)法操作實務
- 廣東省珠海市2022-2023六年級上學期數(shù)學期末試卷(含答案)
評論
0/150
提交評論