上一篇文章我們講解了《Mybatis—spring和mybatis整合(十)》下面我們繼續來講解延遲加載和逆向工程。
【延遲加載】
1、什麼是延遲加載
resultMap可以實現高級映射(使用association、collection實現一對一及一對多映射),association、collection具備延遲加載功能。
需求:
如果查詢訂單並且關聯查詢用戶信息。如果先查詢訂單信息即可滿足要求,當我們需要查詢用戶信息時再查詢用戶信息。把對用戶信息的按需去查詢就是延遲加載。
延遲加載:先從單表查詢、需要時再從關聯表去關聯查詢,大大提高 數據庫性能,因爲查詢單表要比關聯查詢多張錶速度要快。
2、使用association實現延遲加載需求
查詢訂單並且關聯查詢用戶信息
3、mapper.xml
需要定義兩個mapper的方法對應的statement。
1)只查詢訂單信息
SELECT * FROM orders
在查詢訂單的statement中使用association去延遲加載(執行)下邊的satatement(關聯查詢用戶信息)
<!-- 查詢訂單關聯查詢用戶,用戶信息需要延遲加載 -->
<select id="findOrdersUserLazyLoading" resultMap="OrdersUserLazyLoadingResultMap">
SELECT * FROM orders
</select>
2)關聯查詢用戶信息
通過上邊查詢到的訂單信息中user_id去關聯查詢用戶信息
使用UserMapper.xml中的findUserById
上邊先去執行findOrdersUserLazyLoading,當需要去查詢用戶的時候再去執行findUserById,通過resultMap的定義將延遲加載執行配置起來。
4、延遲加載resultMap
使用association中的select指定延遲加載去執行的statement的id。
<!-- 延遲加載的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>
5、mapper.java
//查詢訂單關聯查詢用戶,用戶信息是延遲加載
public List<Orders> findOrdersUserLazyLoading()throws Exception;
6、測試
1)測試思路
1、執行上邊mapper方法(findOrdersUserLazyLoading),內部去調用cn.itcast.mybatis.mapper.OrdersMapperCustom中的findOrdersUserLazyLoading只查詢orders信息(單表)。
2、在程序中去遍歷上一步驟查詢出的List,當我們調用Orders中的getUser方法時,開始進行延遲加載。
3、延遲加載,去調用UserMapper.xml中findUserbyId這個方法獲取用戶信息。
2)延遲加載配置
mybatis默認沒有開啓延遲加載,需要在SqlMapConfig.xml中setting配置。
在mybatis核心配置文件中配置:
lazyLoadingEnabled、aggressiveLazyLoading
在SqlMapConfig.xml中配置:
<!-- 全局配置參數,需要時再設置 -->
<settings>
<!-- 打開延遲加載 的開關 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 將積極加載改爲消極加載即按需要加載 -->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 開啓二級緩存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
3)測試代碼
// 查詢訂單關聯查詢用戶,用戶信息使用延遲加載
@Test
public void testFindOrdersUserLazyLoading() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();// 創建代理對象
OrdersMapperCustom ordersMapperCustom = sqlSession
.getMapper(OrdersMapperCustom.class);
// 查詢訂單信息(單表)
List<Orders> list = ordersMapperCustom.findOrdersUserLazyLoading();
// 遍歷上邊的訂單列表
for (Orders orders : list) {
// 執行getUser()去查詢用戶信息,這裏實現按需加載
User user = orders.getUser();
System.out.println(user);
}
}
7、延遲加載思考
不使用mybatis提供的association及collection中的延遲加載功能,如何實現延遲加載??
實現方法如下:
定義兩個mapper方法:
1)查詢訂單列表
2)根據用戶id查詢用戶信息
實現思路:
先去查詢第一個mapper方法,獲取訂單信息列表
在程序中(service),按需去調用第二個mapper方法去查詢用戶信息。
總之:
使用延遲加載方法,先去查詢簡單的sql(最好單表,也可以關聯查詢),再去按需要加載關聯查詢的其它信息。
【逆向工程】
1、什麼是逆向工程
mybaits需要程序員自己編寫sql語句,mybatis官方提供逆向工程 可以針對單表自動生成mybatis執行所需要的代碼(mapper.java,mapper.xml、po..)
企業實際開發中,常用的逆向工程方式:
由於數據庫的表生成java代碼。
2、下載逆向工程
建議使用java程序方式,不依賴開發工具。
3、使用方法(會用)
1)運行逆向工程
2)生成代碼配置文件
代碼中黑色的字體是配置數據庫的時候要更改的內容
<?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">
<generatorConfiguration>
<context id="testTables" targetRuntime="MyBatis3">
<commentGenerator>
<!-- 是否去除自動生成的註釋 true:是 : false:否 -->
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!--數據庫連接的信息:驅動類、連接地址、用戶名、密碼 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis" **userId="root"
password="mysql">**
</jdbcConnection>
<!-- <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 -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- targetProject:生成PO類的位置 -->
<javaModelGenerator targetPackage="cn.itcast.ssm.po"
targetProject=".\src">
<!-- enableSubPackages:是否讓schema作爲包的後綴 -->
<property name="enableSubPackages" value="false" />
<!-- 從數據庫返回的值被清理前後的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="cn.itcast.ssm.mapper"
targetProject=".\src">
<!-- enableSubPackages:是否讓schema作爲包的後綴 -->
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- targetPackage:mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="cn.itcast.ssm.mapper"
targetProject=".\src">
<!-- enableSubPackages:是否讓schema作爲包的後綴 -->
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!-- 指定數據庫表 -->
<table tableName="items"></table>
<table tableName="orders"></table>
<table tableName="orderdetail"></table>
<table tableName="user"></table>
</context>
</generatorConfiguration>
3)執行生成程序
執行後的結果:
4)使用生成的代碼
需要將生成工程中所生成的代碼拷貝到自己的工程中。
測試ItemsMapper中的方法
private ApplicationContext applicationContext;
private ItemsMapper itemsMapper;
//在setUp這個方法得到spring容器
@Before
public void setUp() throws Exception {
applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");
itemsMapper = (ItemsMapper) applicationContext.getBean("itemsMapper");
}
//自定義條件查詢
@Test
public void testSelectByExample() {
ItemsExample itemsExample = new ItemsExample();
//通過criteria構造查詢條件
ItemsExample.Criteria criteria = itemsExample.createCriteria();
criteria.andNameEqualTo("筆記本3");
//可能返回多條記錄
List<Items> list = itemsMapper.selectByExample(itemsExample);
System.out.println(list);
}
//根據主鍵查詢
@Test
public void testSelectByPrimaryKey() {
Items items = itemsMapper.selectByPrimaryKey(1);
System.out.println(items);
}
//插入
@Test
public void testInsert() {
//構造 items對象
Items items = new Items();
items.setName("手機");
items.setPrice(999f);
itemsMapper.insert(items);
}
//更新數據
@Test
public void testUpdateByPrimaryKey() {
//對所有字段進行更新,需要先查詢出來再更新
Items items = itemsMapper.selectByPrimaryKey(1);
items.setName("水杯");
itemsMapper.updateByPrimaryKey(items);
//如果傳入字段不空爲才更新,在批量更新中使用此方法,不需要先查詢再更新
//itemsMapper.updateByPrimaryKeySelective(record);
}
小編關於Mybatis的系列博客就先寫到這裏,歡迎讀者們的閱讀。。。。