溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

MyBatis的知識點(diǎn)有哪些

發(fā)布時(shí)間:2021-12-30 09:52:30 來源:億速云 閱讀:201 作者:小新 欄目:大數(shù)據(jù)

這篇文章將為大家詳細(xì)講解有關(guān)MyBatis的知識點(diǎn)有哪些,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。


4.1 注解模式開發(fā)

初期的 MyBatis 是一個(gè) XML 驅(qū)動(dòng)的框架。配置信息是基于 XML 的,映射語句也是定義在 XML 中的。而在 MyBatis 3 中,提供了其它的配置方式。MyBatis 3 構(gòu)建在全面且強(qiáng)大的基于 Java 語言的配置 API 之上。它是 XML 和注解配置的基礎(chǔ)。注解提供了一種簡單且低成本的方式來實(shí)現(xiàn)簡單的映射語句。

提示: Java 注解的表達(dá)能力和靈活性十分有限。盡管MyBatis團(tuán)隊(duì)花了很多時(shí)間在調(diào)查、設(shè)計(jì)和試驗(yàn)上,但最強(qiáng)大的 MyBatis 映射并不能用注解來構(gòu)建。

經(jīng)驗(yàn)對于單表的操作使用注解更加便利,但是對于復(fù)雜的多表,使用注解模式就顯得難以維護(hù)建議使用XML。

常用注解

注解用途
@Insert新增
@Update更新
@Delete刪除
@Select查詢
@Result封裝結(jié)果集
@Results與@Result配合,封裝多個(gè)結(jié)果集
@One實(shí)現(xiàn)一對一結(jié)果集封裝
@Many實(shí)現(xiàn)一對多結(jié)果集封裝

以下的查詢案例和要求均和XML模式一致,只是將xml操作替換為注解操作

對于注解的查詢操作是不需要Mapper.xml配置文件的,因?yàn)閟ql的配置和結(jié)果映射都通過注解實(shí)現(xiàn)了

SqlMapConfig.xml更新

<mappers>
    <!-- 注解方式Mapper的信息已經(jīng)在接口中使用功能注解實(shí)現(xiàn),所以掃描接口解析注解獲取 -->
    <package name="com.zyj.mapper"/>
</mappers>
4.1.1簡單操作

對于基礎(chǔ)的單表新增、更新、查詢、刪除操作如下,sql語句和xml一致,這里不多介紹。

public interface UserMapper {

    // 新增
    @Insert(value = "insert into user(id, username, `password`, birthday) values (#{id}, #{username}, #{password}, #{birthday})")
    void addUser(User user);

    // 更新
    @Update(value = "update user set username = #{username}, `password` = #{password}, birthday = #{birthday} where id = #{id}")
    void updateUser(User user);

    // 查詢
    @Select(value = "select * from user")
    List<User> selectAll();

    // 刪除
    @Delete(value = "delete from user where id = #{id}")
    void deleteUser(Integer id);

}
4.1.2 一對一查詢

執(zhí)行過程:

1)執(zhí)行@Select標(biāo)簽的sql語句。

2)執(zhí)行@Results標(biāo)簽的語句封裝@Select的查詢結(jié)果。

3)封裝結(jié)果的時(shí)候有一個(gè)屬性是user ,內(nèi)部的one屬性關(guān)聯(lián)到了另外一個(gè)查詢結(jié)果。所以就會(huì)去UserMapper中執(zhí)行selectById 根據(jù) column=uidorderuid作為參數(shù)去查詢結(jié)果。

// 訂單一對一查詢
public interface OrdersMapper {

    // select * from orders o left join user u on o.uid = u.id
    @Results({
            @Result(property = "id", column = "id"),
            @Result(property = "ordertime", column = "ordertime"),
            @Result(property = "total", column = "total"),
            @Result(
                    javaType = User.class,
                    property = "user",
                    column = "uid",
                    one = @One(select = "com.zyj.mapper.UserMapper.selectById"))
    })
    @Select(value = "select * from orders")
    List<Order> findAllOrderAndUser();

}
// 用戶查詢
public interface UserMapper {
    @Select(value = "select * from user where id = #{id}")
    User selectById(Integer id);
}

注解和標(biāo)簽對應(yīng)關(guān)系總結(jié):

注解標(biāo)簽
@Selectselect
@ResultsresultMap
@Resultid和<result
@Oneassociation
4.1.3 一對多查詢

執(zhí)行過程:

1)執(zhí)行@Select標(biāo)簽的sql語句。

2)執(zhí)行@Results標(biāo)簽的語句封裝@Select的查詢結(jié)果。

3)封裝結(jié)果的時(shí)候有一個(gè)屬性是orderList ,內(nèi)部的Many屬性關(guān)聯(lián)到了另外一個(gè)查詢結(jié)果。所以就會(huì)去OrderMapper中執(zhí)行selectByUId 根據(jù) column=idUserid作為參數(shù)去查詢結(jié)果。

