非本人總結(jié)的筆記,抄點(diǎn)筆記復(fù)習(xí)復(fù)習(xí)岁疼。感謝傳智博客及黑馬程序猿成長(zhǎng)
關(guān)聯(lián)查詢
數(shù)據(jù)中的表結(jié)構(gòu)
數(shù)據(jù)庫(kù)的分析方法
第一步:確定單表存儲(chǔ)的是什么內(nèi)容。
第二步:確定每個(gè)表中的關(guān)鍵字段缆娃。不能為null的字段捷绒。
第三步:確定表和表之間數(shù)據(jù)庫(kù)層面的關(guān)系。外鍵關(guān)系贯要。
第四步:從業(yè)務(wù)層面分析表和表之間的關(guān)系暖侨。
訂單--商品模型分析
第一步:
User:客戶表。存儲(chǔ)的是購(gòu)買商品的用戶信息崇渗。
Orders:訂單表字逗。存儲(chǔ)的就是用戶生成的訂單。
OrderDetail:訂單明細(xì)表宅广。保存的是每個(gè)訂單的明細(xì)葫掉。
Items:商品表。保存的是商品信息跟狱。
第二步:
User:id:主鍵俭厚。Username:用戶名
Orders:id主鍵。user_id:用戶id(外鍵)
Orderdetail:id主鍵驶臊。orders_id:訂單的id(外鍵)挪挤。items_id:商品id(外鍵)
Items:id主鍵。Name商品名稱关翎。Price商品價(jià)格扛门。Createtime生成日期。
第三步:
第四步:從業(yè)務(wù)層面分析表和表之間的關(guān)系
用戶→訂單:一個(gè)用戶可以下多個(gè)訂單笤休。一對(duì)多
訂單→用戶:一個(gè)訂單只屬于一個(gè)用戶尖飞。一對(duì)一
訂單→訂單明細(xì):一個(gè)訂單包含多個(gè)明細(xì)。一對(duì)多
訂單明細(xì)→訂單:一個(gè)訂單明細(xì)只屬于一個(gè)訂單。
訂單明細(xì)→商品:一個(gè)訂單明細(xì)對(duì)應(yīng)一個(gè)商品政基。一對(duì)一
商品→訂單明細(xì):一個(gè)商品可以被多個(gè)明細(xì)對(duì)應(yīng)贞铣。一對(duì)多
用戶→商品:一對(duì)多
商品→用戶:一對(duì)多
一對(duì)一查詢
Sql語(yǔ)句
SELECT o.id, user_id, number, createtime, note, username, birthday, sex, address FROM orderso JOIN USER u ON o.user_id = u.id
使用resultType實(shí)現(xiàn)
定義一個(gè)POJO
和sql語(yǔ)句的結(jié)果集對(duì)應(yīng)
public class OrderUser extends Orders {
//用戶相關(guān)的字段
private String username;
private String sex;
private Date birthday;
private String address;
//set和get方法省略
}
Mapper文件
<?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">
<mapper namespace="cn.itcast.mapper.OrderMapper">
<select id="getOrderWithUser" resultType="orderuser">
SELECT
o.id,
user_id,
number,
createtime,
note,
username,
birthday,
sex,
address
FROM
orders o
JOIN USER u ON o.user_id = u.id
</select>
</mapper>
接口定義
public interface OrderMapper{
List<OrderUser> getOrderWithUser();
}
測(cè)試方法
@Test
public void testGetOrderWithUser() {
SqlSession sqlSession = sessionFactory.openSession();
OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
List<OrderUser> orderUserList = orderMapper.getOrderWithUser();
System.out.println(orderUserList);
sqlSession.close();
}
使用ResultMap實(shí)現(xiàn)
定義一個(gè)POJO
在orders POJO中添加一個(gè)User屬性,保存用戶信息
public class Orders {
private Integer id;
private Integer userId;
private String number;
private Date createtime;
private User user;
//省略get和set方法
}
Mapper文件
<!-- 使用resultMap實(shí)現(xiàn)一對(duì)一映射 -->
<resultMap type="orders" id="orderUserResultMap">
<!-- order表的主鍵 -->
<id column="id" property="id"/>
<!-- 普通列 -->
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!-- 用戶表的映射關(guān)系 -->
<!-- 使用association做一對(duì)一關(guān)聯(lián)映射 -->
<!-- property屬性就是pojo中要進(jìn)行一對(duì)一關(guān)聯(lián)的屬性
javaType:指定一對(duì)一關(guān)聯(lián)屬性的類型沮明,可以使用別名辕坝。
-->
<association property="user" javaType="cn.itcast.pojo.User">
<!-- user表的主鍵 -->
<id column="user_id" property="id"/>
<!-- 普通列 -->
<result column="username" property="username"/>
<result column="birthday" property="birthday"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</association>
</resultMap>
<select id="getOrderWithUserResultMap" resultMap="orderUserResultMap">
SELECT
o.id,
user_id,
number,
createtime,
note,
username,
birthday,
sex,
address
FROM
orders o
JOIN USER u ON o.user_id = u.id
</select>
接口定義
public interface OrderMapper{
List<Orders> getOrderWithUserResultMap();
}
測(cè)試方法
@Test
public void testGetOrderWithUserResultMap() throws Exception {
SqlSession sqlSession = sessionFactory.openSession();
OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
List<Orders> list = orderMapper.getOrderWithUserResultMap();
System.out.println(list);
sqlSession.close();
}
小結(jié)
一對(duì)一映射可以有兩種方法,一種是使用resultType荐健,根據(jù)sql語(yǔ)句返回的結(jié)果集創(chuàng)建一pojo類來接收結(jié)果集酱畅。
使用resultMap實(shí)現(xiàn),需要配置一個(gè)resultmap使用association 來配置映射關(guān)系江场。
實(shí)際開發(fā)中resultType用的多纺酸。
一對(duì)多查詢
訂單到訂單明細(xì)是一對(duì)多的關(guān)系。
Sql語(yǔ)句
SELECT o.id, user_id, number, createtime, note, username, birthday, sex, address, od.iddetail_id, od.items_id, od.items_num FROM orderso JOIN USER u ON o.user_id = u.id JOIN orderdetail od ON o.id = od.orders_id
定義一個(gè)POJO
在orders中添加List<OrderDetail>屬性址否,保存訂單明細(xì)列表
public class Orders{
private Integer id;
private Integer userId;
private String number;
private Date createtime;
private String note;
private List<OrderDetail> detailList;
//省略set和get方法
}
Mapper文件
<!-- 一對(duì)多管理映射使用ResultMap實(shí)現(xiàn) -->
<!-- resultMap定義 -->
<!-- resultMap之間可以使用extends繼承 -->
<resultMap type="orders" id="orderDetailResultMap" extends="orderUserResultMap">
<!-- 配置一對(duì)多映射關(guān)系 -->
<!-- property一對(duì)多關(guān)系映射的屬性 -->
<!-- ofType:指定列表中元素的數(shù)據(jù)類型 -->
<collection property="detailList" ofType="cn.itcast.pojo.Orderdetail">
<!-- 訂單明細(xì)表的id -->
<id column="detail_id" property="id"/>
<!-- 普通列 -->
<result column="items_id" property="itemsId"/>
<result column="items_num" property="itemsNum"/>
<result column="id" property="ordersId"/>
</collection>
</resultMap>
<select id="getOrderWithDetail" resultMap="orderDetailResultMap">
SELECT
o.id,
user_id,
number,
createtime,
note,
username,
birthday,
sex,
address,
od.id detail_id,
od.items_id,
od.items_num
FROM
orders o
JOIN USER u ON o.user_id = u.id
JOIN orderdetail od ON o.id = od.orders_id
</select>
接口定義
public interface OrderMapper{
List<Orders> getOrderWithDetail();
}
測(cè)試方法
@Test
public void testGetOrderWithDetail() throws Exception {
SqlSession sqlSession = sessionFactory.openSession();
OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
List<Orders> list = orderMapper.getOrderWithDetail(); System.out.println(list);
sqlSession.close();
}
一對(duì)多復(fù)雜
需求
查詢訂單關(guān)聯(lián)訂單明細(xì)餐蔬,商品明細(xì)要關(guān)聯(lián)商品信息。
Sql語(yǔ)句
SELECT o.id, o.user_id, o.number, o.createtime, o.note, u.username, u.birthday, u.sex, u.address, od.iddetail_id, od.items_id, od.items_num, i.name
, i.pic, i.price, i.createtimectime FROM orderso JOIN USER u ON o.user_id = u.id JOIN orderdetail od ON o.id = od.orders_id JOINitems i ON od.items_id = i.id
定義一個(gè)POJO
在Orderdetail中添加一個(gè)Items屬性佑附,保存商品信息樊诺。
public class Orderdetail{
private Integer id;
private Integer ordersId;
private Integer itemsId;
private Integer itemNum;
private Items items;
//省略set和get方法
}
Mapper文件
<!-- 一對(duì)多復(fù)雜 -->
<!-- 定義一個(gè)ResultMap -->
<resultMap type="Orders" id="orderWithDetailWithItemsResultMap" extends="orderUserResultMap">
<!-- 配置一對(duì)多映射關(guān)系 -->
<!-- property一對(duì)多關(guān)系映射的屬性 -->
<!-- ofType:指定列表中元素的數(shù)據(jù)類型 -->
<collection property="detailList" ofType="cn.itcast.pojo.Orderdetail">
<!-- 訂單明細(xì)表的id -->
<id column="detail_id" property="id"/>
<!-- 普通列 -->
<result column="items_id" property="itemsId"/>
<result column="items_num" property="itemsNum"/>
<result column="id" property="ordersId"/>
<!-- 訂單明細(xì)一對(duì)一關(guān)聯(lián)商品信息 -->
<association property="items" javaType="cn.itcast.pojo.Items">
<!-- 商品表的主鍵 -->
<id column="items_id" property="id"/>
<!-- 普通列 -->
<result column="name" property="name"/>
<result column="pic" property="pic"/>
<result column="price" property="price"/>
<result column="ctime" property="createtime"/>
</association>
</collection>
</resultMap>
<select id="getOrderWithDetailWithItems" resultMap="orderWithDetailWithItemsResultMap">
SELECT
o.id,
o.user_id,
o.number,
o.createtime,
o.note,
u.username,
u.birthday,
u.sex,
u.address,
od.id detail_id,
od.items_id,
od.items_num,
i.`name`,
i.pic,
i.price,
i.createtime ctime
FROM
orders o
JOIN USER u ON o.user_id = u.id
JOIN orderdetail od ON o.id = od.orders_id
JOIN items i ON od.items_id = i.id
</select>
接口方法定義
public interface OrderMapper{
List<Orders> getOrderWithDetailWithItems();
}
測(cè)試方法
@Test
public void testGetOrderWithDetailWithItems() throws Exception {
SqlSession sqlSession = sessionFactory.openSession();
OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
List<Orders> list = orderMapper.getOrderWithDetailWithItems();
System.out.println(list);
sqlSession.close();
}
多對(duì)多關(guān)聯(lián)映射
如下需求:
查詢用戶購(gòu)買的商品信息,用戶和商品的關(guān)系是多對(duì)多關(guān)系音同。
需求1:
查詢顯示字段:用戶賬號(hào)词爬、用戶名稱、用戶性別权均、商品名稱顿膨、商品價(jià)格(最常見)
企業(yè)開發(fā)中常見明細(xì)列表,用戶購(gòu)買商品明細(xì)列表螺句,
使用resultType將上邊查詢列映射到pojo輸出虽惭。
需求2:
查詢顯示字段:用戶賬號(hào)、用戶名稱蛇尚、購(gòu)買商品數(shù)量芽唇、商品明細(xì)(鼠標(biāo)移上顯示明細(xì))
使用resultMap將用戶購(gòu)買的商品明細(xì)列表映射到user對(duì)象中。
其實(shí)是一個(gè)一對(duì)多的映射關(guān)系
延遲加載
需要查詢關(guān)聯(lián)信息時(shí)取劫,使用mybatis延遲加載特性可有效的減少數(shù)據(jù)庫(kù)壓力匆笤,首次查詢只查詢主要信息,關(guān)聯(lián)信息等用戶獲取時(shí)再加載谱邪。
在mybatis中默認(rèn)沒有開啟延遲加載
配置方法
需要配置SqlMapConfig.xml炮捧,中有一個(gè)setting節(jié)點(diǎn),需要在setting節(jié)點(diǎn)中配置開啟延遲加載惦银。
<!-- 全局參數(shù)配置 -->
<settings>
<!-- 配置開啟延遲加載 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 設(shè)置按需加載 -->
<setting name="aggressiveLazyLoading" value="false" />
</settings>
Mapper文件
<!-- 懶加載 -->
<!-- 配置一個(gè)resultMap咆课,懶加載user -->
<resultMap type="orders" id="ordersLazyLoading">
<!-- order表的主鍵 -->
<id column="id" property="id"/>
<!-- 普通列 -->
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!-- 延遲加載用戶信息 -->
<!-- select指定一個(gè)statementID查詢用戶末誓,延遲加載的查詢 -->
<!-- column指定查詢條件的列 -->
<association property="user" select="getUserById" column="user_id">
<!-- user表的主鍵 -->
<id column="user_id" property="id"/>
<!-- 普通列 -->
<result column="username" property="username"/>
<result column="birthday" property="birthday"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</association>
</resultMap>
<select id="getOrderLazyLoading" resultMap="ordersLazyLoading">
select * from orders
</select>
<select id="getUserById" parameterType="int" resultType="cn.itcast.pojo.User">
SELECT * from user where id = #{id}
</select>
接口定義
public interface OrderMapper{
List<Orders> getOrderLazyLoading();
}
測(cè)試方法
@Test
public void testgetOrderLazyLoading() throws Exception {
SqlSession sqlSession = sessionFactory.openSession();
OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
List<Orders> list = orderMapper.getOrderLazyLoading();
Orders orders = list.get(0);
System.out.println(orders.getId());
//懶加載
System.out.println(orders.getUser().getUsername());
System.out.println(list);
sqlSession.close();
}
Mybatis的緩存
一級(jí)緩存、二級(jí)緩存书蚪。
Mybatis緩存介紹
如下圖喇澡,是mybatis一級(jí)緩存和二級(jí)緩存的區(qū)別圖解:
Mybatis一級(jí)緩存的作用域是同一個(gè)SqlSession,在同一個(gè)sqlSession中兩次執(zhí)行相同的sql語(yǔ)句殊校,第一次執(zhí)行完畢會(huì)將數(shù)據(jù)庫(kù)中查詢的數(shù)據(jù)寫到緩存(內(nèi)存)晴玖,第二次會(huì)從緩存中獲取數(shù)據(jù)將不再?gòu)臄?shù)據(jù)庫(kù)查詢,從而提高查詢效率为流。當(dāng)一個(gè)sqlSession結(jié)束后該sqlSession中的一級(jí)緩存也就不存在了呕屎。Mybatis默認(rèn)開啟一級(jí)緩存。
Mybatis二級(jí)緩存是多個(gè)SqlSession共享的敬察,其作用域是mapper的同一個(gè)namespace秀睛,不同的sqlSession兩次執(zhí)行相同namespace下的sql語(yǔ)句且向sql中傳遞參數(shù)也相同即最終執(zhí)行相同的sql語(yǔ)句,第一次執(zhí)行完畢會(huì)將數(shù)據(jù)庫(kù)中查詢的數(shù)據(jù)寫到緩存(內(nèi)存)莲祸,第二次會(huì)從緩存中獲取數(shù)據(jù)將不再?gòu)臄?shù)據(jù)庫(kù)查詢琅催,從而提高查詢效率。Mybatis默認(rèn)沒有開啟二級(jí)緩存需要在setting全局參數(shù)中配置開啟二級(jí)緩存虫给。
一級(jí)緩存
原理
下圖是根據(jù)id查詢用戶的一級(jí)緩存圖解:
一級(jí)緩存區(qū)域是根據(jù)SqlSession為單位劃分的。
每次查詢會(huì)先從緩存區(qū)域找侠碧,如果找不到從數(shù)據(jù)庫(kù)查詢抹估,查詢到數(shù)據(jù)將數(shù)據(jù)寫入緩存。Mybatis內(nèi)部存儲(chǔ)緩存使用一個(gè)HashMap弄兜,key為hashCode+sqlId+Sql語(yǔ)句药蜻。value為從查詢出來映射生成的java對(duì)象。
sqlSession執(zhí)行insert替饿、update语泽、delete等操作commit提交后會(huì)清空緩存區(qū)域。
測(cè)試一級(jí)緩存
@Test
public void testlevel1cache() throws Exception {
SqlSession sqlSession = sessionFactory.openSession();
OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
//第一次查詢视卢,從數(shù)據(jù)庫(kù)中查詢數(shù)據(jù)
List<OrderUser> list = orderMapper.getOrderWithUser();
System.out.println(list);
//更新orders表踱卵,會(huì)清空一級(jí)緩存
OrderUser orderUser = list.get(0);
orderUser.setNote("修改數(shù)據(jù)庫(kù)清空一級(jí)緩存");
orderMapper.updateOrders(orderUser);
sqlSession.commit();
//第二次查詢從一級(jí)緩存中命中
List<OrderUser> list2 = orderMapper.getOrderWithUser();
System.out.println(list2);
//關(guān)閉sqlsession
sqlSession.close();
}
二級(jí)緩存
原理
下圖是多個(gè)sqlSession請(qǐng)求UserMapper的二級(jí)緩存圖解。
二級(jí)緩存區(qū)域是根據(jù)mapper的namespace劃分的据过,相同namespace的mapper查詢數(shù)據(jù)放在同一個(gè)區(qū)域惋砂,如果使用mapper代理方法每個(gè)mapper的namespace都不同,此時(shí)可以理解為二級(jí)緩存區(qū)域是根據(jù)mapper劃分绳锅。
每次查詢會(huì)先從緩存區(qū)域找西饵,如果找不到從數(shù)據(jù)庫(kù)查詢,查詢到數(shù)據(jù)將數(shù)據(jù)寫入緩存鳞芙。
Mybatis內(nèi)部存儲(chǔ)緩存使用一個(gè)HashMap眷柔,key為hashCode+sqlId+Sql語(yǔ)句期虾。value為從查詢出來映射生成的java對(duì)象
sqlSession執(zhí)行insert、update驯嘱、delete等操作commit提交后會(huì)清空緩存區(qū)域镶苞。
開啟二級(jí)緩存
第一步:在核心配置文件SqlMapConfig.xml中加入
<setting name="cacheEnabled"value="true"/>
描述 | 允許值 | 默認(rèn)值 | |
---|---|---|---|
cacheEnabled | 對(duì)在此配置文件下的所有cache 進(jìn)行全局性開/關(guān)設(shè)置。 | true | false | true |
第二步:在需要開啟二級(jí)緩存的mapper文件中加入<cache/>節(jié)點(diǎn)宙拉。
第三步:在開啟二級(jí)緩存的mapper中使用的pojo類需要實(shí)現(xiàn)序列化接口宾尚。
測(cè)試二級(jí)緩存
@Test
public void testLevel2Cache() throws Exception {
//第一次查詢從數(shù)據(jù)庫(kù)中查詢
SqlSession sqlSession = sessionFactory.openSession();
OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
List<OrderUser> list = orderMapper.getOrderWithUser();
System.out.println(list);
sqlSession.close();
//更新數(shù)據(jù)庫(kù)清空二級(jí)緩存
SqlSession sqlSession1 = sessionFactory.openSession();
OrderMapper orderMapper1 = sqlSession1.getMapper(OrderMapper.class);
OrderUser orderUser = list.get(0);
orderUser.setNote("測(cè)試二級(jí)緩存");
orderMapper1.updateOrders(orderUser);
sqlSession1.commit();
sqlSession1.close();
//第二次查詢從二級(jí)緩存中取數(shù)據(jù)
SqlSession sqlSession2 = sessionFactory.openSession();
OrderMapper orderMapper2 = sqlSession2.getMapper(OrderMapper.class);
List<OrderUser> list2 = orderMapper2.getOrderWithUser();
System.out.println(list2);
sqlSession2.close();
}
設(shè)置某方法不使用二級(jí)緩存
更新數(shù)據(jù)庫(kù)不刷新二級(jí)緩存
Mybatis集成第三方緩存工具ehcache
Ehcache是一個(gè)分布式的緩存框架
整合環(huán)境
需要用到ehcache的jar包mybatis+ehcache的整合包。
整合步驟
第一步:把ehcache的jar包和整合包放到工程中谢澈。
第二步:創(chuàng)建一個(gè)ehcache的配置文件煌贴。配置了ehcache的相關(guān)設(shè)置。
第三步:需要在mapper文件中指定使用ehcache做緩存锥忿。
整合的原理
Mybatis-ehcache整合包中實(shí)現(xiàn)了mybatis的Cache接口牛郑。只要實(shí)現(xiàn)這個(gè)接口就可以整合。
創(chuàng)建ehcache的配置文件
classpath下名稱為:ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<!-- 數(shù)據(jù)緩存要存放的磁盤地址 -->
<diskStore path="d:\temp\ehcache" />
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
制定使用ehcache做緩存
應(yīng)用場(chǎng)景
使用場(chǎng)景:對(duì)于訪問響應(yīng)速度要求高敬鬓,但是時(shí)效性不高的查詢淹朋,可以采用二級(jí)緩存技術(shù)。
注意:在使用二級(jí)緩存的時(shí)候钉答,要設(shè)置一下刷新間隔(cache標(biāo)簽中有一個(gè)flashInterval屬性)來定時(shí)刷新二級(jí)緩存础芍,這個(gè)刷新間隔根據(jù)具體需求來設(shè)置,比如設(shè)置30分鐘数尿、60分鐘等仑性,單位為毫秒。
局限性
Mybatis的二級(jí)緩存對(duì)細(xì)粒度的數(shù)據(jù)右蹦,緩存實(shí)現(xiàn)不好诊杆。
場(chǎng)景:對(duì)商品信息進(jìn)行緩存招狸,由于商品信息查詢?cè)L問量大官套,但是要求用戶每次查詢都是最新的商品信息咒钟,此時(shí)如果使用二級(jí)緩存偶惠,就無法實(shí)現(xiàn)當(dāng)一個(gè)商品發(fā)送變化只刷新該商品的緩存信息而不刷新其他商品緩存信息葛作,因?yàn)槎?jí)緩存是Mapper級(jí)別的队塘,當(dāng)一個(gè)商品的信息發(fā)送更新穴张,所有的商品信息緩存數(shù)據(jù)都會(huì)被清空撬统。
解決此類問題晃洒,需要在業(yè)務(wù)層根據(jù)需要對(duì)數(shù)據(jù)有針對(duì)性的緩存
比如可以對(duì)經(jīng)常變化的數(shù)據(jù)操作單獨(dú)放到另一個(gè)namespace的Mapper中
Mybatis整合Spring
整合思路
Dao層:
1慨灭、數(shù)據(jù)庫(kù)連接池配置在spring中。
2球及、sqlsessionFactory對(duì)象放到spring容器中氧骤,以單例形式存在。
3吃引、把mapper的代理對(duì)象都放到spring容器筹陵。如果使用傳統(tǒng)的dao開發(fā)方式刽锤,sqlsession應(yīng)用從spring容器中獲得。
Service層:
1朦佩、所有的service實(shí)現(xiàn)類對(duì)象都放到spring容器中并思。
2、事務(wù)配置也應(yīng)該放到service層语稠,交給spring管理宋彼。
整合需要的環(huán)境
1、Mybatis的jar包
2仙畦、Mybatis依賴的jar包
3输涕、Spring的jar包
4、Mybatis和spring的整合包慨畸。
5莱坎、Mysql的數(shù)據(jù)庫(kù)驅(qū)動(dòng)
6、數(shù)據(jù)庫(kù)連接池的jar包寸士。
工程搭建步驟
第一步:創(chuàng)建一個(gè)java工程
第二步:導(dǎo)入jar包(上面提到的jar包)
第三步:創(chuàng)建mybatis的核心配置文件SqlmapConfig.xml
第四步:spring的配置文件
? 1檐什、數(shù)據(jù)庫(kù)連接池
? 2、SqlsessionFactory配置弱卡,應(yīng)該是整合包中的乃正。
第五步:開發(fā)dao
? 1、傳統(tǒng)dao開發(fā)(接口+實(shí)現(xiàn)類)
? 2婶博、Mapper代理的形式
第六步:
? 1烫葬、如果是傳統(tǒng)dao需要把實(shí)現(xiàn)類配置到spring容器中
? 2、Mapper代理形式凡蜻,也需要把代理對(duì)象配置spring容器中。
第七步:測(cè)試垢箕。
Sql mapConfig.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">
<configuration>
<!-- 別名配置 -->
<typeAliases>
<package name="cn.itcast.pojo"/>
</typeAliases>
<!-- 加載Mapper映射文件 -->
<mappers>
<package name="cn.itcast.mapper"/>
</mappers>
</configuration>
applicationContext. xml(Spring的配置文件)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">
<!-- 加載配置文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 數(shù)據(jù)庫(kù)連接池 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${JDBC_DRIVER}"/>
<property name="url" value="${JDBC_URL}"/>
<property name="username" value="${JDBC_USER}"/>
<property name="password" value="${JDBC_PASSWORD}"/>
<property name="maxActive" value="10"/>
<property name="maxIdle" value="5"/>
</bean>
<!-- sqlsessionFactory配置 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 加載mybatis的配置文件 -->
<property name="configLocation" value="classpath:SqlMapConfig.xml"/>
<!-- 數(shù)據(jù)庫(kù)連接池 -->
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
傳統(tǒng)dao的開發(fā)方式
接口+實(shí)現(xiàn)類
Mapper文件
創(chuàng)建mapper文件划栓。在SqlmapConfig.xml中加載。
接口
public interface OrderDao {
List<OrderUser> getOrderWithUser();
List<Orders> getOrderWithUserResultMap();
}
實(shí)現(xiàn)類
如果想從spring容器中獲得sqlsession需要繼承SqlSessionDaoSupport類条获。
public class OrderDaoImpl extends SqlSessionDaoSupport implements OrderDao {
@Override
public List<OrderUser> getOrderWithUser() {
//從spring容器中獲得sqlsession對(duì)象
SqlSession sqlSession = this.getSqlSession();
List<OrderUser> list = sqlSession.selectList("test.getOrderWithUser");
//不能調(diào)用close方法忠荞,交給spring完成
//sqlSession.close();
return list;
}
@Override
public List<Orders> getOrderWithUserResultMap() {
SqlSession sqlSession = this.getSqlSession();
List<Orders> list = sqlSession.selectList("test.getOrderWithUserResultMap");
return list;
}
}
把實(shí)現(xiàn)類配置到spring容器中
測(cè)試方法
public class OrderDaoTest {
private ApplicationContext applicationContext;
@Before
public void setUp() throws Exception {
//初始化spring容器
applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
}
@Test
public void testGetOrderWithUser() {
OrderDao orderDao = (OrderDao) applicationContext.getBean("orderDao");
List<OrderUser> orderWithUser = orderDao.getOrderWithUser();
System.out.println(orderWithUser);
}
@Test
public void testGetOrderWithUserResultMap() {
OrderDao orderDao = (OrderDao) applicationContext.getBean("orderDao");
List<Orders> list = orderDao.getOrderWithUserResultMap();
System.out.println(list);
}
}
Mapper代理形式的dao
Mapper文件+接口的開發(fā)
Mapper代理對(duì)象配置到spring容器中
使用Mapper的代理類
<!-- mapper的代理對(duì)象 -->
<bean id="orderMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<!-- mapperInterface這個(gè)屬性就是指定要為哪個(gè)接口做代理 -->
<property name="mapperInterface" value="cn.itcast.mapper.OrderMapper"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
使用包掃描器創(chuàng)建代理對(duì)象
<!-- 配置包掃描器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 指定要掃描的包,如果有多個(gè)包帅掘,使用半角逗號(hào)分隔 -->
<!-- 掃描后bean的id就是類名委煤,首字母小寫 -->
<property name="basePackage" value="cn.itcast.mapper"/>
<!-- 不需要指定sqlsessionFactory,掃描器會(huì)自動(dòng)找 -->
</bean>
掃描器是應(yīng)用廣泛的修档。
sqlmapConfig.xml:
逆向工程
什么是逆向工程
根據(jù)數(shù)據(jù)庫(kù)中的表生成java代碼碧绞。
1、pojo類吱窝。根據(jù)數(shù)據(jù)庫(kù)中表的字段生成讥邻。
2迫靖、Mapper接口。
3兴使、Mapper映射文件系宜。都是基于單表的操作。
官方提供工具
需要配置的信息
在generatorConfig.xml中配置
1发魄、數(shù)據(jù)庫(kù)連接
2盹牧、指定POJO生成的包名及生成的位置
3、指定Mapper文件励幼、映射文件生成的包及位置
4汰寓、指定需要逆向的表
指定逆向工程
執(zhí)行GeneratorSqlmap.java中的main方法。
注意:如果發(fā)現(xiàn)生成的代碼有問題需要?jiǎng)h除后重新生成赏淌,否則會(huì)在原文件中追加內(nèi)容踩寇。