Mybatis介紹
MyBatis 本是apache的一個(gè)開源項(xiàng)目iBatis, 2010年這個(gè)項(xiàng)目由apache software foundation 遷移到了google code,并且改名為MyBatis 。2013年11月遷移到Github。
MyBatis是一個(gè)優(yōu)秀的持久層框架,它對(duì)jdbc的操作數(shù)據(jù)庫(kù)的過程進(jìn)行封裝,使開發(fā)者只需要關(guān)注 SQL 本身,而不需要花費(fèi)精力去處理例如注冊(cè)驅(qū)動(dòng)、創(chuàng)建connection、創(chuàng)建statement、手動(dòng)設(shè)置參數(shù)、結(jié)果集檢索等jdbc繁雜的過程代碼。
Mybatis通過xml或注解的方式將要執(zhí)行的各種statement(statement、preparedStatemnt、CallableStatement)配置起來,并通過java對(duì)象和statement中的sql進(jìn)行映射生成最終執(zhí)行的sql語句,最后由mybatis框架執(zhí)行sql并將結(jié)果映射成java對(duì)象并返回。
JDBC存在的問題
1、? 數(shù)據(jù)庫(kù)連接創(chuàng)建、釋放頻繁造成系統(tǒng)資源浪費(fèi),從而影響系統(tǒng)性能。如果使用數(shù)據(jù)庫(kù)連接池可解決此問題。
2、? Sql語句在代碼中硬編碼,造成代碼不易維護(hù),實(shí)際應(yīng)用中sql變化的可能較大,sql變動(dòng)需要改變java代碼。
3、? 使用preparedStatement向占有位符號(hào)傳參數(shù)存在硬編碼,因?yàn)閟ql語句的where條件不一定,可能多也可能少,修改sql還要修改代碼,系統(tǒng)不易維護(hù)。
4、? 對(duì)結(jié)果集解析存在硬編碼(查詢列名),sql變化導(dǎo)致解析代碼變化,系統(tǒng)不易維護(hù),如果能將數(shù)據(jù)庫(kù)記錄封裝成pojo對(duì)象解析比較方便。
Mybatis架構(gòu)

Mybatis架構(gòu)
Mybatis使用
mybaits的代碼由github.com管理
下載地址:https://github.com/mybatis/mybatis-3/releases
mybatis如下:

