mybatis框架--学习笔记(下)
上篇:mybatis框架--學習筆記(上):https://blog.csdn.net/a745233700/article/details/81034021
8、高級映射:
(1)一對一查詢:
①使用resultType:
<!-- 一對一查詢:resultType --> <select id="findOrdersUser" resultType="com.zwp.po.OrdersCustom">select orders.*,user.username,user.sex,user.addressfrom orders,userwhere orders.user_id=user.id </select> //Orders的擴展類 public class OrdersCustom extends Orders{//添加用屬性private String username;private String sex;private String address;//下面省略get和set方法.. }②使用resultMap:(association)
使用resultMap將查詢結(jié)果中的訂單信息映射到Orders對象中,在orders類中添加User屬性,將關(guān)聯(lián)查詢出來的用戶信息映射到orders對象中的user屬性中。
public class Orders {private Integer id;private Integer userId;private String number;private Date createtime;private String note;private User user;//在Orders中添加User屬性,一對一//下面省略get和set方法 } <!-- 一對一查詢:resultMap使用resultMap將查詢結(jié)果中的訂單信息映射到Orders對象中,在orders類中添加User屬性,將關(guān)聯(lián)查詢出來的用戶信息添加到orders對象的user屬性中--><resultMap type="com.zwp.po.Orders" id="OrdersUserResultMap"><!-- 配置訂單信息的映射 --><!-- id:指定查詢列中的唯一標識,即訂單信息的唯一標識,如果有多個列組成唯一標識,則配置多個idcolumn:查詢出來的列名; property:映射到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" /><!-- 配置映射的關(guān)聯(lián)的用戶信息 --><!-- association:用于映射關(guān)聯(lián)查詢的單個對象信息property:要將關(guān)聯(lián)查詢的用戶信息映射到Orders中的哪個屬性 --><association property="user" javaType="com.zwp.po.User"><!-- id:關(guān)聯(lián)查詢的唯一標識,column:指定唯一標識的用戶的列 --><id column="user_id" property="id" /><result column="username" property="username" /><result column="sex" property="sex" /><result column="address" property="address" /></association> </resultMap> <select id="findOrdersUserResultMap" resultMap="OrdersUserResultMap">select orders.*,user.username,user.sex,user.addressfrom orders,userwhere orders.user_id=user.id</select>小結(jié):實現(xiàn)一對一查詢:
resultyType:使用resultType實現(xiàn)較為簡單,如果pojo中沒有包括查詢出來的列名,需要增加列名對應(yīng)的屬性,即可完成映射。如果沒有查詢結(jié)果的特殊要求,建議使用resultyType。
resultMap:需要 單獨定義resultMap,實現(xiàn)有點麻煩,如果有對查詢結(jié)果有特殊要求,使用resultMap可以完成將關(guān)聯(lián)查詢映射到pojo的屬性中。
resultMap可以實現(xiàn)延時加載,resultyType無法實現(xiàn)延時加載。
(2)一對多查詢:(collection)
要求:對orders映射不能出現(xiàn)重復記錄。
思路:在order.java類中添加List<OrderDetail>orderDetails屬性,最終會將訂單信息映射到orders中,訂單所對應(yīng)的訂單明細映射到orders中的orderDetails屬性中。
public class Orders {private Integer id;private Integer userId;private String number;private Date createtime;private String note;private User user;//用戶信息,一對一//訂單明細:一對多private List<Orderdetail> orderdetail;//省略get和set方法 } ????????<!-- 一對多查詢: --><resultMap type="com.zwp.po.Orders" id="OrdersAndOrderdetailResultMap" extends="OrdersUserResultMap"><!-- 訂單信息 --><!-- 用戶信息 --><!-- extends繼承:可以不用再配置訂單信息和用戶信息的映射 --><!-- 訂單明細信息:一個訂單關(guān)聯(lián)查詢出了多條明細,要使用collection進行映射collection:對關(guān)聯(lián)查詢多條映射到集合對象中;property:將關(guān)聯(lián)查詢多條映射到pojo的哪個屬性中;ofType:指定映射到list集合屬性中pojo的類型。--><collection property="orderdetail" ofType="com.zwp.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><select id="findOrdersAndOrderdetailResultMap" resultMap="OrdersAndOrderdetailResultMap">select orders.*,user.username,user.sex,user.address,orderdetail.id orderdetail_id,orderdetail.items_id,orderdetail.items_num,orderdetail.orders_idfrom orders,user,orderdetailwhere orders.user_id=user.id and orderdetail.orders_id=orders.id</select>小結(jié):mybatis使用resultMap的collection對關(guān)聯(lián)查詢的多條記錄映射到一個list集合屬性中。
如果使用resultType實現(xiàn):將訂單明細映射到orders中的ordertails中,需要自己處理,使用雙重循環(huán)遍歷,去掉重復記錄,將訂單明細放在ordertails中。
(3)多對多查詢:
映射思路:將用戶信息映射到user中。
在user類中添加訂單列表屬性List<Orders>orderslist,將用戶創(chuàng)建的訂單映射到orderlist;
在Orders中添加訂單明細列表屬性List<OrderDetail>orderdetails,將訂單的明細映射到orderdetails;
在OrderDetail中添加items屬性,將訂單明細所對應(yīng)的商品映射到items。
<!-- 多對多查詢 --><resultMap type="com.zwp.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"/><!-- 配置訂單信息:用戶對訂單:一對多關(guān)系:collection --><collection property="orders" ofType="com.zwp.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" /><!-- 配置訂單詳情信息:訂單對訂單詳情:一對多關(guān)系:collection --><collection property="orderdetail" ofType="com.zwp.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"/><!-- 配置商品信息:訂單詳情對商品:一對一:association --><association property="items" javaType="com.zwp.po.Items"><id column="itemsid" property="id"/><result column="name" property="name"/><result column="price" property="price"/><result column="detail" property="detail"/><result column="items_creatime" property="creatime"/></association></collection></collection></resultMap><select id="findUserAndItemsResultMap" resultMap="UserAndItemsResultMap">select orders.*,user.username,user.sex,user.address,orderdetail.id orderdetail_id,orderdetail.items_id,orderdetail.items_num,orderdetail.orders_id,items.id itemsid,items.name,items.price,items.detail,items.creatime items_creatimefrom orders,user,orderdetail,itemswhere orders.user_id=user.id and orderdetail.orders_id=orders.id and items_id=items.id</select> public class User {private Integer id;private String username;private String birthday;private String sex;private String address;private List<Orders> orders; } public class Orders {private Integer id;private Integer userId;private String number;private Date createtime;private String note;private User user;private List<Orderdetail> orderdetail; } public class Orderdetail {private Integer id;private Integer ordersId;private Integer itemsId;private Integer itemsNum;private Items items; } public class Items {private Integer id;private String name;private Float price;private String pic;private Date creatime;private String detail; }(4)總結(jié):
①resultMap:使用association和collection完成一對一和一對多高級映射,用于對結(jié)果有特殊的映射要求。
②association:
? ? 作用:將關(guān)聯(lián)查詢信息映射到一個pojo對象中。
? ? 場合:為了方便查詢關(guān)聯(lián)信息,可以使用association將關(guān)聯(lián)訂單信息映射為用戶對象的pojo屬性中,比如:查詢訂單及關(guān)聯(lián)用戶信息。
? ? 使用resultType無法將查詢結(jié)果映射到pojo對象的pojo屬性中,根據(jù)對結(jié)果集查詢遍歷的需要選擇使用resultType還是resultMap。
③collection:
? ? 作用:將關(guān)聯(lián)查詢信息映射到一個list集合中。
? ? 場合:為了方便查詢遍歷關(guān)聯(lián)信息可以使用collection,將關(guān)聯(lián)信息映射到list集合中,比如:查詢用戶權(quán)限范圍模塊下及模塊下的菜單,可以使用collection將其權(quán)限模塊映射到權(quán)限模塊list中,將菜單列表映射到權(quán)限模塊對象的菜單list屬性中,這樣做的目的也是方便對查詢結(jié)果進行遍歷查詢。
? ? 如果使用resultType無法將查詢結(jié)果映射到List集合中。
9、延時加載:
resultMap的association和collection具備延時加載功能。
延時加載:先從單表查詢,需要時再從關(guān)聯(lián)表去關(guān)聯(lián)查詢,大大提高數(shù)據(jù)庫性能,因為查詢單表要比關(guān)聯(lián)查詢多表速度要快。
(1)使用association中的select指定延遲加載去執(zhí)行的statement的id
<!-- 延遲加載:查詢用戶訂單信息:用戶信息要求延遲加載 --><resultMap type="com.zwp.po.Orders" id="OrderUserLazyLoading"><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,如果不在同一個namespace,需要加上namespacecolumn:表示關(guān)聯(lián)的字段--><association property="user" javaType="com.zwp.po.User" select="findUserById" column="user_id"><id column="user_id" property="id" /><result column="username" property="username" /><result column="sex" property="sex" /><result column="address" property="address" /><result column="birthday" property="birthday" /></association></resultMap> <!-- 不可以使用resultType,因為resultType沒有延遲加載功能 --><select id="findOrderUserLazyLoading" resultMap="OrderUserLazyLoading">select * from orders</select><!-- 查詢訂單關(guān)聯(lián)查詢用戶,用戶信息需要延時加載 --><select id="findUserById" parameterType="int" resultType="com.zwp.po.User">SELECT * FROM USER WHERE id=#{id}</select>(2)延遲加載配置:
Mybatis默認沒有開啟延時加載,需要在SqlMapperConfig.xml中的setting配置。
<!-- settings:配置全局變量 --><settings><!-- 開啟延遲加載開關(guān) --><setting name="lazyLoadingEnabled" value="true"/><!-- 將積極加載改為消極加載,即按需加載 --><setting name="aggressiveLazyLoading" value="false"/></settings>(3)總結(jié):
使用延時加載方法,先去查詢簡單的sql(最好是單表,也可以關(guān)聯(lián)查詢),再去按需要加載關(guān)聯(lián)查詢的其他信息。
10、一級緩存:(mybatis默認支持一級緩存)
緩存:提高系統(tǒng)的性能,減少數(shù)據(jù)庫的壓力。
11、二級緩存:(默認不開啟)
(1)開啟二級緩存:
①在核心配置文件SqlMapConfig.xml中加入:
<!-- settings:配置全局變量 --><settings><!-- 開啟二級緩存 --><setting name="cacheEnabled" value="true"/></settings>②在xxxMapper.xml文件中開啟二級緩存,xxxMapper.xml下的sql執(zhí)行完會存儲到他的緩存區(qū)域(HashMap)
<mapper namespace="com.zwp.mapper.OrdersMapperCustom"><!-- 開啟本mapper下的二級緩存<cache/> </mapper>(2)useCache配置:禁用二級緩存:
在statement中設(shè)置useCache=false可以禁用當前select語句的二級緩存,即每次查詢都會發(fā)出sql去查詢,默認是true,即改sql使用二級緩存。
<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">場景:針對每次查詢都需要更新的數(shù)據(jù)sql,要設(shè)置成useCache=false,禁用二級緩存。
(3)刷新緩存(清空緩存):
設(shè)置statement配置中的flushCache="true"屬性,默認情況下為true即刷新緩存,如果改成false則不會刷新。
<insert id="insertUser" parameterType="com.zwp.domain.User" flushCache="true">場景:一般情況下執(zhí)行完commit操作都需要刷新緩存,flushCache=true表示刷新緩存,這樣可以避免數(shù)據(jù)庫臟讀。
12、分布緩存:mybatis整合ehcache:
分布緩存:可以實現(xiàn)對緩存數(shù)據(jù)進行集中管理。
(1)Mybatis無法實現(xiàn)分布式緩存,需要和其他分布式緩存框架進行整合。
(2)整合方法:
? ? ????mybatis提供了一個cache接口,如果要實現(xiàn)自己的緩存邏輯,實現(xiàn)cache接口開發(fā)即可。
????? ?mybatis和ehcache整合,mybatis和ehcache整合包中提供了一個Cache接口的實現(xiàn)類。
(3)加入jar包依賴:
(4)整合ehcache:
(5)加入ehcache的配置文件:
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <diskStore path="D:\develop\ehcache" /> <defaultCache maxElementsInMemory="1000" maxElementsOnDisk="10000000" eternal="false" overflowToDisk="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> </defaultCache> </ehcache>13、mybatis和spring整合開發(fā):
需要spring通過單例方式管理SqlSessionFactory。
spring和mybatis整合生成代理對象,使用SqlSessionFactory創(chuàng)建SqlSession,持久層的mapper都需要由spring進行管理。
步驟:
(1)導入jar包依賴:
(2)sqlSessionFactory配置:
在applicationContext.xml配置sqlSessionFatory,sqlSessionFatory在mybatis和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: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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!-- 1.加載數(shù)據(jù)庫配置文件 --><context:property-placeholder location="classpath:db.properties"/><!-- 2.配置連接池 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"><property name="driverClass" value="${jdbc.driver}"></property><property name="jdbcUrl" value="${jdbc.url}"></property><property name="user" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property></bean><!-- 3.創(chuàng)建會話工廠sqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><!-- 加載mybatis的配置文件 --><property name="configLocation" value="mybatis/SqlMapConfig.xml"></property><!-- 配置數(shù)據(jù)源 --><property name="dataSource" ref="dataSource"></property></bean> </beans>(3)①原始dao開發(fā):
--User.xml文件:
<mapper namespace="test"><select id="findUserById" parameterType="int" resultType="com.zwp.ssm.po.User">SELECT * FROM USER WHERE id=#{id}</select> </mapper>在SqlMapConfig.xml文件中加載映射文件:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration><!-- 加載映射文件 --><mappers><!-- 通過resource加載單個映射文件 --><mapper resource="sqlmap/User.xml"></mapper></mappers> </configuration> --Dao:(實現(xiàn)類繼承SqlSessionDaoSupport) public interface UserDao {//根據(jù)id查詢用戶public User findUserById(int id) throws Exception; }DaoImpl接口實現(xiàn)類需要注入sqlSessionFactory,通過spring進行注入:
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao{//繼承SqlSessionDaoSupport//父類已經(jīng)定義SqlSessionFactory對象和set方法,不需要重新寫@Overridepublic User findUserById(int id) throws Exception{SqlSession sqlSession=this.getSqlSession();//不需要手動關(guān)閉sqlSessionSystem.out.println(sqlSession);User user=sqlSession.selectOne("test.findUserById",id);return user;} }通過spring創(chuàng)建接口的bean對象:
<!--原始dao接口 --><bean id="userDao" class="com.zwp.Dao.UserDaoImpl"><!-- sqlSessionFactory不能寫錯 --><property name="sqlSessionFactory" ref="sqlSessionFactory"></property></bean> (3)②mapper代理開發(fā):--mapper.xml和mapper.java:
public interface UserMapper {/*(1)mapper.java接口中方法名和mapper.xml中的statement的id一致(2)mapper.java接口中方法的輸入?yún)?shù)類型和mapper.xml中statement的parameterType指定的類型一致(3)mapper.java接口中方法的返回值類型和mapper.xml中statement的resultment中resultType指定類型一致。*///根據(jù)id查詢用戶public User findUserById(int id) throws IOException; } <?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="com.zwp.ssm.mapper.UserMapper"><select id="findUserById" parameterType="int" resultType="com.zwp.ssm.po.User">SELECT * FROM USER WHERE id=#{id}</select> </mapper>
----通過mapperFactoryBean創(chuàng)建代理對象(此方法存在問題):
<!-- mapper接口 --><!-- MapperFactoryBean:根據(jù)mapper接口生成代理對象 --><bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"><!-- mapperInterface指定mapper接口 --><property name="mapperInterface" value="com.zwp.ssm.mapper.UserMapper"></property><property name="sqlSessionFactory" ref="sqlSessionFactory"></property></bean>此方法的問題:如果有很多個mapper,需要針對每個mapper進行單獨配置。
解決方法:通過MapperScannerConfigure進行mapper批量掃描。
<!-- mapper批量掃描,從mapper包中掃描出mapper,自動創(chuàng)建代理對象并且在spring容器中注冊遵循規(guī)范:需要mapper接口類名和mapper.xml映射文件名稱一致,且在同一目錄下 自動掃描出來的mapper的bean的id為類名(首字母小寫)--><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><!-- 指定掃描的包名 --><!-- 如果掃描多個包,每個包中間使用半角逗號隔開 --><property name="basePackage" value="com.zwp.ssm.mapper"></property><!-- sqlSessionFactoryBeanName不能寫成sqlSessionFactory,不然會導致連接不上數(shù)據(jù)庫 --><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property></bean>總結(jié)
以上是生活随笔為你收集整理的mybatis框架--学习笔记(下)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mybatis框架--学习笔记(上)
- 下一篇: SpringMVC框架--学习笔记(上)