// 用戶查詢一對多
public interface UserMapper {
    // select * from user u left join orders o on u.id = o.uid;
    @Results({
            @Result(property = "id", column = "id"),
            @Result(property = "username", column = "username"),
            @Result(property = "password", column = "password"),
            @Result(property = "birthday", column = "birthday"),
            @Result(
                    property = "orderList",
                    column = "id",
                    javaType = List.class,
                    many = @Many(select = "com.zyj.mapper.OrdersMapper.selectByUId")
            )
    })
    @Select(value = "select * from user")
    List<User> findAllUserAndOrder();
}
// 根據(jù)用戶id查詢用戶訂單
public interface OrdersMapper {
    // 根據(jù)用戶id返回查詢結(jié)果
    @Select(value = "select * from orders where uid = #{uid}")
    List<Order> selectByUId(Integer uid);
}

注解和標(biāo)簽對應(yīng)關(guān)系總結(jié):

注解標(biāo)簽
@Select<select>
@Results<resultMap>
@Result<id>和<result>
@Many<collection>
4.1.4多對多查詢

執(zhí)行過程:

1)執(zhí)行@Select標(biāo)簽的sql語句。

2)執(zhí)行@Results標(biāo)簽的語句封裝@Select的查詢結(jié)果。

3)封裝結(jié)果的時(shí)候有一個(gè)屬性是roleList ,內(nèi)部的Many屬性關(guān)聯(lián)到了另外一個(gè)查詢結(jié)果。所以就會(huì)去RoleMapper中執(zhí)行selectByUserId 根據(jù) column=idUserid作為參數(shù)去查詢結(jié)果。

public interface UserMapper {
    // select * from user u left join sys_user_role ur on u.id = ur.userid left join sys_role r on ur.roleid = r.id;
    @Results({
            @Result(property = "id", column = "id"),
            @Result(property = "username", column = "username"),
            @Result(property = "password", column = "password"),
            @Result(property = "birthday", column = "birthday"),
            @Result(
                    property = "roleList",
                    column = "id",
                    javaType = List.class,
                    many = @Many(select = "com.zyj.mapper.RoleMapper.selectByUserId")
            )
    })
    @Select(value = "select * from user")
    List<User> findAllUserAndRole();
}
// 根據(jù)用戶id查詢角色
public interface RoleMapper {
    @Select(value = "select r.* from sys_role r inner join sys_user_role ur on r.id = ur.roleid where userid = #{uid}")
    List<Role> selectByUserId(Integer uid);
}

注解和標(biāo)簽對應(yīng)關(guān)系總結(jié):

注解標(biāo)簽
@Selectselect
@ResultsresultMap
@Resultid和result
@Manycollection
4.1.5 注解的動(dòng)態(tài)SQL

MyBatis提供的動(dòng)態(tài)Sql標(biāo)簽在注解模式中也是一樣適用,但是寫法和剛才的一對一一對多、多對多 的查詢有所差異。作用和效果是一樣的。所以這里只給出一個(gè)案例即可。

    @Update({"<script>",
      "update Author",
      "  <set>",
      "    <if test='username != null'>username=#{username},</if>",
      "    <if test='password != null'>password=#{password},</if>",
      "    <if test='email != null'>email=#{email},</if>",
      "    <if test='bio != null'>bio=#{bio}</if>",
      "  </set>",
      "where id=#{id}",
      "</script>"})
    void updateAuthorValues(Author author);

如果想在注解的映射器接口中使用動(dòng)態(tài)SQL,那么可以使用script元素。

4.2 緩存機(jī)制
	Mybatis 使用到了兩種緩存:本地緩存(local cache)和二級緩存(second level cache)。 兩個(gè)緩存的關(guān)系如下圖:

MyBatis的知識點(diǎn)有哪些

每當(dāng)一個(gè)新 session 被創(chuàng)建,MyBatis 就會(huì)創(chuàng)建一個(gè)與之相關(guān)聯(lián)的本地緩存。任何在 session 執(zhí)行過的查詢結(jié)果都會(huì)被保存在本地緩存中,所以,當(dāng)再次執(zhí)行參數(shù)相同的相同查詢時(shí),就不需要實(shí)際查詢數(shù)據(jù)庫了。本地緩存將會(huì)在做出修改、事務(wù)提交或回滾,以及關(guān)閉 session 時(shí)清空。

4.2.1 驗(yàn)證一級緩存

1)在同一個(gè)sqlSession中,對User用戶表根據(jù)id進(jìn)行2次查詢,觀察控制臺的sql打印情況。