圖片.png
目錄結(jié)構(gòu)
mybatis-3.2.7.jar? ? mybatis的核心包
lib文件夾? ? ? ? ? ? mybatis的依賴包所在
mybatis-3.2.7.pdf mybatis使用手冊(cè)
創(chuàng)建核心配置文件
<?xml version="1.0"encoding="UTF-8"?><!DOCTYPE configuration
? ? ? ? PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
? ? ? ? "http://mybatis.org/dtd/mybatis-3-config.dtd"><!-- 和spring整合后 environments配置將廢除 --><!-- 使用jdbc事務(wù)管理 --><!-- 數(shù)據(jù)庫(kù)連接池 -->
src目錄下創(chuàng)建log4j.properties jdbc.properties
# Global logging configurationlog4j.rootLogger=DEBUG,stdout# Console output...log4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
創(chuàng)建pojo映射文件 User.xml
<?xml version="1.0"encoding="UTF-8"?><!DOCTYPE mapper
? ? ? ? PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
? ? ? ? "http://mybatis.org/dtd/mybatis-3-mapper.dtd">SELECT *? ? ? ? FROM `user`? ? ? ? WHERE id = #{v}
標(biāo)簽解釋
在pojo的映射文件xml中,包含<select>、<insert>、<update>、<delete> 分別對(duì)應(yīng) 查詢、添加、更新、刪除操作
其中 id 代表對(duì)應(yīng)標(biāo)簽的識(shí)別id
parameterType代表占位符的類型
resultType 代表返回值類型
語句解釋
#{v}代表占位符 占位符標(biāo)識(shí)為v
${value}代表字符串拼接 標(biāo)識(shí)必須為value
select * from userwhereusername like'%xx%'
對(duì)應(yīng)的UserMap.xml配置文件中的SQL文件寫法
SELECT * FROM `user`whereusername like"%"#{v}"%"
測(cè)試代碼
@TestpublicvoidtestSelectOne()throwsIOException{//創(chuàng)建SqlSessionFactoryBuilder對(duì)象SqlSessionFactoryBuilder builder =newSqlSessionFactoryBuilder();//加載SqlMapConfig.xml配置文件 創(chuàng)建SqlSessionFactorySqlSessionFactory sessionFactory = builder.build(Resources.getResourceAsStream("SqlMapConfig.xml"));//創(chuàng)建SqlSession對(duì)象SqlSession sqlSession = sessionFactory.openSession();//SqlSession執(zhí)行對(duì)象查詢User user = (User) sqlSession.selectOne("queryUserById",1);? ? ? ? System.out.println(user);//釋放資源sqlSession.close();? ? }
insert
映射文件 mapper sql書寫
<!-- 返回最后插入的主鍵id -->SELECT LAST_INSERT_ID()insert into user(username,birthday,address,sex) values(#{username},#{birthday},#{address},#{sex})
update
映射文件 mapper sql
<!--更新用戶-->update user? ? ? ? set username=#{username},ses=#{sex},birthday=#{birthday},address=#{address}? ? ? ? where id = #{id}
測(cè)試代碼
@TestpublicvoidtestUpdateUserById()throwsIOException{? ? ? ? SqlSessionFactoryBuilder builder =newSqlSessionFactoryBuilder();? ? ? ? SqlSessionFactory sessionFactory = builder.build(Resources.getResourceAsStream("sqlMapConfig.xml"));? ? ? ? SqlSession sqlSession = sessionFactory.openSession();? ? ? ? User user =newUser();? ? ? ? user.setId(33);? ? ? ? user.setUsername("www33333");? ? ? ? user.setSex("釹");? ? ? ? user.setBirthday(newDate());? ? ? ? user.setAddress("332211aasss");intline = sqlSession.insert("test.updateUserById", user);? ? ? ? sqlSession.commit();? ? ? ? System.out.println(line);? ? }
delete
Mapper映射文件
<!--刪除用戶-->DELETE from user? ? ? ? WHERE id = #{vvvv}
測(cè)試代碼
@TestpublicvoidtestDeleteUserById()throwsIOException{? ? ? ? SqlSessionFactoryBuilder builder =newSqlSessionFactoryBuilder();? ? ? ? SqlSessionFactory sessionFactory = builder.build(Resources.getResourceAsStream("sqlMapConfig.xml"));? ? ? ? SqlSession sqlSession = sessionFactory.openSession();? ? ? ? sqlSession.delete("test.deleteUserById",32);? ? ? ? sqlSession.commit();? ? }
MyBatis 解決JDBC的需求
1、數(shù)據(jù)庫(kù)連接創(chuàng)建、釋放頻繁造成系統(tǒng)資源浪費(fèi)從而影響系統(tǒng)性能,如果使用數(shù)據(jù)庫(kù)連接池可解決此問題。
解決:在SqlMapConfig.xml中配置數(shù)據(jù)連接池,使用連接池管理數(shù)據(jù)庫(kù)鏈接。
2、Sql語句寫在代碼中造成代碼不易維護(hù),實(shí)際應(yīng)用sql變化的可能較大,sql變動(dòng)需要改變java代碼。
解決:將Sql語句配置在XXXXmapper.xml文件中與java代碼分離。
3、向sql語句傳參數(shù)麻煩,因?yàn)閟ql語句的where條件不一定,可能多也可能少,占位符需要和參數(shù)一一對(duì)應(yīng)。
解決:Mybatis自動(dòng)將java對(duì)象映射至sql語句,通過statement中的parameterType定義輸入?yún)?shù)的類型。
4、對(duì)結(jié)果集解析麻煩,sql變化導(dǎo)致解析代碼變化,且解析前需要遍歷,如果能將數(shù)據(jù)庫(kù)記錄封裝成pojo對(duì)象解析比較方便。
解決:Mybatis自動(dòng)將sql執(zhí)行結(jié)果映射至java對(duì)象,通過statement中的resultType定義輸出結(jié)果的類型
提出一個(gè)需求
MyBatis與HIbernate的不同
Mybatis和hibernate不同,它不完全是一個(gè)ORM框架,因?yàn)镸yBatis需要程序員自己編寫Sql語句。mybatis可以通過XML或注解方式靈活配置要運(yùn)行的sql語句,并將java對(duì)象和sql語句映射生成最終執(zhí)行的sql,最后將sql執(zhí)行的結(jié)果再映射生成java對(duì)象。
Mybatis學(xué)習(xí)門檻低,簡(jiǎn)單易學(xué),程序員直接編寫原生態(tài)sql,可嚴(yán)格控制sql執(zhí)行性能,靈活度高,非常適合對(duì)關(guān)系數(shù)據(jù)模型要求不高的軟件開發(fā),例如互聯(lián)網(wǎng)軟件、企業(yè)運(yùn)營(yíng)類軟件等,因?yàn)檫@類軟件需求變化頻繁,一但需求變化要求成果輸出迅速。但是靈活的前提是mybatis無法做到數(shù)據(jù)庫(kù)無關(guān)性,如果需要實(shí)現(xiàn)支持多種數(shù)據(jù)庫(kù)的軟件則需要自定義多套sql映射文件,工作量大。
Hibernate對(duì)象/關(guān)系映射能力強(qiáng),數(shù)據(jù)庫(kù)無關(guān)性好,對(duì)于關(guān)系模型要求高的軟件(例如需求固定的定制化軟件)如果用hibernate開發(fā)可以節(jié)省很多代碼,提高效率。但是Hibernate的學(xué)習(xí)門檻高,要精通門檻更高,而且怎么設(shè)計(jì)O/R映射,在性能和對(duì)象模型之間如何權(quán)衡,以及怎樣用好Hibernate需要具有很強(qiáng)的經(jīng)驗(yàn)和能力才行。
總之,按照用戶的需求在有限的資源環(huán)境下只要能做出維護(hù)性、擴(kuò)展性良好的軟件架構(gòu)都是好架構(gòu),所以框架只有適合才是最好。
Mapper動(dòng)態(tài)代理方式開發(fā)
開發(fā)規(guī)范
Mapper接口開發(fā)方法只需要程序員編寫Mapper接口(相當(dāng)于Dao接口),由Mybatis框架根據(jù)接口定義創(chuàng)建接口的動(dòng)態(tài)代理對(duì)象,代理對(duì)象的方法體同上邊Dao接口實(shí)現(xiàn)類方法。
Mapper接口開發(fā)需要遵循以下規(guī)范:
1、? ? Mapper.xml文件中的namespace與mapper接口的類路徑相同。
2、Mapper接口方法名和Mapper.xml中定義的每個(gè)statement的id相同
3、Mapper接口方法的輸入?yún)?shù)類型和mapper.xml中定義的每個(gè)sql 的parameterType的類型相同
4、Mapper接口方法的輸出參數(shù)類型和mapper.xml中定義的每個(gè)sql的resultType的類型相同
創(chuàng)建UserMapper.xml 映射文件
<?xml version="1.0"encoding="UTF-8"?><!DOCTYPE mapper
? ? ? ? PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
? ? ? ? "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--根據(jù)id查詢用戶-->select *? ? ? ? from user? ? ? ? where id = #{id}<!--根據(jù)用戶名查詢用戶-->select *? ? ? ? from user? ? ? ? where username like '%${value}%'
創(chuàng)建接口UserMapper
publicinterfaceUserMapper{publicUserqueryUserById(intid);publicListqueryUserByName(String userName);}
核心配置文件加載UserMapper.xml
<?xml version="1.0"encoding="UTF-8"?><!DOCTYPE mapper
? ? ? ? PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
? ? ? ? "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace命名空間 用于隔離sql --><!--根據(jù)id查詢用戶-->select *? ? ? ? from user? ? ? ? where id = #{id}<!--根據(jù)用戶名查詢用戶-->select *? ? ? ? from user? ? ? ? where username like '%${value}%'
測(cè)試代碼
/**
? ? * 根據(jù)id查詢用戶
? ? */@TestpublicvoidtestQueryUserById()throwsIOException{? ? ? ? SqlSessionFactoryBuilder builder =newSqlSessionFactoryBuilder();? ? ? ? SqlSessionFactory sessionFactory = builder.build(Resources.getResourceAsStream("SqlMapConfig.xml"));? ? ? ? SqlSession sqlSession = sessionFactory.openSession();? ? ? ? UserMapper userMapper = sqlSession.getMapper(UserMapper.class);? ? ? ? User user = userMapper.queryUserById(31);? ? ? ? System.out.println(user);? ? }/**? ? * 根據(jù)name查詢用戶列表? ? *@throwsIOException? ? */@TestpublicvoidtestQueryUserByname()throwsIOException{? ? ? ? SqlSessionFactoryBuilder builder =newSqlSessionFactoryBuilder();? ? ? ? SqlSessionFactory sqlSessionFactory = builder.build(Resources.getResourceAsStream("SqlMapConfig.xml"));? ? ? ? SqlSession sqlSession = sqlSessionFactory.openSession();? ? ? ? UserMapper userMapper = sqlSession.getMapper(UserMapper.class);? ? ? ? List userList = userMapper.queryUserByName("王");for(User user : userList) {? ? ? ? ? ? System.out.println(user);? ? ? ? }? ? }
SqlMapConfig.xml配置文件詳解
配置內(nèi)容
SqlMapConfig.xml中配置的內(nèi)容和順序如下
properties(屬性)
settings(全局配置參數(shù))
typeAliases(類型別名)
typeHandlers(類型處理器)
objectFactory(對(duì)象工廠)
plugins(插件)
environments(環(huán)境集合屬性對(duì)象)
environment(環(huán)境子屬性對(duì)象)
transactionManager(事務(wù)管理)
dataSource(數(shù)據(jù)源)
mappers(映射器)
properties(屬性)
db.properties 配置文件內(nèi)容
jdbc.driver=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8jdbc.username=rootjdbc.password=root
SqlMapConfig.xml
<!-- 是用resource屬性加載外部配置文件 --><!-- 在properties內(nèi)部用property定義屬性 --><!-- 如果外部配置文件有該屬性,則內(nèi)部定義屬性被外部屬性覆蓋 --><!-- 使用jdbc事務(wù)管理 --><!-- 數(shù)據(jù)庫(kù)連接池 --><!-- 加載映射文件 -->
tips
MyBatis將按照下面的順序來加載屬性
在properties元素體內(nèi)定義的屬性首先被讀取
然后會(huì)讀取properties元素中resource或url加載的屬性,它會(huì)覆蓋已讀取的同名屬性
typeAliases(類型別名)
mybatis支持別名
別名? ? 映射的類型_byte? ? byte _longlong_shortshort_intint_integerint_doubledouble_floatfloat_boolean? boolean string? ? String byte? ? ? BytelongLongshortShortintInteger integer? IntegerdoubleDoublefloatFloat boolean? Boolean date? ? ? Date decimal? BigDecimal bigdecimal BigDecimal map? ? ? Map
自定義別名
SqlMapConfig.xml
<?xml version="1.0"encoding="UTF-8"?><!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd"><!-- 是用resource屬性加載外部配置文件 --><!-- 在properties內(nèi)部用property定義屬性 --><!-- 單個(gè)別名定義 --><!-- 批量別名定義,掃描整個(gè)包下的類,別名為類名(大小寫不敏感) --><!-- 和spring整合后 environments配置將廢除 --><!-- 使用jdbc事務(wù)管理 --><!-- 數(shù)據(jù)庫(kù)連接池 --><!-- 加載映射文件 -->
在mapper.xml配置文件中,就可以使用設(shè)置的別名了
別名大小寫不敏感

