Mybatis介紹
MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code流济,并且改名為MyBatis 。2013年11月遷移到Github泵肄。
MyBatis是一個優(yōu)秀的持久層框架煌寇,它對jdbc的操作數(shù)據(jù)庫的過程進行封裝焕蹄,使開發(fā)者只需要關(guān)注 SQL 本身,而不需要花費精力去處理例如注冊驅(qū)動阀溶、創(chuàng)建connection腻脏、創(chuàng)建statement鸦泳、手動設(shè)置參數(shù)、結(jié)果集檢索等jdbc繁雜的過程代碼永品。
Mybatis通過xml或注解的方式將要執(zhí)行的各種statement(statement辽故、preparedStatemnt、CallableStatement)配置起來腐碱,并通過java對象和statement中的sql進行映射生成最終執(zhí)行的sql語句誊垢,最后由mybatis框架執(zhí)行sql并將結(jié)果映射成java對象并返回。
JDBC存在的問題
1症见、? 數(shù)據(jù)庫連接創(chuàng)建喂走、釋放頻繁造成系統(tǒng)資源浪費,從而影響系統(tǒng)性能谋作。如果使用數(shù)據(jù)庫連接池可解決此問題芋肠。
2、? Sql語句在代碼中硬編碼遵蚜,造成代碼不易維護帖池,實際應(yīng)用中sql變化的可能較大,sql變動需要改變java代碼吭净。
3睡汹、? 使用preparedStatement向占有位符號傳參數(shù)存在硬編碼,因為sql語句的where條件不一定寂殉,可能多也可能少囚巴,修改sql還要修改代碼,系統(tǒng)不易維護友扰。
4彤叉、? 對結(jié)果集解析存在硬編碼(查詢列名),sql變化導致解析代碼變化村怪,系統(tǒng)不易維護秽浇,如果能將數(shù)據(jù)庫記錄封裝成pojo對象解析比較方便。
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使用手冊
創(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ù)庫連接池 -->
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}
標簽解釋
在pojo的映射文件xml中甚负,包含<select>柬焕、<insert>、<update>腊敲、<delete> 分別對應(yīng) 查詢击喂、添加、更新碰辅、刪除操作
其中 id 代表對應(yīng)標簽的識別id
parameterType代表占位符的類型
resultType 代表返回值類型
語句解釋
#{v}代表占位符 占位符標識為v
${value}代表字符串拼接 標識必須為value
select * from userwhereusername like'%xx%'
對應(yīng)的UserMap.xml配置文件中的SQL文件寫法
SELECT * FROM `user`whereusername like"%"#{v}"%"
測試代碼
@TestpublicvoidtestSelectOne()throwsIOException{//創(chuàng)建SqlSessionFactoryBuilder對象SqlSessionFactoryBuilder builder =newSqlSessionFactoryBuilder();//加載SqlMapConfig.xml配置文件 創(chuàng)建SqlSessionFactorySqlSessionFactory sessionFactory = builder.build(Resources.getResourceAsStream("SqlMapConfig.xml"));//創(chuàng)建SqlSession對象SqlSession sqlSession = sessionFactory.openSession();//SqlSession執(zhí)行對象查詢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}
測試代碼
@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}
測試代碼
@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ù)庫連接創(chuàng)建、釋放頻繁造成系統(tǒng)資源浪費從而影響系統(tǒng)性能没宾,如果使用數(shù)據(jù)庫連接池可解決此問題凌彬。
解決:在SqlMapConfig.xml中配置數(shù)據(jù)連接池沸柔,使用連接池管理數(shù)據(jù)庫鏈接。
2铲敛、Sql語句寫在代碼中造成代碼不易維護褐澎,實際應(yīng)用sql變化的可能較大,sql變動需要改變java代碼伐蒋。
解決:將Sql語句配置在XXXXmapper.xml文件中與java代碼分離工三。
3、向sql語句傳參數(shù)麻煩先鱼,因為sql語句的where條件不一定俭正,可能多也可能少,占位符需要和參數(shù)一一對應(yīng)焙畔。
解決:Mybatis自動將java對象映射至sql語句掸读,通過statement中的parameterType定義輸入?yún)?shù)的類型。
4宏多、對結(jié)果集解析麻煩儿惫,sql變化導致解析代碼變化,且解析前需要遍歷伸但,如果能將數(shù)據(jù)庫記錄封裝成pojo對象解析比較方便肾请。
解決:Mybatis自動將sql執(zhí)行結(jié)果映射至java對象,通過statement中的resultType定義輸出結(jié)果的類型
提出一個需求
MyBatis與HIbernate的不同
Mybatis和hibernate不同砌烁,它不完全是一個ORM框架筐喳,因為MyBatis需要程序員自己編寫Sql語句。mybatis可以通過XML或注解方式靈活配置要運行的sql語句函喉,并將java對象和sql語句映射生成最終執(zhí)行的sql,最后將sql執(zhí)行的結(jié)果再映射生成java對象荣月。
Mybatis學習門檻低管呵,簡單易學,程序員直接編寫原生態(tài)sql哺窄,可嚴格控制sql執(zhí)行性能捐下,靈活度高,非常適合對關(guān)系數(shù)據(jù)模型要求不高的軟件開發(fā)萌业,例如互聯(lián)網(wǎng)軟件坷襟、企業(yè)運營類軟件等,因為這類軟件需求變化頻繁生年,一但需求變化要求成果輸出迅速婴程。但是靈活的前提是mybatis無法做到數(shù)據(jù)庫無關(guān)性,如果需要實現(xiàn)支持多種數(shù)據(jù)庫的軟件則需要自定義多套sql映射文件抱婉,工作量大档叔。
Hibernate對象/關(guān)系映射能力強桌粉,數(shù)據(jù)庫無關(guān)性好,對于關(guān)系模型要求高的軟件(例如需求固定的定制化軟件)如果用hibernate開發(fā)可以節(jié)省很多代碼衙四,提高效率铃肯。但是Hibernate的學習門檻高,要精通門檻更高传蹈,而且怎么設(shè)計O/R映射押逼,在性能和對象模型之間如何權(quán)衡,以及怎樣用好Hibernate需要具有很強的經(jīng)驗和能力才行惦界。
總之宴胧,按照用戶的需求在有限的資源環(huán)境下只要能做出維護性、擴展性良好的軟件架構(gòu)都是好架構(gòu)表锻,所以框架只有適合才是最好恕齐。
Mapper動態(tài)代理方式開發(fā)
開發(fā)規(guī)范
Mapper接口開發(fā)方法只需要程序員編寫Mapper接口(相當于Dao接口),由Mybatis框架根據(jù)接口定義創(chuàng)建接口的動態(tài)代理對象瞬逊,代理對象的方法體同上邊Dao接口實現(xiàn)類方法显歧。
Mapper接口開發(fā)需要遵循以下規(guī)范:
1、? ? Mapper.xml文件中的namespace與mapper接口的類路徑相同确镊。
2士骤、Mapper接口方法名和Mapper.xml中定義的每個statement的id相同
3、Mapper接口方法的輸入?yún)?shù)類型和mapper.xml中定義的每個sql 的parameterType的類型相同
4蕾域、Mapper接口方法的輸出參數(shù)類型和mapper.xml中定義的每個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}%'
測試代碼
/**
? ? * 根據(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(對象工廠)
plugins(插件)
environments(環(huán)境集合屬性對象)
environment(環(huán)境子屬性對象)
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ù)庫連接池 --><!-- 加載映射文件 -->
tips
MyBatis將按照下面的順序來加載屬性
在properties元素體內(nèi)定義的屬性首先被讀取
然后會讀取properties元素中resource或url加載的屬性,它會覆蓋已讀取的同名屬性
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定義屬性 --><!-- 單個別名定義 --><!-- 批量別名定義旨巷,掃描整個包下的類巨缘,別名為類名(大小寫不敏感) --><!-- 和spring整合后 environments配置將廢除 --><!-- 使用jdbc事務(wù)管理 --><!-- 數(shù)據(jù)庫連接池 --><!-- 加載映射文件 -->
在mapper.xml配置文件中,就可以使用設(shè)置的別名了
別名大小寫不敏感
圖片.png
mappers(映射器)
Mapper配置的幾種方法
使用相對于類路徑的資源(現(xiàn)在的使用方式)
<mapper class=""/> 使用mapper類接口路徑
此方法要求mapper接口名稱和mapper映射文件名稱相同采呐,且放在同一個目錄中
<package name=""/> 注冊指定包下的所有mapper接口
此方法要求mapper接口名稱和mapper映射文件名稱相同若锁,且放在同一個目錄中
Mybatis輸入映射和輸出映射
輸出簡單類型
輸出POJO對象
開發(fā)中通過可以使用pojo傳遞查詢條件
查詢條件可能是綜合的查詢條件,不僅包括用戶的查詢條件還包括其它的查詢條件
包裝對象:Pojo類中的一個屬性是另外一個pojo
創(chuàng)建包裝類對象QueryVo
publicclassQueryVo{privateUser user;publicUsergetUser(){returnuser;? ? }publicvoidsetUser(User user){this.user = user;? ? }? ? }
創(chuàng)建映射文件Mapper.xml文件
其中輸入?yún)?shù)為包裝條件對象QueryVo 輸出對象為User泛型
<!--根據(jù)用戶名查詢數(shù)據(jù)-->SELECT * FROM user where username LIKE? '%${user.username}'
Mapper接口
在UserMapper接口中添加方法
/**? ? * 根據(jù)包裝條件查詢用戶列表數(shù)據(jù)? ? *? ? *@paramqueryVo? ? *@return*/publicList queryUserByQueryVo(QueryVo queryVo);
測試方法
@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將字段名和屬性名作為一個指定的對應(yīng)關(guān)系仰冠。resultMap實質(zhì)上還需要將查詢結(jié)果映射到POJO對象中。
resultMap可以實現(xiàn)將查詢結(jié)果映射為復(fù)雜類型的POJO
創(chuàng)建一個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;//附加對象? 用戶對象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ù)庫中表對應(yīng)的查詢列不一致
創(chuàng)建OrderMapper.xml映射文件
<!--
? ? ? ? id 對應(yīng)指定的resultMap標識
? ? ? ? type 指定映射到哪一個pojo上
? ? --><!--id 定義主鍵 如果是多個字段 則定義多個id
? ? ? ? 標簽中的property 表示 指定映射到pojo的哪個屬性
? ? ? ? 標簽中的column 表示 指定映射到數(shù)據(jù)庫中的列名
? ? ? ? --><!--普通屬性使用result定義--><!--resultMap標簽指定一個ResultMap的標識-->SELECT id, user_id,? ? ? ? number,? ? ? ? createtime, note FROM `orders`
測試代碼
@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);? ? ? ? }? ? }
動態(tài)SQL
通過Mybatis提供的各種標簽方法實現(xiàn)動態(tài)拼接SQL
if標簽
編寫mapper.xml文件
<!--動態(tài)標簽--><!-- 考慮到sex 和username不一定同時存在 所以加入if標簽進行判斷 -->SELECT * FROM user? ? ? ? WHERE 1=1and sex = #{sex}and username LIKE "%${username}%"
上面這種判斷 還是存在where 1=1? 的情況蝶糯,這種情況顯然還是很麻煩的 洋只,下面我們使用where標簽對上面的判斷進行改造
where標簽
mapper.xml文件
<!-- 考慮到sex 和username不一定同時存在 所以加入if標簽進行判斷 -->SELECT * FROM userand sex = #{sex}and username LIKE "%${username}%"
where標簽會自動添加where條件,同時會處理sql語句中的第一個and關(guān)鍵字
sql片段
sql中可將重復(fù)的sql提取出來,使用時用Include引用木张,最終達到sql重用的目的
上面的sql提取出來后
<!-- 根據(jù)條件查詢用戶 --><!-- SELECT id, username, birthday, sex, address FROM `user` --><!-- 使用include標簽加載sql片段众辨;refid是sql片段id -->SELECTFROM `user`<!-- where標簽可以自動添加where關(guān)鍵字,同時處理sql語句中第一個and關(guān)鍵字 -->AND sex = #{sex}AND username LIKE? ? ? ? ? ? '%${username}%'<!-- 聲明sql片段 -->id, username, birthday, sex, address
foreach標簽
向sql中傳遞數(shù)組或list mybatis使用foreach解析
改造QueryVo
在QueryVo中加入List代表多個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標簽
? ? ? ? ? ? collection:要遍歷的集合舷礼,在這里是QueryVo中的ids屬性
? ? ? ? ? ? 直接傳遞數(shù)組時collection指定array
? ? ? ? ? ? ? 直接傳遞list時collection指定list
? ? ? ? ? ? item:遍歷的項目
? ? ? ? ? ? open:在前面添加的sql片段
? ? ? ? ? ? close:在結(jié)尾處添加的sql片段
? ? ? ? ? ? separator:指定遍歷的元素之間使用的分隔符
? ? ? ? ? ? -->#{item}
測試方法
@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);? ? ? ? }? ? }
一對一查詢
使用resultMap
改造pojo類
在Order類中加入User屬性鹃彻,user屬性中用于存儲關(guān)聯(lián)查詢的用戶信息,對于訂單來說訂單關(guān)聯(lián)查詢用戶是一對一關(guān)系妻献,所以這里使用單個User對象存儲關(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;//附加對象? 用戶對象privateUser user;}
Mapper.xml
<!--映射數(shù)據(jù)庫主鍵 id--><!--一對一屬性映射--><!--一對一關(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)查詢時 對應(yīng)映射的類與數(shù)據(jù)庫查詢列不一致 所以使用resultMap映射
Orders中有User屬性育拨,所以需要使用一對一映射User 使用resultMap的association標簽映射User屬性谨履,在association標簽下 再分別映射user對象的屬性 其中指定的property是user對象的屬性名 column是對應(yīng)數(shù)據(jù)庫列的名稱
測試代碼
@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);? ? ? ? }? ? }
一對多查詢
修改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 映射文件
<!-- 一對多 -->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對象應(yīng)該放到spring容器中作為單例存在。
傳統(tǒng)dao的開發(fā)方式中熬丧,應(yīng)該從spring容器中獲得sqlsession對象笋粟。
Mapper代理形式中,應(yīng)該從spring容器中直接獲得mapper的代理對象析蝴。
數(shù)據(jù)庫的連接以及數(shù)據(jù)庫連接池事務(wù)管理都交給spring容器來完成害捕。
整合需要的jar包
spring的jar包
Mybatis的jar包
Spring+mybatis的整合包。
Mysql的數(shù)據(jù)庫驅(qū)動jar包闷畸。
數(shù)據(jù)庫連接池的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. 指定掃描包,會把包內(nèi)所有的類都設(shè)置別名佑菩,別名的名稱就是類名盾沫,大小寫不敏感 -->
applicationContext.xml
<?xml version="1.0"encoding="UTF-8"?><!--加載配置文件--><!--配置數(shù)據(jù)庫連接池--><!--配置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}
測試代碼
@TestpublicvoidtestQueryById(){? ? ? ? ClassPathXmlApplicationContext applicationContext =newClassPathXmlApplicationContext("config/applicationContext.xml");? ? ? ? UserMapper userMapper = (UserMapper) applicationContext.getBean("userMapper");? ? ? ? User user = userMapper.findUserById(10);? ? ? ? System.out.println(user);? ? }
在存在多個mapper的時候 在spring中都需要制定具體的mapper 這種方式在我們開發(fā)中是很麻煩的,所以在這種時候我們引入掃描包形式配置mapper
掃描包形式配置mapper
在配置的時候需要制定 MapperScannerConfigurer 在property中指定掃描的基礎(chǔ)包
由于工廠已經(jīng)實例化 所以不需要指定工廠 MapperScannerConfigurer也能找到工廠
<!--包掃描形式配置mapper-->
Mybatis逆向工程
使用官方網(wǎng)站提供的Mapper自動生成工具 mybatis-generator-core來生成pojo類和Mapper映射文件
導入逆向工程
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"><!-- 是否去除自動生成的注釋 true:是 : false:否 --><!--數(shù)據(jù)庫連接的信息:驅(qū)動類殿漠、連接地址赴精、用戶名、密碼 --><!-- <jdbcConnection driverClass="oracle.jdbc.OracleDriver" connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg"
? ? ? ? ? ? userId="yycg" password="yycg"> </jdbcConnection> --><!-- 默認false,把JDBC DECIMAL 和 NUMERIC 類型解析為 Integer卫病,為 true時把JDBC DECIMAL
? ? ? ? ? ? 和 NUMERIC 類型解析為java.math.BigDecimal --><!-- targetProject:生成PO類的位置 --><!-- enableSubPackages:是否讓schema作為包的后綴 --><!-- 從數(shù)據(jù)庫返回的值被清理前后的空格 --><!-- targetProject:mapper映射文件生成的位置 --><!-- enableSubPackages:是否讓schema作為包的后綴 --><!-- targetPackage:mapper接口生成的位置 --><!-- enableSubPackages:是否讓schema作為包的后綴 --><!-- 指定數(shù)據(jù)庫表 -->
生成逆向工程代碼 執(zhí)行工程main主函數(shù)
圖片.png
圖片.png
代碼生成在工程目錄下
圖片.png
作者:So_ProbuING
鏈接:http://www.reibang.com/p/ab18a3a09fc2
來源:簡書
簡書著作權(quán)歸作者所有,任何形式的轉(zhuǎn)載都請聯(lián)系作者獲得授權(quán)并注明出處。