JAVAEE——Mybatis(Mybatis介紹配置使用以及與Spring整合)

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)并注明出處。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末竹椒,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子写穴,更是在濱河造成了極大的恐慌共苛,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仪吧,死亡現(xiàn)場離奇詭異庄新,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門择诈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來械蹋,“玉大人,你說我怎么就攤上這事羞芍』└辏” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵荷科,是天一觀的道長唯咬。 經(jīng)常有香客問我,道長畏浆,這世上最難降的妖魔是什么胆胰? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮刻获,結(jié)果婚禮上蜀涨,老公的妹妹穿的比我還像新娘。我一直安慰自己蝎毡,他們只是感情好厚柳,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著顶掉,像睡著了一般草娜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上痒筒,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天宰闰,我揣著相機與錄音,去河邊找鬼簿透。 笑死移袍,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的老充。 我是一名探鬼主播葡盗,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼啡浊!你這毒婦竟也來了觅够?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤巷嚣,失蹤者是張志新(化名)和其女友劉穎喘先,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體廷粒,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡窘拯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年红且,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涤姊。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡暇番,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出思喊,到底是詐尸還是另有隱情壁酬,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布搔涝,位于F島的核電站厨喂,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏庄呈。R本人自食惡果不足惜蜕煌,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望诬留。 院中可真熱鬧斜纪,春花似錦、人聲如沸文兑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绿贞。三九已至因块,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間籍铁,已是汗流浹背涡上。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拒名,地道東北人吩愧。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像增显,于是被迫代替她去往敵國和親雁佳。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容