一、Mybatis中的延遲加載java
問題:在一對多中,當咱們有一個用戶,它有100個帳戶。 在查詢用戶的時候,要不要把關聯的帳戶查出來? 在查詢帳戶的時候,要不要把關聯的用戶查出來? 在查詢用戶時,用戶下的帳戶信息應該是,何時使用,何時查詢的。 在查詢帳戶時,帳戶的所屬用戶信息應該是隨着帳戶查詢時一塊兒查詢出來。 什麼是延遲加載 在真正使用數據時才發起查詢,不用的時候不查詢。按需加載(懶加載) 什麼是當即加載 無論用不用,只要一調用方法,立刻發起查詢。 在對應的四種表關係中:一對多,多對一,一對一,多對多 一對多,多對多:一般狀況下咱們都是採用延遲加載。 多對一,一對一:一般狀況下咱們都是採用當即加載。
二、Mybatis中的緩存sql
什麼是緩存 存在於內存中的臨時數據。 爲何使用緩存 減小和數據庫的交互次數,提升執行效率。 什麼樣的數據能使用緩存,什麼樣的數據不能使用 適用於緩存: 常常查詢而且不常常改變的。 數據的正確與否對最終結果影響不大的。 不適用於緩存: 常常改變的數據 數據的正確與否對最終結果影響很大的。 例如:商品的庫存,銀行的匯率,股市的牌價。 Mybatis中的一級緩存和二級緩存 一級緩存: 它指的是Mybatis中SqlSession對象的緩存。 當咱們執行查詢以後,查詢的結果會同時存入到SqlSession爲咱們提供一塊區域中。 該區域的結構是一個Map。當咱們再次查詢一樣的數據,mybatis會先去sqlsession中 查詢是否有,有的話直接拿出來用。 當SqlSession對象消失時,mybatis的一級緩存也就消失了。 二級緩存: 它指的是Mybatis中SqlSessionFactory對象的緩存。由同一個SqlSessionFactory對象建立的SqlSession共享其緩存。 二級緩存的使用步驟: 第一步:讓Mybatis框架支持二級緩存(在SqlMapConfig.xml中配置) 第二步:讓當前的映射文件支持二級緩存(在IUserDao.xml中配置) 第三步:讓當前的操做支持二級緩存(在select標籤中配置)
三、Mybatis中的註解開發數據庫
環境搭建 單表CRUD操做(代理Dao方式) 多表查詢操做 緩存的配置
延遲加載:緩存
就是在須要用到數據時才進行加載,不須要用到數據時就不加載數據。延遲加載也稱懶加載.session
好處:先從單表查詢,須要時再從關聯表去關聯查詢,大大提升數據庫性能,由於查詢單表要比關聯查詢多張錶速mybatis
度要快。app
壞處:框架
由於只有當須要用到數據時,纔會進行數據庫查詢,這樣在大批量數據查詢時,由於查詢工做也要消耗ide
時間,因此可能形成用戶等待時間變長,形成用戶體驗降低。性能
需求:
查詢帳戶(Account)信息而且關聯查詢用戶(User)信息。若是先查詢帳戶(Account)信息便可知足要
求,當咱們須要查詢用戶(User)信息時再查詢用戶(User)信息。把對用戶(User)信息的按需去查詢就是延遲加
載。
mybatis第三天實現多表操做時,咱們使用了resultMap來實現一對一,一對多,多對多關係的操做。主要
是經過 association、collection 實現一對一及一對多映射。association、collection 具有延遲加載功
能。
public interface IAccountDao {
/**
* 查詢全部帳戶,同時獲取帳戶的所屬用戶名稱以及它的地址信息
* @return
*/
List<Account> findAll();
}
<?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.itheima.dao.IAccountDao">
<!-- 創建對應關係 -->
<resultMap type="account" id="accountMap">
<id column="id" property="id"/>
<result column="uid" property="uid"/>
<result column="money" property="money"/>
<!-- 它是用於指定從表方的引用實體屬性的 -->
<association property="user" javaType="user"
select="com.itheima.dao.IUserDao.findById"
column="uid">
</association>
</resultMap>
<select id="findAll" resultMap="accountMap">
select * from account
</select>
</mapper>
select: 填寫咱們要調用的 select 映射的 id
column : 填寫咱們要傳遞給 select 映射的參數
* <p>Title: IUserDao</p>
* <p>Description: 用戶的業務層接口</p>
* <p>Company: http://www.itheima.com/ </p>
*/
public interface IUserDao {
/**
* 根據 id 查詢
* @param userId
* @return
*/
User findById(Integer userId);
}
<?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.itheima.dao.IUserDao">
<!-- 根據 id 查詢 -->
<select id="findById" resultType="user" parameterType="int" >
select * from user where id = #{uid}
</select>
</mapper>
/**
*
* <p>Title: MybastisCRUDTest</p>
* <p>Description: 一對多帳戶的操做</p>
* <p>Company: http://www.itheima.com/ </p>
*/
public class AccountTest {
private InputStream in ;
private SqlSessionFactory factory;
private SqlSession session;
private IAccountDao accountDao;
@Test
public void testFindAll() {
//6.執行操做
List<Account> accounts = accountDao.findAll();
}
@Before//在測試方法執行以前執行
public void init()throws Exception {
//1.讀取配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.建立構建者對象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//3.建立 SqlSession 工廠對象
factory = builder.build(in);
//4.建立 SqlSession 對象
session = factory.openSession();
//5.建立 Dao 的代理對象
accountDao = session.getMapper(IAccountDao.class);
}
@After//在測試方法執行完成以後執行
public void destroy() throws Exception{
//7.釋放資源
session.close();
in.close();
}
}
測試結果以下:
咱們發現,由於本次只是將 Account對象查詢出來放入 List 集合中,並無涉及到 User對象,因此就沒有
發出 SQL 語句查詢帳戶所關聯的 User 對象的查詢。
一樣咱們也能夠在一對多關係配置的<collection>結點中配置延遲加載策略。
<collection>結點中也有 select 屬性,column 屬性。
需求:
完成加載用戶對象時,查詢該用戶所擁有的帳戶信息。
/**
*
* <p>Title: User</p>
* <p>Description: 用戶的實體類</p>
* <p>Company: http://www.itheima.com/ </p>
*/
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
private List<Account> accounts;
public List<Account> getAccounts() {
return accounts;
}
public void setAccounts(List<Account> accounts) {
this.accounts = accounts;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", birthday=" + birthday
+ ", sex=" + sex + ", address="
+ address + "]";
}
}
/**
* 查詢全部用戶,同時獲取出每一個用戶下的全部帳戶信息傳智播客——專一於 Java、.Net 和 Php、網頁平面設計工程師的培訓
北京市昌平區建材城西路金燕龍辦公樓一層 電話:400-618-9090
* @return
*/
List<User> findAll();
/**
* 根據用戶 id 查詢帳戶信息
* @param uid
* @return
*/
List<Account> findByUid(Integer uid);
<resultMap type="user" id="userMap">
<id column="id" property="id"></id>
<result column="username" property="username"/>
<result column="address" property="address"/>
<result column="sex" property="sex"/>
<result column="birthday" property="birthday"/>
<!-- collection 是用於創建一對多中集合屬性的對應關係
ofType 用於指定集合元素的數據類型
select 是用於指定查詢帳戶的惟一標識(帳戶的 dao 全限定類名加上方法名稱)
column 是用於指定使用哪一個字段的值做爲條件查詢
-->
<collection property="accounts" ofType="account"
select="com.itheima.dao.IAccountDao.findByUid"
column="id">
</collection>
</resultMap>
<!-- 配置查詢全部操做 -->
<select id="findAll" resultMap="userMap">
select * from user
</select>
<collection>標籤:
主要用於加載關聯的集合對象
select 屬性:
用於指定查詢 account 列表的 sql 語句,因此填寫的是該 sql 映射的 id
column 屬性:
用於指定 select 屬性的 sql 語句的參數來源,上面的參數來自於 user 的 id 列,因此就寫成 id 這一
個字段名了