@Test
public void test1(){
	// 獲取一個(gè)sqlSession
	SqlSession sqlSession = sessionFactory.openSession();
	UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
	// 使用sqlSession執(zhí)行第一次查詢
	User u1 = userMapper.selectUserByUserId(1);
	System.out.println(u1);
	// 使用sqlSession執(zhí)行第二次查詢
	User u2 = userMapper.selectUserByUserId(1);
	System.out.println(u2);
	sqlSession.close();
}

MyBatis的知識點(diǎn)有哪些

2)在同一個(gè)sqlSession中,對User用戶表根據(jù)id進(jìn)行2次查詢。但是,中間對查詢到的用戶執(zhí)行Update更新操作,并提交事務(wù),觀察控制臺的sql打印情況。

@Test
public void test2(){
	// 獲取一個(gè)sqlSession
	SqlSession sqlSession = sessionFactory.openSession();
	UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
	// 使用sqlSession執(zhí)行第一次查詢
	User u1 = userMapper.selectUserByUserId( 1 );
	System.out.println(u1);
	// 第二次查詢之前執(zhí)行更新操作并提交事務(wù)
    u1.setSex("女");
	userMapper.updateUserByUserId(u1);
	sqlSession.commit();
	// 使用sqlSession執(zhí)行第二次查詢
	User u2 = userMapper.selectUserByUserId(1);
	System.out.println(u2);
	sqlSession.close();
}

MyBatis的知識點(diǎn)有哪些

總結(jié):

1)第一次查詢用戶的時(shí)候,會(huì)在一級緩存中去查詢用戶信息,如果查詢不到就去數(shù)據(jù)庫中查詢。并將查詢到的結(jié)果更新到以及緩存中。

2)如果同一個(gè)SqlSession中執(zhí)行了commit事務(wù)提交操作(增加、更新、刪除),那么就會(huì)清空SqlSession中的緩存信息,避免下次查詢的時(shí)候出現(xiàn)臟數(shù)據(jù)。

3)第二次查詢的時(shí)候同樣去一級緩存查詢,如果有值就獲取返回,如果沒有就查詢數(shù)據(jù)庫并添加到一級緩存中。

4.2.2 驗(yàn)證二級緩存

二級緩存和一級緩存原理類似,只不過緩存的級別更高而已。一級緩存針對sqlSession,但是二級緩存就針對Mapper文件。所以二級緩存可以被多個(gè)sqlSession共享。

二級緩存和一級緩存不一樣,一級緩存默認(rèn)都是開啟的,二級緩存默認(rèn)是關(guān)閉的。所以需要配置開啟。二級緩存的開啟需要配置2個(gè)地方。

  • 總開關(guān)開啟二級緩存SqlMapConfig.xml配置文件開啟。

<!-- 二級緩存總開關(guān) -->
<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>
  • 由于二級緩存是Mapper級別的緩存,所以可以針對單個(gè)Mapper配置是否需要開啟。

<!--對應(yīng)的Mapper.xml開啟二級緩存。如:UserMapper.xml、OrderMapper.xml-->
<cache></cache>

MyBatis的知識點(diǎn)有哪些

基于上訴流程測試二級緩存

@Test
public` `void` `testTwoCache(){
	// 獲取sqlSession
	SqlSession sqlSession1 = sessionFactory.openSession();
	SqlSession sqlSession2 = sessionFactory.openSession();
	SqlSession sqlSession3 = sessionFactory.openSession();
    
	String statement = "com.zyj.UserMapper.selectById" ;
	UserMapper userMapper1 = sqlSession1.getMapper(UserMapper. class );
	UserMapper userMapper2 = sqlSession2.getMapper(UserMapper. class );
	UserMapper userMapper3 = sqlSession2.getMapper(UserMapper. class );
    
	// 第一次執(zhí)行查詢,結(jié)果會(huì)放入二級緩存中
	User u1 = userMapper1.selectById( 1 );
	System.out.println(u1);
	sqlSession1.close(); // 關(guān)閉第一個(gè)session
	// 執(zhí)行更新操作,并提交
	u1.setUsername("知春秋");
	userMapper3.selectById(u1);
	sqlSession3.commit();
    
    // 第二次查詢,由于更新操作導(dǎo)致二級緩存被更新,所以會(huì)重新查詢數(shù)據(jù)庫
	User u2 = userMapper2.selectById( 1 );
	System.out.println(u2);
    sqlSession2.close();
}
4.3 MyBatis學(xué)習(xí)思維導(dǎo)圖(提供參考)

MyBatis的知識點(diǎn)有哪些

4.4 MyBatis源碼剖析思維導(dǎo)圖(提供參考)

MyBatis的知識點(diǎn)有哪些

關(guān)于“MyBatis的知識點(diǎn)有哪些”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學(xué)到更多知識,如果覺得文章不錯(cuò),請把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI