版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、79/79Mybatis框架課程講師:傳智.燕青Mybatis入門單獨(dú)使用jdbc編程問(wèn)題總結(jié)jdbc程序Publicstaticvoid main(String args) Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;try /加載數(shù)據(jù)庫(kù)驅(qū)動(dòng)Class.forName(com.mysql.jdbc.Driver);/通過(guò)驅(qū)動(dòng)管理類獲取數(shù)據(jù)庫(kù)鏈接connection = DriverManager.getConnection(jdbc:mys
2、ql:/localhost:3306/mybatis?characterEncoding=utf-8, root, mysql);/定義sql語(yǔ)句 ?表示占位符String sql = select *from userwhere username = ?;/獲取預(yù)處理statementpreparedStatement = connection.prepareStatement(sql);/設(shè)置參數(shù),第一個(gè)參數(shù)為sql語(yǔ)句中參數(shù)的序號(hào)(從1開(kāi)始),第二個(gè)參數(shù)為設(shè)置的參數(shù)值preparedStatement.setString(1, 王五);/向數(shù)據(jù)庫(kù)發(fā)出sql執(zhí)行查詢,查詢出結(jié)果集resul
3、tSet = preparedStatement.executeQuery();/遍歷查詢結(jié)果集while(resultSet.next()System.out.println(resultSet.getString(id)+ +resultSet.getString(username); catch (Exception e) e.printStackTrace();finally/釋放資源if(resultSet!=null)try resultSet.close(); catch (SQLException e) / TODO Auto-generated catch blocke.pr
4、intStackTrace();if(preparedStatement!=null)try preparedStatement.close(); catch (SQLException e) / TODO Auto-generated catch blocke.printStackTrace();if(connection!=null)try connection.close(); catch (SQLException e) / TODO Auto-generated catch blocke.printStackTrace();上邊使用jdbc的原始方法(未經(jīng)封裝)實(shí)現(xiàn)了查詢數(shù)據(jù)庫(kù)表記錄
5、的操作。jdbc編程步驟:加載數(shù)據(jù)庫(kù)驅(qū)動(dòng)創(chuàng)建并獲取數(shù)據(jù)庫(kù)鏈接創(chuàng)建jdbc statement對(duì)象設(shè)置sql語(yǔ)句設(shè)置sql語(yǔ)句中的參數(shù)(使用preparedStatement)通過(guò)statement執(zhí)行sql并獲取結(jié)果對(duì)sql執(zhí)行結(jié)果進(jìn)行解析處理釋放資源(resultSet、preparedstatement、connection)jdbc問(wèn)題總結(jié)如下:數(shù)據(jù)庫(kù)鏈接創(chuàng)建、釋放頻繁造成系統(tǒng)資源浪費(fèi)從而影響系統(tǒng)性能,如果使用數(shù)據(jù)庫(kù)鏈接池可解決此問(wèn)題。Sql語(yǔ)句在代碼中硬編碼,造成代碼不易維護(hù),實(shí)際應(yīng)用sql變化的可能較大,sql變動(dòng)需要改變java代碼。使用preparedStatement向占有位符
6、號(hào)傳參數(shù)存在硬編碼,因?yàn)閟ql語(yǔ)句的where條件不一定,可能多也可能少,修改sql還要修改代碼,系統(tǒng)不易維護(hù)。對(duì)結(jié)果集解析存在硬編碼(查詢列名),sql變化導(dǎo)致解析代碼變化,系統(tǒng)不易維護(hù),如果能將數(shù)據(jù)庫(kù)記錄封裝成pojo對(duì)象解析比較方便。MyBatis介紹MyBatis 本是 HYPERLINK :/baike.baidu /view/28283.htm apache的一個(gè)開(kāi)源項(xiàng)目 HYPERLINK :/baike.baidu /view/628102.htm iBatis, 2010年這個(gè)項(xiàng)目由apache software foundation 遷移到了google code,并且改名
7、為MyBatis,實(shí)質(zhì)上Mybatis對(duì)ibatis進(jìn)行一些改進(jìn)。MyBatis是一個(gè)優(yōu)秀的持久層框架,它對(duì)jdbc的操作數(shù)據(jù)庫(kù)的過(guò)程進(jìn)行封裝,使開(kāi)發(fā)者只需要關(guān)注SQL 本身,而不需要花費(fèi)精力去處理例如注冊(cè)驅(qū)動(dòng)、創(chuàng)建connection、創(chuàng)建statement、手動(dòng)設(shè)置參數(shù)、結(jié)果集檢索等jdbc繁雜的過(guò)程代碼。Mybatis通過(guò)xml或注解的方式將要執(zhí)行的各種statement(statement、preparedStatemnt、CallableStatement)配置起來(lái),并通過(guò)java對(duì)象和statement中的sql進(jìn)行映射生成最終執(zhí)行的sql語(yǔ)句,最后由mybatis框架執(zhí)行sql并
8、將結(jié)果映射成java對(duì)象并返回。Mybatis架構(gòu)mybatis配置SqlMapConfig.xml,此文件作為mybatis的全局配置文件,配置了mybatis的運(yùn)行環(huán)境等信息。mapper.xml文件即sql映射文件,文件中配置了操作數(shù)據(jù)庫(kù)的sql語(yǔ)句。此文件需要在SqlMapConfig.xml中加載。通過(guò)mybatis環(huán)境等配置信息構(gòu)造SqlSessionFactory即會(huì)話工廠由會(huì)話工廠創(chuàng)建sqlSession即會(huì)話,操作數(shù)據(jù)庫(kù)需要通過(guò)sqlSession進(jìn)行。mybatis底層自定義了Executor執(zhí)行器接口操作數(shù)據(jù)庫(kù),Executor接口有兩個(gè)實(shí)現(xiàn),一個(gè)是基本執(zhí)行器、一個(gè)是緩存
9、執(zhí)行器。Mapped Statement也是mybatis一個(gè)底層封裝對(duì)象,它包裝了mybatis配置信息與sql映射信息等。mapper.xml文件中一個(gè)sql對(duì)應(yīng)一個(gè)Mapped Statement對(duì)象,sql的id即是Mapped statement的id。Mapped Statement對(duì)sql執(zhí)行輸入?yún)?shù)進(jìn)行定義,包括HashMap、基本類型、pojo,Executor通過(guò)Mapped Statement在執(zhí)行sql前將輸入的java對(duì)象映射至sql中,輸入?yún)?shù)映射就是jdbc編程中對(duì)preparedStatement設(shè)置參數(shù)。Mapped Statement對(duì)sql執(zhí)行輸出結(jié)果進(jìn)行
10、定義,包括HashMap、基本類型、pojo,Executor通過(guò)Mapped Statement在執(zhí)行sql后將輸出結(jié)果映射至java對(duì)象中,輸出結(jié)果映射過(guò)程相當(dāng)于jdbc編程中對(duì)結(jié)果的解析處理過(guò)程。mybatis下載mybaits的代碼由github管理,地址: s:/github /mybatis/mybatis-3/releasesmybatis-3.2.7.jarmybatis的核心包libmybatis的依賴包mybatis-3.2.7.pdfmybatis使用手冊(cè)創(chuàng)建mysql數(shù)據(jù)庫(kù)先導(dǎo)入sql_table.sql,再導(dǎo)入 sql_data.sql腳本:如下:Mybatis入門程
11、序需求實(shí)現(xiàn)以下功能:根據(jù)用戶id查詢一個(gè)用戶信息根據(jù)用戶名稱模糊查詢用戶信息列表添加用戶更新用戶刪除用戶第一步:創(chuàng)建java工程使用eclipse創(chuàng)建java工程,jdk使用1.7.0_72。第二步:加入jar包加入mybatis核心包、依賴包、數(shù)據(jù)驅(qū)動(dòng)包。第三步:perties在classpath下創(chuàng)建perties如下:# Global logging configurationlog4j.rootLogger=DEBUG, stdout# Console output.log4j.appender.stdout=org.apache.log4j.Con
12、soleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%5p %t - %m%nmybatis默認(rèn)使用log4j作為輸出日志信息。第四步:SqlMapConfig.xml在classpath下創(chuàng)建SqlMapConfig.xml,如下:SqlMapConfig.xml是mybatis核心配置文件,上邊文件的配置內(nèi)容為數(shù)據(jù)源、事務(wù)管理。第五步:po類Po類作為mybatis進(jìn)行sql映射使用,po類通常與數(shù)據(jù)庫(kù)表對(duì)應(yīng)
13、,User.java如下:PublicclassUser privateintid;private String username;/ 用戶XXprivate String sex;/ 性別private Date birthday;/ 生日private String address;/ 地址get/set第六步:程序編寫(xiě)查詢映射文件:在classpath下的sqlmap目錄下創(chuàng)建sql映射文件Users.xml:namespace :命名空間,用于隔離sql語(yǔ)句,后面會(huì)講另一層非常重要的作用。在SqlMapConfig.xml中添加:select * from userwhere id =
14、 #id select * from userwhere username like %$value% parameterType:定義輸入到sql中的映射類型,#id表示使用preparedstatement設(shè)置占位符號(hào)并將輸入變量id傳到sql。resultType:定義結(jié)果映射類型。加載映射文件mybatis框架需要加載映射文件,將Users.xml添加在SqlMapConfig.xml,如下:測(cè)試程序:publicclass Mybatis_first /會(huì)話工廠private SqlSessionFactory sqlSessionFactory;Beforepublicvoid c
15、reateSqlSessionFactory() throws IOException / 配置文件String resource = SqlMapConfig.xml;InputStream inputStream = Resources.getResourceAsStream(resource);/ 使用SqlSessionFactoryBuilder從xml配置文件中創(chuàng)建SqlSessionFactorysqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);/ 根據(jù) id查詢用戶信息Testpublic
16、void testFindUserById() / 數(shù)據(jù)庫(kù)會(huì)話實(shí)例SqlSession sqlSession = null;try / 創(chuàng)建數(shù)據(jù)庫(kù)會(huì)話實(shí)例sqlSessionsqlSession = sqlSessionFactory.openSession();/ 查詢單個(gè)記錄,根據(jù)用戶id查詢用戶信息Useruser = sqlSession.selectOne(test.findUserById, 10);/ 輸出用戶信息System.out.println(user); catch (Exception e) e.printStackTrace(); finally if (sqlSe
17、ssion != null) sqlSession.close();/ 根據(jù)用戶名稱模糊查詢用戶信息Testpublicvoid testFindUserByUsername() / 數(shù)據(jù)庫(kù)會(huì)話實(shí)例SqlSession sqlSession = null;try / 創(chuàng)建數(shù)據(jù)庫(kù)會(huì)話實(shí)例sqlSessionsqlSession = sqlSessionFactory.openSession();/ 查詢單個(gè)記錄,根據(jù)用戶id查詢用戶信息List list = sqlSession.selectList(test.findUserByUsername, 張);System.out.println(
18、list.size(); catch (Exception e) e.printStackTrace(); finally if (sqlSession != null) sqlSession.close();#和$#表示一個(gè)占位符號(hào),通過(guò)#可以實(shí)現(xiàn)preparedStatement向占位符中設(shè)置值,自動(dòng)進(jìn)行java類型和jdbc類型轉(zhuǎn)換,#可以有效防止sql注入。#可以接收簡(jiǎn)單類型值或pojo屬性值。如果parameterType傳輸單個(gè)簡(jiǎn)單類型值,#括號(hào)中可以是value或其它名稱。$表示拼接sql串,通過(guò)$可以將parameterType 傳入的內(nèi)容拼接在sql中且不進(jìn)行jdbc類型轉(zhuǎn)換
19、,$可以接收簡(jiǎn)單類型值或pojo屬性值,如果parameterType傳輸單個(gè)簡(jiǎn)單類型值,$括號(hào)中只能是value。parameterType和resultTypeparameterType:指定輸入?yún)?shù)類型,mybatis通過(guò)ognl從輸入對(duì)象中獲取參數(shù)值拼接在sql中。resultType:指定輸出結(jié)果類型,mybatis將sql查詢結(jié)果的一行記錄數(shù)據(jù)映射為resultType指定類型的對(duì)象。selectOne和selectListselectOne查詢一條記錄,如果使用selectOne查詢多條記錄則拋出異常:org.apache.ibatis.exceptions.TooManyRes
20、ultsException: Expected one result (or null) to be returned by selectOne(), but found: 3at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)selectList可以查詢一條或多條記錄。添加映射文件:在SqlMapConfig.xml中添加:select LAST_INSERT_ID() insert into user(username,birthday,sex,address
21、) values(#username,#birthday,#sex,#address)測(cè)試程序:/ 添加用戶信息Testpublicvoid testInsert() / 數(shù)據(jù)庫(kù)會(huì)話實(shí)例SqlSession sqlSession = null;try / 創(chuàng)建數(shù)據(jù)庫(kù)會(huì)話實(shí)例sqlSessionsqlSession = sqlSessionFactory.openSession();/ 添加用戶信息Useruser =new User();user.setUsername(張小明);user.setAddress(河南鄭州);user.setSex(1);user.setPrice(1999.9
22、f);sqlSession.insert(test.insertUser, user);/提交事務(wù)sqlSession mit(); catch (Exception e) e.printStackTrace(); finally if (sqlSession != null) sqlSession.close();mysql自增主鍵返回通過(guò)修改sql映射文件,可以將mysql自增主鍵返回:select LAST_INSERT_ID()insert into user(username,birthday,sex,address) values(#username,#birthday,#sex,
23、#address);添加selectKey實(shí)現(xiàn)將主鍵返回keyProperty:返回的主鍵存儲(chǔ)在pojo中的哪個(gè)屬性order:selectKey的執(zhí)行順序,是相對(duì)與insert語(yǔ)句來(lái)說(shuō),由于mysql的自增原理執(zhí)行完insert語(yǔ)句之后才將主鍵生成,所以這里selectKey的執(zhí)行順序?yàn)閍fterresultType:返回的主鍵是什么類型LAST_INSERT_ID():是mysql的函數(shù),返回auto_increment自增列新記錄id值。Mysql使用uuid實(shí)現(xiàn)主鍵需要增加通過(guò)select uuid()得到uuid值select uuid()insert into user(id,us
24、ername,birthday,sex,address) values(#id,#username,#birthday,#sex,#address)注意這里使用的order是“BEFORE”O(jiān)racle使用序列生成主鍵首先自定義一個(gè)序列且用于生成主鍵,selectKey使用如下:SELECT 自定義序列.NEXTVAL FROM DUALinsert into user(id,username,birthday,sex,address) values(#id,#username,#birthday,#sex,#address)注意這里使用的order是“BEFORE”刪除映射文件:delete
25、 from userwhere id=#id測(cè)試程序:/ 根據(jù)id刪除用戶TestpublicvoidtestDelete() / 數(shù)據(jù)庫(kù)會(huì)話實(shí)例SqlSession sqlSession = null;try / 創(chuàng)建數(shù)據(jù)庫(kù)會(huì)話實(shí)例sqlSessionsqlSession = sqlSessionFactory.openSession();/ 刪除用戶sqlSession.delete(test.deleteUserById,18);/ 提交事務(wù)sqlSession mit(); catch (Exception e) e.printStackTrace(); finally if (sql
26、Session != null) sqlSession.close();修改映射文件update userset username=#username,birthday=#birthday,sex=#sex,address=#addresswhere id=#id測(cè)試程序/ 更新用戶信息TestpublicvoidtestUpdate() / 數(shù)據(jù)庫(kù)會(huì)話實(shí)例SqlSession sqlSession = null;try / 創(chuàng)建數(shù)據(jù)庫(kù)會(huì)話實(shí)例sqlSessionsqlSession = sqlSessionFactory.openSession();/ 添加用戶信息Useruser =new
27、 User();user.setId(16);user.setUsername(張小明);user.setAddress(河南鄭州);user.setSex(1);user.setPrice(1999.9f);sqlSession.update(test.updateUser, user);/ 提交事務(wù)sqlSession mit(); catch (Exception e) e.printStackTrace(); finally if (sqlSession != null) sqlSession.close();Mybatis解決jdbc編程的問(wèn)題數(shù)據(jù)庫(kù)鏈接創(chuàng)建、釋放頻繁造成系統(tǒng)資源浪費(fèi)
28、從而影響系統(tǒng)性能,如果使用數(shù)據(jù)庫(kù)鏈接池可解決此問(wèn)題。解決:在SqlMapConfig.xml中配置數(shù)據(jù)鏈接池,使用連接池管理數(shù)據(jù)庫(kù)鏈接。Sql語(yǔ)句寫(xiě)在代碼中造成代碼不易維護(hù),實(shí)際應(yīng)用sql變化的可能較大,sql變動(dòng)需要改變java代碼。解決:將Sql語(yǔ)句配置在XXXXmapper.xml文件中與java代碼分離。向sql語(yǔ)句傳參數(shù)麻煩,因?yàn)閟ql語(yǔ)句的where條件不一定,可能多也可能少,占位符需要和參數(shù)一一對(duì)應(yīng)。解決:Mybatis自動(dòng)將java對(duì)象映射至sql語(yǔ)句,通過(guò)statement中的parameterType定義輸入?yún)?shù)的類型。對(duì)結(jié)果集解析麻煩,sql變化導(dǎo)致解析代碼變化,且解析前
29、需要遍歷,如果能將數(shù)據(jù)庫(kù)記錄封裝成pojo對(duì)象解析比較方便。解決:Mybatis自動(dòng)將sql執(zhí)行結(jié)果映射至java對(duì)象,通過(guò)statement中的resultType定義輸出結(jié)果的類型。與hibernate不同Mybatis和hibernate不同,它不完全是一個(gè)ORM框架,因?yàn)镸yBatis需要程序員自己編寫(xiě)Sql語(yǔ)句,不過(guò)mybatis可以通過(guò)XML或注解方式靈活配置要運(yùn)行的sql語(yǔ)句,并將java對(duì)象和sql語(yǔ)句映射生成最終執(zhí)行的sql,最后將sql執(zhí)行的結(jié)果再映射生成java對(duì)象。Mybatis學(xué)習(xí)門檻低,簡(jiǎn)單易學(xué),程序員直接編寫(xiě)原生態(tài)sql,可嚴(yán)格控制sql執(zhí)行性能,靈活度高,非常適
30、合對(duì)關(guān)系數(shù)據(jù)模型要求不高的軟件開(kāi)發(fā),例如互聯(lián)網(wǎng)軟件、企業(yè)運(yùn)營(yíng)類軟件等,因?yàn)檫@類軟件需求變化頻繁,一但需求變化要求成果輸出迅速。但是靈活的前提是mybatis無(wú)法做到數(shù)據(jù)庫(kù)無(wú)關(guān)性,如果需要實(shí)現(xiàn)支持多種數(shù)據(jù)庫(kù)的軟件則需要自定義多套sql映射文件,工作量大。Hibernate對(duì)象/關(guān)系映射能力強(qiáng),數(shù)據(jù)庫(kù)無(wú)關(guān)性好,對(duì)于關(guān)系模型要求高的軟件(例如需求固定的定制化軟件)如果用hibernate開(kāi)發(fā)可以節(jié)省很多代碼,提高效率。但是Hibernate的學(xué)習(xí)門檻高,要精通門檻更高,而且怎么設(shè)計(jì)O/R映射,在性能和對(duì)象模型之間如何權(quán)衡,以與怎樣用好Hibernate需要具有很強(qiáng)的經(jīng)驗(yàn)和能力才行??傊凑沼脩舻男?/p>
31、求在有限的資源環(huán)境下只要能做出維護(hù)性、擴(kuò)展性良好的軟件架構(gòu)都是好架構(gòu),所以框架只有適合才是最好。Dao開(kāi)發(fā)方法使用Mybatis開(kāi)發(fā)Dao,通常有兩個(gè)方法,即原始Dao開(kāi)發(fā)方法和Mapper接口開(kāi)發(fā)方法。需求將下邊的功能實(shí)現(xiàn)Dao:根據(jù)用戶id查詢一個(gè)用戶信息根據(jù)用戶名稱模糊查詢用戶信息列表添加用戶信息SqlSession的使用范圍SqlSession中封裝了對(duì)數(shù)據(jù)庫(kù)的操作,如:查詢、插入、更新、刪除等。通過(guò)SqlSessionFactory創(chuàng)建SqlSession,而SqlSessionFactory是通過(guò)SqlSessionFactoryBuilder進(jìn)行創(chuàng)建。SqlSessionFact
32、oryBuilderSqlSessionFactoryBuilder用于創(chuàng)建SqlSessionFacoty,SqlSessionFacoty一旦創(chuàng)建完成就不需要SqlSessionFactoryBuilder了,因?yàn)镾qlSession是通過(guò)SqlSessionFactory生產(chǎn),所以可以將SqlSessionFactoryBuilder當(dāng)成一個(gè)工具類使用,最佳使用范圍是方法范圍即方法體內(nèi)局部變量。SqlSessionFactorySqlSessionFactory是一個(gè)接口,接口中定義了openSession的不同重載方法,SqlSessionFactory的最佳使用范圍是整個(gè)應(yīng)用運(yùn)行期間
33、,一旦創(chuàng)建后可以重復(fù)使用,通常以單例模式管理SqlSessionFactory。SqlSessionSqlSession是一個(gè)面向用戶的接口,sqlSession中定義了數(shù)據(jù)庫(kù)操作,默認(rèn)使用DefaultSqlSession實(shí)現(xiàn)類。執(zhí)行過(guò)程如下:加載數(shù)據(jù)源等配置信息Environment environment = configuration.getEnvironment();創(chuàng)建數(shù)據(jù)庫(kù)鏈接創(chuàng)建事務(wù)對(duì)象創(chuàng)建Executor,SqlSession所有操作都是通過(guò)Executor完成,mybatis源碼如下:if (ExecutorType.BATCH = executorType) execut
34、or = newBatchExecutor(this, transaction); elseif (ExecutorType.REUSE = executorType) executor = new ReuseExecutor(this, transaction); else executor = new SimpleExecutor(this, transaction); if (cacheEnabled) executor = new CachingExecutor(executor, autoCommit); SqlSession的實(shí)現(xiàn)類即DefaultSqlSession,此對(duì)象中對(duì)操
35、作數(shù)據(jù)庫(kù)實(shí)質(zhì)上用的是Executor結(jié)論:每個(gè)線程都應(yīng)該有它自己的SqlSession實(shí)例。SqlSession的實(shí)例不能共享使用,它也是線程不安全的。因此最佳的范圍是請(qǐng)求或方法范圍。絕對(duì)不能將SqlSession實(shí)例的引用放在一個(gè)類的靜態(tài)字段或?qū)嵗侄沃?。打開(kāi)一個(gè) SqlSession;使用完畢就要關(guān)閉它。通常把這個(gè)關(guān)閉操作放到 finally 塊中以確保每次都能執(zhí)行關(guān)閉。如下:SqlSession session = sqlSessionFactory.openSession();try / do work finally session.close();原始Dao開(kāi)發(fā)方式原始Dao開(kāi)發(fā)方
36、法需要程序員編寫(xiě)Dao接口和Dao實(shí)現(xiàn)類。映射文件select * from userwhere id = #idselect LAST_INSERT_ID() insert into user(username,birthday,sex,address) values(#username,#birthday,#sex,#address)Dao接口Publicinterface UserDao publicUser getUserById(int id) throws Exception;publicvoid insertUser(Useruser)throws Exception;Publi
37、cclass UserDaoImpl implements UserDao /注入SqlSessionFactorypublic UserDaoImpl(SqlSessionFactory sqlSessionFactory)this.setSqlSessionFactory(sqlSessionFactory);private SqlSessionFactory sqlSessionFactory;Overridepublic UsergetUserById(int id) throws Exception SqlSession session = sqlSessionFactory.ope
38、nSession();Useruser =null;try /通過(guò)sqlsession調(diào)用selectOne方法獲取一條結(jié)果集/參數(shù)1:指定定義的statement的id,參數(shù)2:指定向statement中傳遞的參數(shù)user = session.selectOne(test.findUserById, 1);System.out.println(user); finallysession.close();returnuser;OverridePublicvoid insertUser(Useruser)throws Exception SqlSession sqlSession= sqlSes
39、sionFactory.openSession();try sqlSession.insert(insertUser, user);sqlSession mit(); finallysession.close();問(wèn)題原始Dao開(kāi)發(fā)中存在以下問(wèn)題:Dao方法體存在重復(fù)代碼:通過(guò)SqlSessionFactory創(chuàng)建SqlSession,調(diào)用SqlSession的數(shù)據(jù)庫(kù)操作方法調(diào)用sqlSession的數(shù)據(jù)庫(kù)操作方法需要指定statement的id,這里存在硬編碼,不得于開(kāi)發(fā)維護(hù)。Mapper動(dòng)態(tài)代理方式實(shí)現(xiàn)原理Mapper接口開(kāi)發(fā)方法只需要程序員編寫(xiě)Mapper接口(相當(dāng)于Dao接口),由My
40、batis框架根據(jù)接口定義創(chuàng)建接口的動(dòng)態(tài)代理對(duì)象,代理對(duì)象的方法體同上邊Dao接口實(shí)現(xiàn)類方法。Mapper接口開(kāi)發(fā)需要遵循以下規(guī)范:Mapper.xml文件中的namespace與mapper接口的類路徑一樣。Mapper接口方法名和Mapper.xml中定義的每個(gè)statement的id一樣Mapper接口方法的輸入?yún)?shù)類型和mapper.xml中定義的每個(gè)sql 的parameterType的類型一樣Mapper接口方法的輸出參數(shù)類型和mapper.xml中定義的每個(gè)sql的resultType的類型一樣Mapper.xml(映射文件)定義mapper映射文件UserMapper.xml(
41、內(nèi)容同Users.xml),需要修改namespace的值為UserMapper接口路徑。將UserMapper.xml放在classpath 下mapper目錄下。select * from userwhere id = #id select * from user where username like %$value% select LAST_INSERT_ID() insert into user(username,birthday,sex,address) values(#username,#birthday,#sex,#address)Mapper.java(接口文件)/* * 用
42、戶管理mapper */Publicinterface UserMapper /根據(jù)用戶id查詢用戶信息publicUser findUserById(int id) throws Exception;/查詢用戶列表public List findUserByUsername(String username) throws Exception;/添加用戶信息publicvoid insertUser(Useruser)throws Exception; 接口定義有如下特點(diǎn):Mapper接口方法名和Mapper.xml中定義的statement的id一樣Mapper接口方法的輸入?yún)?shù)類型和map
43、per.xml中定義的statement的parameterType的類型一樣Mapper接口方法的輸出參數(shù)類型和mapper.xml中定義的statement的resultType的類型一樣加載UserMapper.xml文件修改SqlMapConfig.xml文件:測(cè)試Publicclass UserMapperTest extends TestCase private SqlSessionFactory sqlSessionFactory;protectedvoid setUp() throws Exception /mybatis配置文件String resource = sqlMap
44、Config.xml;InputStream inputStream = Resources.getResourceAsStream(resource);/使用SqlSessionFactoryBuilder創(chuàng)建sessionFactorysqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);Publicvoid testFindUserById() throws Exception /獲取sessionSqlSession session = sqlSessionFactory.openSession();
45、/獲取mapper接口的代理對(duì)象UserMapper userMapper = session.getMapper(UserMapper.class);/調(diào)用代理對(duì)象方法Useruser = userMapper.findUserById(1);System.out.println(user);/關(guān)閉sessionsession.close();Testpublicvoid testFindUserByUsername() throws Exception SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper us
46、erMapper = sqlSession.getMapper(UserMapper.class);List list = userMapper.findUserByUsername(張);System.out.println(list.size();Publicvoid testInsertUser() throws Exception /獲取sessionSqlSession session = sqlSessionFactory.openSession();/獲取mapper接口的代理對(duì)象UserMapper userMapper = session.getMapper(UserMapp
47、er.class);/要添加的數(shù)據(jù)Useruser =new User();user.setUsername(張三);user.setBirthday(new Date();user.setSex(1);user.setAddress(市);/通過(guò)mapper接口添加用戶userMapper.insertUser(user);/提交session mit();/關(guān)閉sessionsession.close();總結(jié)selectOne和selectList動(dòng)態(tài)代理對(duì)象調(diào)用sqlSession.selectOne()和sqlSession.selectList()是根據(jù)mapper接口方法的返回值
48、決定,如果返回list則調(diào)用selectList方法,如果返回單個(gè)對(duì)象則調(diào)用selectOne方法。namespacemybatis官方推薦使用mapper代理方法開(kāi)發(fā)mapper接口,程序員不用編寫(xiě)mapper接口實(shí)現(xiàn)類,使用mapper代理方法時(shí),輸入?yún)?shù)可以使用pojo包裝對(duì)象或map對(duì)象,保證dao的通用性。SqlMapConfig.xml配置文件配置內(nèi)容SqlMapConfig.xml中配置的內(nèi)容和順序如下:properties(屬性)settings(全局配置參數(shù))typeAliases(類型別名)typeHandlers(類型處理器)objectFactory(對(duì)象工廠)plug
49、ins(插件)environments(環(huán)境集合屬性對(duì)象)environment(環(huán)境子屬性對(duì)象)transactionManager(事務(wù)管理)dataSource(數(shù)據(jù)源)mappers(映射器)properties(屬性)SqlMapConfig.xml可以引用java屬性文件中的配置信息如下:在classpath下定義perties文件,jdbc.driver=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql:/localhost:3306/mybatisjdbc.username=rootjdbc.password=mysqlSqlMapC
50、onfig.xml引用如下:注意: MyBatis 將按照下面的順序來(lái)加載屬性:在properties 元素體內(nèi)定義的屬性首先被讀取。然后會(huì)讀取properties 元素中resource或 url加載的屬性,它會(huì)覆蓋已讀取的同名屬性。最后讀取parameterType傳遞的屬性,它會(huì)覆蓋已讀取的同名屬性。因此,通過(guò)parameterType傳遞的屬性具有最高優(yōu)先級(jí),resource或 url 加載的屬性次之,最低優(yōu)先級(jí)的是properties 元素體內(nèi)定義的屬性。settings(配置)mybatis全局配置參數(shù),全局參數(shù)將會(huì)影響mybatis的運(yùn)行行為。詳細(xì)參見(jiàn)“學(xué)習(xí)資料/mybatis-
51、settings.xlsx”文件typeAliases(類型別名)mybatis支持別名:別名映射的類型_byte byte _long long _short short _int int _integer int _double double _float float _boolean boolean string String byte Byte long Long short Short int Integer integer Integer double Double float Float boolean Boolean date Date decimal BigDecimal b
52、igdecimal BigDecimal 自定義別名:在SqlMapConfig.xml中配置:typeHandlers(類型處理器)類型處理器用于java類型和jdbc類型映射,如下:select * from userwhere id = #idmybatis自帶的類型處理器基本上滿足日常需求,不需要單獨(dú)定義。mybatis支持類型處理器:類型處理器Java類型JDBC類型BooleanTypeHandler Boolean,boolean 任何兼容的布爾值ByteTypeHandler Byte,byte 任何兼容的數(shù)字或字節(jié)類型ShortTypeHandler Short,short
53、任何兼容的數(shù)字或短整型IntegerTypeHandler Integer,int 任何兼容的數(shù)字和整型LongTypeHandler Long,long 任何兼容的數(shù)字或長(zhǎng)整型FloatTypeHandler Float,float 任何兼容的數(shù)字或單精度浮點(diǎn)型DoubleTypeHandler Double,double 任何兼容的數(shù)字或雙精度浮點(diǎn)型BigDecimalTypeHandler BigDecimal 任何兼容的數(shù)字或十進(jìn)制小數(shù)類型StringTypeHandler String CHAR和VARCHAR類型ClobTypeHandler String CLOB和LONGVAR
54、CHAR類型NStringTypeHandler String NVARCHAR和NCHAR類型NClobTypeHandler String NCLOB類型ByteArrayTypeHandler byte 任何兼容的字節(jié)流類型BlobTypeHandler byte BLOB和LONGVARBINARY類型DateTypeHandler Date(java.util)TIMESTAMP類型DateOnlyTypeHandler Date(java.util)DATE類型TimeOnlyTypeHandler Date(java.util)TIME類型SqlTimestampTypeHand
55、ler Timestamp(java.sql)TIMESTAMP類型SqlDateTypeHandler Date(java.sql)DATE類型SqlTimeTypeHandler Time(java.sql)TIME類型ObjectTypeHandler 任意其他或未指定類型EnumTypeHandler Enumeration類型VARCHAR-任何兼容的字符串類型,作為代碼存儲(chǔ)(而不是索引)。mappers(映射器)Mapper配置的幾種方法:使用相對(duì)于類路徑的資源如:使用完全限定路徑如:使用mapper接口類路徑如:注意:此種方法要求mapper接口名稱和mapper映射文件名稱一樣
56、,且放在同一個(gè)目錄中。注冊(cè)指定包下的所有mapper接口如:注意:此種方法要求mapper接口名稱和mapper映射文件名稱一樣,且放在同一個(gè)目錄中。Mapper.xml映射文件Mapper.xml映射文件中定義了操作數(shù)據(jù)庫(kù)的sql,每個(gè)sql是一個(gè)statement,映射文件是mybatis的核心。parameterType(輸入類型)#與$#實(shí)現(xiàn)的是向prepareStatement中的預(yù)處理語(yǔ)句中設(shè)置參數(shù)值,sql語(yǔ)句中#表示一個(gè)占位符即?。select * from userwhere id = #id使用占位符#可以有效防止sql注入,在使用時(shí)不需要關(guān)心參數(shù)值的類型,mybatis會(huì)
57、自動(dòng)進(jìn)行java類型和jdbc類型的轉(zhuǎn)換。#可以接收簡(jiǎn)單類型值或pojo屬性值,如果parameterType傳輸單個(gè)簡(jiǎn)單類型值,#括號(hào)中可以是value或其它名稱。$和#不同,通過(guò)$可以將parameterType 傳入的內(nèi)容拼接在sql中且不進(jìn)行jdbc類型轉(zhuǎn)換, $可以接收簡(jiǎn)單類型值或pojo屬性值,如果parameterType傳輸單個(gè)簡(jiǎn)單類型值,$括號(hào)中只能是value。使用$不能防止sql注入,但是有時(shí)用$會(huì)非常方便,如下的例子: select * from userwhere username like %$value%如果本例子使用#則傳入的字符串中必須有%號(hào),而%是人為拼接在
58、參數(shù)中,顯然有點(diǎn)麻煩,如果采用$在sql中拼接為%的方式則在調(diào)用mapper接口傳遞參數(shù)就方便很多。/如果使用占位符號(hào)則必須人為在傳參數(shù)中加%List list = userMapper.selectUserByName(%管理員%);/如果使用$原始符號(hào)則不用人為在參數(shù)中加%Listlist = userMapper.selectUserByName(管理員);再比如order by排序,如果將列名通過(guò)參數(shù)傳入sql,根據(jù)傳的列名進(jìn)行排序,應(yīng)該寫(xiě)為:ORDER BY $columnName如果使用#將無(wú)法實(shí)現(xiàn)此功能。傳遞簡(jiǎn)單類型參考上邊的例子。傳遞pojo對(duì)象Mybatis使用ognl表達(dá)式
59、解析對(duì)象字段的值,如下例子: select * from userwhere id=#id and username like %$username%上邊紅色標(biāo)注的是user對(duì)象中的字段名稱。測(cè)試:Publicvoid testFindUserByUser()throws Exception/獲取sessionSqlSession session = sqlSessionFactory.openSession();/獲限mapper接口實(shí)例UserMapper userMapper = session.getMapper(UserMapper.class);/構(gòu)造查詢條件user對(duì)象Useru
60、ser =new User();user.setId(1);user.setUsername(管理員);/傳遞user對(duì)象查詢用戶列表Listlist = userMapper.findUserByUser(user);/關(guān)閉sessionsession.close();異常測(cè)試:Sql中字段名輸入錯(cuò)誤后測(cè)試,username輸入dusername測(cè)試結(jié)果報(bào)錯(cuò):org.apache.ibatis.exceptions.PersistenceException: # Error querying database. Cause: org.apache.ibatis.reflection.Refl
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025版滅鼠防治技術(shù)專利授權(quán)合同4篇
- 2025年度電梯安裝與智能化運(yùn)維服務(wù)保障合同4篇
- 二零二五年度促銷員突發(fā)事件應(yīng)急處理合同4篇
- 2025年度生態(tài)廊道建設(shè)承包樹(shù)木合同范本3篇
- 2025年度航空航天設(shè)備研發(fā)合同協(xié)議2篇
- 二零二五年度房屋維修基金管理合同4篇
- 二零二五年度城市綠化工程勞動(dòng)合同范本3篇
- 二零二五年度明星演唱會(huì)演出合同范本4篇
- 2025年度車輛租賃市場(chǎng)推廣合作合同7篇
- 二零二五年度存量房交易糾紛調(diào)解合同范本3篇
- 五年級(jí)上冊(cè)寒假作業(yè)答案(人教版)
- 2025年山東浪潮集團(tuán)限公司招聘25人高頻重點(diǎn)提升(共500題)附帶答案詳解
- 2024年財(cái)政部會(huì)計(jì)法律法規(guī)答題活動(dòng)題目及答案一
- 2025年江西省港口集團(tuán)招聘筆試參考題庫(kù)含答案解析
- (2024年)中國(guó)傳統(tǒng)文化介紹課件
- 液化氣安全檢查及整改方案
- 《冠心病》課件(完整版)
- 2024年云網(wǎng)安全應(yīng)知應(yīng)會(huì)考試題庫(kù)
- 公園保潔服務(wù)投標(biāo)方案
- 光伏電站項(xiàng)目合作開(kāi)發(fā)合同協(xié)議書(shū)三方版
- 禪密功筑基功法
評(píng)論
0/150
提交評(píng)論