resultMap可以實現高級映射(使用association、collection實現一對一及一對多映射),association、collection具備延遲加載功能。
需求:
如果查詢訂單並且關聯查詢用戶信息。如果先查詢訂單信息即可滿足要求,當我們需要查詢用戶信息時再查詢用戶信息。把對用戶信息的按需去查詢就是延遲加載。
延遲加載:先從單表查詢、需要時再從關聯表去關聯查詢,大大提高 數據庫性能,因為查詢單表要比關聯查詢多張表速度要快。
接下來我們用assocation來實現延遲加載:
先給出需求:
查詢訂單並且關聯查詢用戶信息
老規矩:1.sql語句,2.pojo類,3.mapper.xml和mapper.java接口
第一步:
1。我們要實現延時加載,相當於先查訂單(orders)的信息,等需要用到user的信息時再去查詢User表。
也就是把
<select id="findOrdersUserLazyLoading" resultMap="OrdersUserLazyLoadingResultMap"> Select * from orders; </select>
<select id="finduserByid" parameterType="int" resultType="cn.itcast.mybatis.po.User"> SELECT * FROM USER WHERE ID=#{VALUE} </select>
上面兩條select語句用延遲加載的方式實現。(用resultMap來連接這兩條select語句)
第二步:
2.pojo類:
package cn.itcast.mybatis.po; import java.util.Date; import java.util.List; public class Orders { private Integer id; private Integer user_id; private String number; private Date createtime; private String note; //用戶信息,新增了一個User屬性,為了保存查詢得到的關聯的User表的信息(一對一) private User user; public List<Orderdetail> getOrderdetail() { return orderdetails; } public void setOrderdetail(List<Orderdetail> orderdetail) { this.orderdetails = orderdetail; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getUser_id() { return user_id; } public void setUser_id(Integer user_id) { this.user_id = user_id; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public Date getCreatetime() { return createtime; } public void setCreatetime(Date createtime) { this.createtime = createtime; } public String getNote() { return note; } public void setNote(String note) { this.note = note; } }
第三步:
3.編寫OrderMapperCustom.xml代碼:使用association中的select指定延遲加載去執行的statement的id。
<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserLazyLoadingResultMap">這句代碼的作用就是用來連接上面那兩條select語句來實現延遲加載。
<?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"> <!-- nanmespace:命名空間。 作用就是對sql進行分類話管理,理解Sal分離 注意:使用mapper代理方式,namespace有特殊重要的作用 --> <mapper namespace="cn.itcast.mybatis.mapper.OrdersMapperCustom"> <!-- 延遲加載的resultMap --> <resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserLazyLoadingResultMap"> <!--對訂單信息進行映射配置 --> <resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserLazyLoadingResultMap"> <id column="id" property="id"/> <result column="user_id" property="user_id"/> <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="finduserByid" column="user_id" > </association> </resultMap> <select id="finduserByid" parameterType="int" resultType="cn.itcast.mybatis.po.User"> SELECT * FROM USER WHERE ID=#{VALUE} </select> <select id="findOrdersUserLazyLoading" resultMap="OrdersUserLazyLoadingResultMap"> Select * from orders; </select> </mapper>
編寫OrdersMapperCustom.java接口:
package cn.itcast.mybatis.mapper; import java.util.List; import cn.itcast.mybatis.po.Orders; import cn.itcast.mybatis.po.OrdersCustom; import cn.itcast.mybatis.po.User; public interface OrdersMapperCustom { //函數的名字OrdersMapperCustom.xml中select中的id名一樣 public List<Orders> findOrdersUserLazyLoading(); }
第四步:
不要忘記修改總的配置文件,setting 加上延遲加載的功能
延遲加載配置
mybatis默認沒有開啟延遲加載,需要在SqlMapConfig.xml中setting配置。
在mybatis核心配置文件中配置:
lazyLoadingEnabled、aggressiveLazyLoading
| 設置項 |
描述 |
允許值 |
默認值 |
| lazyLoadingEnabled |
全局性設置懶加載。如果設為‘false’,則所有相關聯的都會被初始化加載。 |
true | false |
false |
| aggressiveLazyLoading |
當設置為‘true’的時候,懶加載的對象可能被任何懶屬性全部加載。否則,每個屬性都按需加載。 |
true | false |
true |
在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"> <configuration> <!-- properties的配置必須寫在typeAliases的上面 --> <properties resource="db.properties"></properties>
<!-- 配置懶加載設置 -->
<settings> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> </settings> <!-- 和spring整合后 environments配置將廢除--> <environments default="development"> <environment id="development"> <!-- 使用jdbc事務管理--> <transactionManager type="JDBC" /> <!-- 數據庫連接池--> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </dataSource> </environment> </environments> <!-- 把映射文件(sqlmap/user.xml)加載進sqlMapConfig.xml--> <mappers> <!-- 把mapper.xml加載進sqlMapConfig.xml--> <!-- 遵循一些規范:需要將mapper接口類名和mapper.xml映射文件名稱保持一致 且在一個目錄中。 當着這個規范的前提是:使用mapper代理方法。 --> <mapper class="cn.itcast.mybatis.mapper.OrdersMapperCustom"/> </mappers> </configuration>
第五步:
編寫測試代碼:
測試思路:
1、執行上邊mapper方法(findOrdersUserLazyLoading),內部去調用cn.itcast.mybatis.mapper.OrdersMapperCustom中的findOrdersUserLazyLoading只查詢orders信息(單表)。
2、在程序中去遍歷上一步驟查詢出的List<Orders>,當我們調用Orders中的getUser方法時,開始進行延遲加載。
3、延遲加載,去調用UserMapper.xml中findUserbyId這個方法獲取用戶信息。
測試代碼Mybatis_mappertest.java如下:
package cn.itcast.mybatis.test; import java.io.IOException; import java.io.InputStream; import java.util.Date; import java.util.List; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Before; import org.junit.Test; import cn.itcast.mybatis.mapper.OrdersMapperCustom; import cn.itcast.mybatis.mapper.userMapper; import cn.itcast.mybatis.po.Orders; import cn.itcast.mybatis.po.User; import cn.itcast.mybatis.po.UserCustom; import cn.itcast.mybatis.po.UserQueryVo; public class Mybatis_mappertest { private SqlSessionFactory sqlSessionFactory; @Before public void setup() throws IOException { String resource="SqlMapConfig.xml"; InputStream inputStream= Resources.getResourceAsStream(resource); //主要是生成SqlsessionFactory。 this.sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream); } @Test public void testMaper() { SqlSession sqlSession=null; sqlSession=sqlSessionFactory.openSession(); //生成代理類 OrdersMapperCustom orderMapper=sqlSession.getMapper(OrdersMapperCustom.class); //創建包裝對象,設置查詢條件 //orderMapper.findOrdersUser(); @SuppressWarnings("unused") List<Orders> list=orderMapper.findOrdersUserLazyLoading(); for(Orders orders:list) {//只有執行了這一步才會執行延遲加載。 User user=orders.getUser(); System.out.println(user); } } }
運行結果如下:
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@30647e13]
DEBUG [main] - ==> Preparing: Select * from orders;
DEBUG [main] - ==> Parameters:
DEBUG [main] - <== Total: 3
DEBUG [main] - ==> Preparing: SELECT * FROM USER WHERE ID=?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <== Total: 1
cn.itcast.mybatis.po.User@1ff90029
我們看一下上面的結果:第一條sql語句:Select * from orders;
然后才會有:SELECT * FROM USER WHERE ID=?
實現了延遲加載、
