文檔版本 | 開發工具 | 測試平臺 | 工程名字 | 日期 | 作者 | 備注 |
---|---|---|---|---|---|---|
V1.0 | 2016.06.28 | lutianfei | none |
mybatis框架履行進程:
mapper代理開發方法(建議使用)
本文內容:
商品表:items
表與表之間的業務關系:
在分析表與表之間的業務關系時需要建立在某個業務意義基礎上去分析。
先分析數據級別之間有關系的表之間的業務關系:
usre和orders:
orders和orderdetail:
orderdetail和itesm:
再分析數據庫級別沒有關系的表之間是不是有業務關系:
SELECT
orders.*,
USER.username,
USER.sex,
USER.address
FROM
orders,
USER
WHERE orders.user_id = user.id
OrdersMapperCustom.java
編寫測試類
public class OrdersMapperCustomTest {
private SqlSessionFactory sqlSessionFactory;
// 此方法是在履行testFindUserById之前履行
@Before
public void setUp() throws Exception {
// 創建sqlSessionFactory
// mybatis配置文件
String resource = "SqlMapConfig.xml";
// 得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 創建會話工廠,傳入mybatis的配置文件信息
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindOrdersUser() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 創建代理對象
OrdersMapperCustom ordersMapperCustom = sqlSession
.getMapper(OrdersMapperCustom.class);
// 調用maper的方法
List<OrdersCustom> list = ordersMapperCustom.findOrdersUser();
System.out.println(list);
sqlSession.close();
}
sql語句 : 同resultType實現的sql
使用resultMap映照的思路
Orders類中添加user屬性
OrdersMapperCustom.xml
<!-- 定單查詢關聯用戶的resultMap
將全部查詢的結果映照到cn.itcast.mybatis.po.Orders中
-->
<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserResultMap">
<!-- 配置映照的定單信息 -->
<!-- id:指定查詢列中的唯 1標識,定單信息的中的唯 1標識,如果有多個列組成唯1標識,配置多個id
column:定單信息的唯 1標識 列
property:定單信息的唯 1標識 列所映照到Orders中哪一個屬性
-->
<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/>
<!-- 配置映照的關聯的用戶信息 -->
<!-- association:用于映照關聯查詢單個對象的信息
property:要將關聯查詢的用戶信息映照到Orders中哪一個屬性
-->
<association property="user" javaType="cn.itcast.mybatis.po.User">
<!-- id:關聯查詢用戶的唯1標識
column:指定唯 1標識用戶信息的列
javaType:映照到user的哪一個屬性
-->
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</association>
</resultMap>
OrdersMapperCustom.java
測試代碼
@Test
public void testFindOrdersUserResultMap() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 創建代理對象
OrdersMapperCustom ordersMapperCustom = sqlSession
.getMapper(OrdersMapperCustom.class);
// 調用maper的方法
List<Orders> list = ordersMapperCustom.findOrdersUserResultMap();
System.out.println(list);
sqlSession.close();
}
如果沒有查詢結果的特殊要求建議使用resultType。
resultMap:需要單獨定義resultMap,實現有點麻煩,如果對查詢結果有特殊的要求,使用resultMap可以完成將關聯查詢映照pojo的屬性中。
需求 : 查詢定單及定單明細的信息。
sql語句
SELECT
orders.*,
USER.username,
USER.sex,
USER.address,
orderdetail.id orderdetail_id,
orderdetail.items_id,
orderdetail.items_num,
orderdetail.orders_id
FROM
orders,
USER,
orderdetail
WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id
分析 : 使用resultType將上邊的 查詢結果映照到pojo中,定單信息的就是重復。
要求:對orders映照不能出現重復記錄。
List<orderDetail>
orderDetails屬性。在Orders.java中添加list定單明細屬性
OrdersMapperCustom.xml
<!-- 定單及定單明細的resultMap
使用extends繼承,不用在中配置定單信息和用戶信息的映照
-->
<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersAndOrderDetailResultMap" extends="OrdersUserResultMap">
<!-- 定單信息 -->
<!-- 用戶信息 -->
<!-- 使用extends繼承,不用在中配置定單信息和用戶信息的映照 -->
<!-- 定單明細信息
1個定單關聯查詢出了多條明細,要使用collection進行映照
collection:對關聯查詢到多條記錄映照到集合對象中
property:將關聯查詢到多條記錄映照到cn.itcast.mybatis.po.Orders哪一個屬性
ofType:指定映照到list集合屬性中pojo的類型
-->
<collection property="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail">
<!-- id:定單明細唯 1標識
property:要將定單明細的唯1標識映照到cn.itcast.mybatis.po.Orderdetail的哪一個屬性
-->
<id column="orderdetail_id" property="id"/>
<result column="items_id" property="itemsId"/>
<result column="items_num" property="itemsNum"/>
<result column="orders_id" property="ordersId"/>
</collection>
</resultMap>
OrdersMapperCustom.java
測試代碼:
@Test
public void testFindOrdersAndOrderDetailResultMap() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 創建代理對象
OrdersMapperCustom ordersMapperCustom = sqlSession
.getMapper(OrdersMapperCustom.class);
// 調用maper的方法
List<Orders> list = ordersMapperCustom
.findOrdersAndOrderDetailResultMap();
System.out.println(list);
sqlSession.close();
}
需求 : 查詢用戶及用戶購買商品信息。
sql語句
SELECT
orders.*,
USER.username,
USER.sex,
USER.address,
orderdetail.id orderdetail_id,
orderdetail.items_id,
orderdetail.items_num,
orderdetail.orders_id,
items.name items_name,
items.detail items_detail,
items.price items_price
FROM
orders,
USER,
orderdetail,
items
WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id AND orderdetail.items_id = items.id
映照思路
List<Orders>
orderslist,將用戶創建的定單映照到orderslistList<OrderDetail>
orderdetials,將定單的明細映照到orderdetialsOrdersMapperCustom.xml
<!-- 查詢用戶及購買的商品 -->
<resultMap type="cn.itcast.mybatis.po.User" id="UserAndItemsResultMap">
<!-- 用戶信息 -->
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
<!-- 定單信息 1個用戶對應多個定單,使用collection映照-->
<collection property="ordersList" ofType="cn.itcast.mybatis.po.Orders">
<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"/>
<!-- 定單明細 1個定單包括 多個明細-->
<collection property="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail">
<id column="orderdetail_id" property="id"/>
<result column="items_id" property="itemsId"/>
<result column="items_num" property="itemsNum"/>
<result column="orders_id" property="ordersId"/>
<!-- 商品信息1個定單明細對應1個商品-->
<association property="items" javaType="cn.itcast.mybatis.po.Items">
<id column="items_id" property="id"/>
<result column="items_name" property="name"/>
<result column="items_detail" property="detail"/>
<result column="items_price" property="price"/>
</association>
</collection>
</collection>
</resultMap>
OrdersMapperCustom.java
測試代碼:
@Test
public void testFindUserAndItemsResultMap() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 創建代理對象
OrdersMapperCustom ordersMapperCustom = sqlSession
.getMapper(OrdersMapperCustom.class);
// 調用maper的方法
List<User> list = ordersMapperCustom.findUserAndItemsResultMap();
System.out.println(list);
sqlSession.close();
}
1對多是多對多的特例,以下需求:
總結:
場合:
resultMap:
association:
場合:
collection:
resultMap可以實現高級映照(使用association、collection實現1對1及1對多映照),association、collection具有延遲加載功能。
需求:
延遲加載:先從單表查詢、需要時再從關聯表去關聯查詢,大大提高數據庫性能,由于查詢單表要比關聯查詢多張表速度要快。
需求 : 查詢定單并且關聯查詢用戶信息
OrdresMapperCustom.xml
需要定義兩個mapper的方法對應的statement。
1、只查詢定單信息
SELECT * FROM orders
在查詢定單的statement中使用association去延遲加載(履行)下邊的satatement(關聯查詢用戶信息)
2、關聯查詢用戶信息
上邊先去履行findOrdersUserLazyLoading,當需要去查詢用戶的時候再去履行findUserById,通過resultMap的定義將延遲加載履行配置起來。
延遲加載resultMap
<!-- 延遲加載的resultMap -->
<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserLazyLoadingResultMap">
<!--對定單信息進行映照配置 -->
<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:指定延遲加載需要履行的statement的id(是根據user_id查詢用戶信息的statement)
要使用userMapper.xml中findUserById完成根據用戶id(user_id)用戶信息的查詢,如果findUserById不在本mapper中需要前邊加namespace
column:定單信息中關聯用戶信息查詢的列,是user_id
關聯查詢的sql理解為:
SELECT orders.*,
(SELECT username FROM USER WHERE orders.user_id = user.id)username,
(SELECT sex FROM USER WHERE orders.user_id = user.id)sex
FROM orders
-->
<association property="user" javaType="cn.itcast.mybatis.po.User"
select="cn.itcast.mybatis.mapper.UserMapper.findUserById" column="user_id">
<!-- 實現對用戶信息進行延遲加載 -->
</association>
</resultMap>
OrderesMapperCustom.java
測試思路:
List<Orders>
,當我們調用Orders中的getUser方法時,開始進行延遲加載。mybatis默許沒有開啟延遲加載,需要在SqlMapConfig.xml中setting
配置。
在mybatis核心配置文件中配置:
設置項 | 描寫 | 允許值 | 默許值 |
---|---|---|---|
lazyLoadingEnabled | 全局性設置懶加載。如果設為‘false’,則所有相干聯的都會被初始化加載。 | true or false | false |
aggressiveLazyLoading | 當設置為‘true’的時候,懶加載的對象可能被任何懶屬性全部加載。否則,每一個屬性都按需加載。 | true or false | true |
在SqlMapConfig.xml中配置:
測試代碼
延遲加載思考
實現方法以下:
總之:使用延遲加載方法,先去查詢簡單的sql(最好單表,也能夠關聯查詢),再去按需要加載關聯查詢的其它信息。
1級緩存是SqlSession級別的緩存。在操作數據庫時需要構造 sqlSession對象,在對象中有1個數據結構(HashMap)用于存儲緩存數據。不同的sqlSession之間的緩存數據區域(HashMap)是相互不影響的。
2級緩存是mapper級別的緩存,多個SqlSession去操作同1個Mapper的sql語句,多個SqlSession可以共用2級緩存,2級緩存是跨SqlSession的。
為何要用緩存?
1級緩存工作原理
第1次發起查詢用戶id為1的用戶信息,先去找緩存中是不是有id為1的用戶信息,如果沒有,從數據庫查詢用戶信息。
//OrdersMapperCusntomTest.java
@Test
public void testCache1() throws Exception{
SqlSession sqlSession = sqlSessionFactory.openSession();//創建代理對象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//下邊查詢使用1個SqlSession
//第1次發起要求,查詢id為1的用戶
User user1 = userMapper.findUserById(1);
System.out.println(user1);
// 如果sqlSession去履行commit操作(履行插入、更新、刪除),清空SqlSession中的1級緩存,這樣做的目的為了讓緩存中存儲的是最新的信息,避免臟讀。
//更新user1的信息
user1.setUsername("測試用戶22");
userMapper.updateUser(user1);
//履行commit操作去清空緩存
sqlSession.commit();
//第2次發起要求,查詢id為1的用戶
User user2 = userMapper.findUserById(1);
System.out.println(user2);
sqlSession.close();
}
service{
//開始履行時,開啟事務,創建SqlSession對象
//第1次調用mapper的方法findUserById(1)
//第2次調用mapper的方法findUserById(1),從1級緩存中取數據
//方法結束,sqlSession關閉
}
首先開啟mybatis的2級緩存。
sqlSession1去查詢用戶id為1的用戶信息,查詢到用戶信息會將查詢數據存儲到2級緩存中。
如果SqlSession3去履行相同 mapper下sql,履行commit提交,清空該 mapper下的2級緩存區域的數據。
sqlSession2去查詢用戶id為1的用戶信息,去緩存中找是不是存在數據,如果存在直接從緩存中取出數據。
2級緩存與1級緩存區分,2級緩存的范圍更大,多個sqlSession可以同享1個UserMapper的2級緩存區域。
<setting name="cacheEnabled" value="true"/>
描寫 | 允許值 | 默許值 |
---|---|---|
cacheEnabled | 對在此配置文件下的所有cache 進行全局性開/關設置。 | true or false |
調用pojo類實現序列化接口
2級緩存測試
@Test
public void testCache2() throws Exception {
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
SqlSession sqlSession3 = sqlSessionFactory.openSession();
// 創建代理對象
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
// 第1次發起要求,查詢id為1的用戶
User user1 = userMapper1.findUserById(1);
System.out.println(user1);
//這里履行關閉操作,將sqlsession中的數據寫到2級緩存區域
sqlSession1.close();
//使用sqlSession3履行commit()操作
UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);
User user = userMapper3.findUserById(1);
user.setUsername("張明明");
userMapper3.updateUser(user);
//履行提交,清空UserMapper下邊的2級緩存
sqlSession3.commit();
sqlSession3.close();
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
// 第2次發起要求,查詢id為1的用戶
User user2 = userMapper2.findUserById(1);
System.out.println(user2);
sqlSession2.close();
}
<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true">
ehcache是1個散布式緩存框架。
散布緩存
mybatis和ehcache整合,mybatis和ehcache整合包中提供了1個cache接口的實現類。
mybatis默許實現cache類是:
加入ehcache包
整合ehcache
加入ehcache的配置文件(在classpath下配置ehcache.xml)
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<diskStore path="F:\develop\ehcache" />
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
<defalutCache/>
指定的的管理策略上一篇 識別喜歡開發的程序員
下一篇 HDU 3572 網絡流