圖片.png
mappers(映射器)
Mapper配置的幾種方法
使用相對(duì)于類路徑的資源(現(xiàn)在的使用方式)
<mapper class=""/> 使用mapper類接口路徑
此方法要求mapper接口名稱和mapper映射文件名稱相同,且放在同一個(gè)目錄中
<package name=""/> 注冊(cè)指定包下的所有mapper接口
此方法要求mapper接口名稱和mapper映射文件名稱相同,且放在同一個(gè)目錄中
Mybatis輸入映射和輸出映射
輸出簡(jiǎn)單類型
輸出POJO對(duì)象
開發(fā)中通過可以使用pojo傳遞查詢條件
查詢條件可能是綜合的查詢條件,不僅包括用戶的查詢條件還包括其它的查詢條件
包裝對(duì)象:Pojo類中的一個(gè)屬性是另外一個(gè)pojo
創(chuàng)建包裝類對(duì)象QueryVo
publicclassQueryVo{privateUser user;publicUsergetUser(){returnuser;? ? }publicvoidsetUser(User user){this.user = user;? ? }? ? }
創(chuàng)建映射文件Mapper.xml文件
其中輸入?yún)?shù)為包裝條件對(duì)象QueryVo 輸出對(duì)象為User泛型
<!--根據(jù)用戶名查詢數(shù)據(jù)-->SELECT * FROM user where username LIKE? '%${user.username}'
Mapper接口
在UserMapper接口中添加方法
/**? ? * 根據(jù)包裝條件查詢用戶列表數(shù)據(jù)? ? *? ? *@paramqueryVo? ? *@return*/publicList queryUserByQueryVo(QueryVo queryVo);
測(cè)試方法
@TestpublicvoidtestQueryVo()throws IOException{? ? ? ? SqlSessionFactoryBuilder builder =newSqlSessionFactoryBuilder();? ? ? ? SqlSessionFactory sqlSessionFactory = builder.build(Resources.getResourceAsStream("SqlMapConfig.xml"));? ? ? ? SqlSession sqlSession = sqlSessionFactory.openSession();? ? ? ? UserMapper userMapper = sqlSession.getMapper(UserMapper.class);? ? ? ? QueryVo queryVo =newQueryVo();? ? ? ? User user =newUser();? ? ? ? user.setUsername("五");? ? ? ? queryVo.setUser(user);? ? ? ? Listlist= userMapper.selectListByUserNameQueryVo(queryVo);for(User user1 :list) {? ? ? ? ? ? System.out.println(user1);? ? ? ? }? ? }
resultMap
在Mapper文件中,resultType可以指定將查詢結(jié)果映射為POJO,前提必須是POJO和sql查詢的列名一致方可映射成功。
如果sql查詢字段名和POJO的屬性名不一致,可以通過resultMap將字段名和屬性名作為一個(gè)指定的對(duì)應(yīng)關(guān)系。resultMap實(shí)質(zhì)上還需要將查詢結(jié)果映射到POJO對(duì)象中。
resultMap可以實(shí)現(xiàn)將查詢結(jié)果映射為復(fù)雜類型的POJO
創(chuàng)建一個(gè)POJO
packagecn.probuing.mybatisintro.pojo;importjava.io.Serializable;importjava.util.Date;publicclassOrdersimplementsSerializable{@OverridepublicStringtoString(){return"Orders [id="+ id +", userId="+ userId +", number="+ number +", createtime="+ createtime? ? ? ? ? ? ? ? +", note="+ note +"]";? ? }/**
? ? *
? ? */privatestaticfinallongserialVersionUID =1L;privateInteger id;privateInteger userId;privateString number;privateDate createtime;privateString note;//附加對(duì)象? 用戶對(duì)象privateUser user;publicUsergetUser(){returnuser;? ? }publicvoidsetUser(User user){this.user = user;? ? }publicIntegergetId(){returnid;? ? }publicvoidsetId(Integer id){this.id = id;? ? }publicIntegergetUserId(){returnuserId;? ? }publicvoidsetUserId(Integer userId){this.userId = userId;? ? }publicStringgetNumber(){returnnumber;? ? }publicvoidsetNumber(String number){this.number = number ==null?null: number.trim();? ? }publicDategetCreatetime(){returncreatetime;? ? }publicvoidsetCreatetime(Date createtime){this.createtime = createtime;? ? }publicStringgetNote(){returnnote;? ? }publicvoidsetNote(String note){this.note = note ==null?null: note.trim();? ? }? ? ? ? }
該pojo中 order中的userid與數(shù)據(jù)庫(kù)中表對(duì)應(yīng)的查詢列不一致
創(chuàng)建OrderMapper.xml映射文件
<!--
? ? ? ? id 對(duì)應(yīng)指定的resultMap標(biāo)識(shí)
? ? ? ? type 指定映射到哪一個(gè)pojo上
? ? --><!--id 定義主鍵 如果是多個(gè)字段 則定義多個(gè)id
? ? ? ? 標(biāo)簽中的property 表示 指定映射到pojo的哪個(gè)屬性
? ? ? ? 標(biāo)簽中的column 表示 指定映射到數(shù)據(jù)庫(kù)中的列名
? ? ? ? --><!--普通屬性使用result定義--><!--resultMap標(biāo)簽指定一個(gè)ResultMap的標(biāo)識(shí)-->SELECT id, user_id,? ? ? ? number,? ? ? ? createtime, note FROM `orders`
測(cè)試代碼
@TestpublicvoidtestResultMapQuery()throwsIOException{? ? ? ? SqlSessionFactoryBuilder builder =newSqlSessionFactoryBuilder();? ? ? ? SqlSessionFactory sqlSessionFactory = builder.build(Resources.getResourceAsStream("SqlMapConfig.xml"));? ? ? ? SqlSession sqlSession = sqlSessionFactory.openSession();? ? ? ? OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);? ? ? ? List orderList = orderMapper.queryOrderList();for(Orders orders : orderList) {? ? ? ? ? ? System.out.println(orders);? ? ? ? }? ? }
動(dòng)態(tài)SQL
通過Mybatis提供的各種標(biāo)簽方法實(shí)現(xiàn)動(dòng)態(tài)拼接SQL
if標(biāo)簽
編寫mapper.xml文件
<!--動(dòng)態(tài)標(biāo)簽--><!-- 考慮到sex 和username不一定同時(shí)存在 所以加入if標(biāo)簽進(jìn)行判斷 -->SELECT * FROM user? ? ? ? WHERE 1=1and sex = #{sex}and username LIKE "%${username}%"
上面這種判斷 還是存在where 1=1? 的情況,這種情況顯然還是很麻煩的 ,下面我們使用where標(biāo)簽對(duì)上面的判斷進(jìn)行改造
where標(biāo)簽
mapper.xml文件
<!-- 考慮到sex 和username不一定同時(shí)存在 所以加入if標(biāo)簽進(jìn)行判斷 -->SELECT * FROM userand sex = #{sex}and username LIKE "%${username}%"
where標(biāo)簽會(huì)自動(dòng)添加where條件,同時(shí)會(huì)處理sql語句中的第一個(gè)and關(guān)鍵字
sql片段
sql中可將重復(fù)的sql提取出來,使用時(shí)用Include引用,最終達(dá)到sql重用的目的
上面的sql提取出來后
<!-- 根據(jù)條件查詢用戶 --><!-- SELECT id, username, birthday, sex, address FROM `user` --><!-- 使用include標(biāo)簽加載sql片段;refid是sql片段id -->SELECTFROM `user`<!-- where標(biāo)簽可以自動(dòng)添加where關(guān)鍵字,同時(shí)處理sql語句中第一個(gè)and關(guān)鍵字 -->AND sex = #{sex}AND username LIKE? ? ? ? ? ? '%${username}%'<!-- 聲明sql片段 -->id, username, birthday, sex, address
foreach標(biāo)簽
向sql中傳遞數(shù)組或list mybatis使用foreach解析
改造QueryVo
在QueryVo中加入List代表多個(gè)id的集合
publicclassQueryVoimplementsSerializable{privateUser user;privateList ids;publicListgetIds(){returnids;? ? }publicvoidsetIds(List<Integer> ids){this.ids = ids;? ? }publicUsergetUser(){returnuser;? ? }publicvoidsetUser(User user){this.user = user;? ? }}
Mapper.xml文件
<!--根據(jù)ids查詢用戶-->SELECT * FROM user<!--
? ? ? ? ? ? foreach標(biāo)簽
? ? ? ? ? ? collection:要遍歷的集合,在這里是QueryVo中的ids屬性
? ? ? ? ? ? 直接傳遞數(shù)組時(shí)collection指定array
? ? ? ? ? ? ? 直接傳遞list時(shí)collection指定list
? ? ? ? ? ? item:遍歷的項(xiàng)目
? ? ? ? ? ? open:在前面添加的sql片段
? ? ? ? ? ? close:在結(jié)尾處添加的sql片段
? ? ? ? ? ? separator:指定遍歷的元素之間使用的分隔符
? ? ? ? ? ? -->#{item}
測(cè)試方法
@TestpublicvoidtestQueryByIds()throws IOException{? ? ? ? SqlSessionFactoryBuilder builder =newSqlSessionFactoryBuilder();? ? ? ? SqlSessionFactory sqlSessionFactory = builder.build(Resources.getResourceAsStream("SqlMapConfig.xml"));? ? ? ? SqlSession sqlSession = sqlSessionFactory.openSession();? ? ? ? UserMapper userMapper = sqlSession.getMapper(UserMapper.class);? ? ? ? QueryVo queryVo =newQueryVo();? ? ? ? Listlist=newArrayList<>();list.add(1);list.add(10);list.add(24);? ? ? ? queryVo.setIds(list);? ? ? ? List users = userMapper.queryUserByIds(queryVo);for(User user : users) {? ? ? ? ? ? System.out.println(user);? ? ? ? }? ? }
一對(duì)一查詢
使用resultMap
改造pojo類
在Order類中加入U(xiǎn)ser屬性,user屬性中用于存儲(chǔ)關(guān)聯(lián)查詢的用戶信息,對(duì)于訂單來說訂單關(guān)聯(lián)查詢用戶是一對(duì)一關(guān)系,所以這里使用單個(gè)User對(duì)象存儲(chǔ)關(guān)聯(lián)查詢的用戶信息
publicclassOrdersimplementsSerializable{@OverridepublicStringtoString(){return"Orders [id="+ id +", userId="+ userId +", number="+ number +", createtime="+ createtime? ? ? ? ? ? ? ? +", note="+ note +"]";? ? }/**
? ? *
? ? */privatestaticfinallongserialVersionUID =1L;privateInteger id;privateInteger userId;privateString number;privateDate createtime;privateString note;//附加對(duì)象? 用戶對(duì)象privateUser user;}
Mapper.xml
<!--映射數(shù)據(jù)庫(kù)主鍵 id--><!--一對(duì)一屬性映射--><!--一對(duì)一關(guān)聯(lián),查詢訂單,訂單內(nèi)部包含用戶屬性-->SELECT? ? ? ? ? ? o.id,? ? ? ? ? ? o.user_id,? ? ? ? ? ? o.number,? ? ? ? ? ? o.createtime,? ? ? ? ? ? o.note,? ? ? ? ? ? u.username,? ? ? ? ? ? u.address? ? ? ? FROM? ? ? ? ? ? `orders` o? ? ? ? ? ? LEFT JOIN `user` u ON o.user_id = u.id
上面的配置文件中 左關(guān)聯(lián)查詢時(shí) 對(duì)應(yīng)映射的類與數(shù)據(jù)庫(kù)查詢列不一致 所以使用resultMap映射
Orders中有User屬性,所以需要使用一對(duì)一映射User 使用resultMap的association標(biāo)簽映射User屬性,在association標(biāo)簽下 再分別映射user對(duì)象的屬性 其中指定的property是user對(duì)象的屬性名 column是對(duì)應(yīng)數(shù)據(jù)庫(kù)列的名稱
測(cè)試代碼
@TestpublicvoidtestQueryByResultMap()throwsIOException{? ? ? ? SqlSessionFactoryBuilder builder =newSqlSessionFactoryBuilder();? ? ? ? SqlSessionFactory sqlSessionFactory = builder.build(Resources.getResourceAsStream("SqlMapConfig.xml"));? ? ? ? SqlSession sqlSession = sqlSessionFactory.openSession();? ? ? ? OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);? ? ? ? List orders = orderMapper.queryOrderUserResultMap();for(Orders order : orders) {? ? ? ? ? ? System.out.println(order);? ? ? ? }? ? }
一對(duì)多查詢
修改POJO User類
publicclassUserimplementsSerializable{/**
? ? *
? ? */privatestaticfinallongserialVersionUID =1L;privateInteger id;privateString username;// 用戶姓名privateString sex;// 性別privateDate birthday;// 生日privateString address;// 地址privateList ordersList;publicListgetOrdersList(){returnordersList;? ? }publicvoidsetOrdersList(List<Orders> ordersList){this.ordersList = ordersList;? ? }}
Mapper.xml 映射文件
<!-- 一對(duì)多 -->SELECT? ? ? ? ? ? o.id,? ? ? ? ? ? o.user_id,? ? ? ? ? ? o.number,? ? ? ? ? ? o.createtime,? ? ? ? ? ? u.username? ? ? ? FROM user u? ? ? ? ? ? left join orders o? ? ? ? ? ? ? ? on o.user_id = u.id
Mybatis整合Spring
整合思路
SqlSessionFactory對(duì)象應(yīng)該放到spring容器中作為單例存在。
傳統(tǒng)dao的開發(fā)方式中,應(yīng)該從spring容器中獲得sqlsession對(duì)象。
Mapper代理形式中,應(yīng)該從spring容器中直接獲得mapper的代理對(duì)象。
數(shù)據(jù)庫(kù)的連接以及數(shù)據(jù)庫(kù)連接池事務(wù)管理都交給spring容器來完成。
整合需要的jar包
spring的jar包
Mybatis的jar包
Spring+mybatis的整合包。
Mysql的數(shù)據(jù)庫(kù)驅(qū)動(dòng)jar包。
數(shù)據(jù)庫(kù)連接池的jar包。
SqlMapConfig.xml
<?xml version="1.0"encoding="UTF-8"?><!DOCTYPE configuration
? ? ? ? PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
? ? ? ? "http://mybatis.org/dtd/mybatis-3-config.dtd"><!-- 設(shè)置別名 --><!-- 2. 指定掃描包,會(huì)把包內(nèi)所有的類都設(shè)置別名,別名的名稱就是類名,大小寫不敏感 -->
applicationContext.xml
<?xml version="1.0"encoding="UTF-8"?><!--加載配置文件--><!--配置數(shù)據(jù)庫(kù)連接池--><!--配置sqlsessionFactory--><!--配置mybatis核心配置文件--><!--配置數(shù)據(jù)源--><!--配置UserMapper--><!--配置mapper接口--><!--配置SqlSessionFactory工廠-->
db.properties
Mapper接口
publicinterfaceUserMapper{publicUserfindUserById(Integer id);}
UserMapper.xml映射文件
<?xml version="1.0"encoding="UTF-8"?><!DOCTYPE mapper
? ? ? ? PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
? ? ? ? "http://mybatis.org/dtd/mybatis-3-mapper.dtd">SELECT *? ? ? ? FROM user? ? ? ? where id = #{v}
測(cè)試代碼
@TestpublicvoidtestQueryById(){? ? ? ? ClassPathXmlApplicationContext applicationContext =newClassPathXmlApplicationContext("config/applicationContext.xml");? ? ? ? UserMapper userMapper = (UserMapper) applicationContext.getBean("userMapper");? ? ? ? User user = userMapper.findUserById(10);? ? ? ? System.out.println(user);? ? }
在存在多個(gè)mapper的時(shí)候 在spring中都需要制定具體的mapper 這種方式在我們開發(fā)中是很麻煩的,所以在這種時(shí)候我們引入掃描包形式配置mapper
掃描包形式配置mapper
在配置的時(shí)候需要制定 MapperScannerConfigurer 在property中指定掃描的基礎(chǔ)包
由于工廠已經(jīng)實(shí)例化 所以不需要指定工廠 MapperScannerConfigurer也能找到工廠
<!--包掃描形式配置mapper-->
Mybatis逆向工程
使用官方網(wǎng)站提供的Mapper自動(dòng)生成工具 mybatis-generator-core來生成pojo類和Mapper映射文件
導(dǎo)入逆向工程
need-to-insert-img
官方提供的逆向工程
修改配置文件
<?xml version="1.0"encoding="UTF-8"?><!DOCTYPE generatorConfiguration
? PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
? "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"><!-- 是否去除自動(dòng)生成的注釋 true:是 : false:否 --><!--數(shù)據(jù)庫(kù)連接的信息:驅(qū)動(dòng)類、連接地址、用戶名、密碼 --><!-- <jdbcConnection driverClass="oracle.jdbc.OracleDriver" connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg"
? ? ? ? ? ? userId="yycg" password="yycg"> </jdbcConnection> --><!-- 默認(rèn)false,把JDBC DECIMAL 和 NUMERIC 類型解析為 Integer,為 true時(shí)把JDBC DECIMAL
? ? ? ? ? ? 和 NUMERIC 類型解析為java.math.BigDecimal --><!-- targetProject:生成PO類的位置 --><!-- enableSubPackages:是否讓schema作為包的后綴 --><!-- 從數(shù)據(jù)庫(kù)返回的值被清理前后的空格 --><!-- targetProject:mapper映射文件生成的位置 --><!-- enableSubPackages:是否讓schema作為包的后綴 --><!-- targetPackage:mapper接口生成的位置 --><!-- enableSubPackages:是否讓schema作為包的后綴 --><!-- 指定數(shù)據(jù)庫(kù)表 -->
生成逆向工程代碼 執(zhí)行工程main主函數(shù)

圖片.png

圖片.png
代碼生成在工程目錄下

圖片.png
作者:So_ProbuING
鏈接:http://www.itdecent.cn/p/ab18a3a09fc2
來源:簡(jiǎn)書
簡(jiǎn)書著作權(quán)歸作者所有,任何形式的轉(zhuǎn)載都請(qǐng)聯(lián)系作者獲得授權(quán)并注明出處。