您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)MyBatis的知識點(diǎn)有哪些,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
初期的 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>
對于基礎(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); }
執(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=uid
將 order
的uid
作為參數(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)簽 |
---|---|
@Select | select |
@Results | resultMap |
@Result | id和<result |
@One | association |
執(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=id
將 User
的id
作為參數(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> |
執(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=id
將 User
的id
作為參數(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)簽 |
---|---|
@Select | select |
@Results | resultMap |
@Result | id和result |
@Many | collection |
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元素。
Mybatis 使用到了兩種緩存:本地緩存(local cache)和二級緩存(second level cache)。 兩個(gè)緩存的關(guā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í)清空。
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(); }
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(); }
總結(jié):
1)第一次查詢用戶的時(shí)候,會(huì)在一級緩存中去查詢用戶信息,如果查詢不到就去數(shù)據(jù)庫中查詢。并將查詢到的結(jié)果更新到以及緩存中。
2)如果同一個(gè)SqlSession中執(zhí)行了commit事務(wù)提交操作(增加、更新、刪除),那么就會(huì)清空SqlSession中的緩存信息,避免下次查詢的時(shí)候出現(xiàn)臟數(shù)據(jù)。
3)第二次查詢的時(shí)候同樣去一級緩存查詢,如果有值就獲取返回,如果沒有就查詢數(shù)據(jù)庫并添加到一級緩存中。
二級緩存和一級緩存原理類似,只不過緩存的級別更高而已。一級緩存針對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>
基于上訴流程測試二級緩存
@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(); }
關(guān)于“MyBatis的知識點(diǎn)有哪些”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學(xué)到更多知識,如果覺得文章不錯(cuò),請把它分享出去讓更多的人看到。
免責(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)容。