MyBatis筆試題


1請寫出Mybatis核心配置文件MyBatis-config.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文件 獲取連接四要素-->
<properties resource="jdbc.properties"/>


<settings>
<!-- 全局性地啟用或禁用延遲加載。當禁用時,所有關聯的配置都會立即加載。 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!--當啟用后,一個有延遲加載屬性的對象的任何一個延遲屬性被加載時,該對象
的所有的屬性都會被加載。否則,所有屬性都是按需加載。 -->
<setting name="aggressiveLazyLoading" value="false"/>
<!--全局關閉2級緩存 -->
<!--<setting name="cacheEnabled" value="false"/>-->

</settings>


<!--創建類的別名-->
<typeAliases>
<!--只要是在mapper.xml文件中使用了cn.pb.bean包下面的任意類的時候,無需再用全類名
使用簡寫的類名
之前應該 cn.pb.bean.Student
現在 Student
-->
<package name="cn.pb.bean"/>
</typeAliases>


<!--設置mybatis運行環境 default默認的運行環境====environment id的屬性值-->
<environments default="mysql">
<environment id="mysql">
<!--配置事務管理器-->
<transactionManager type="JDBC"></transactionManager>
<!--配置數據源 POOLED:mybatis自帶的數據源-->
<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>

<!--配置需要的mapper文件-->
<mappers>
<mapper resource="mapper/StudentMapper.xml"/>
</mappers>
</configuration>

 

2請寫出Mybatis框架的優缺點?

 

優點:

 

1. 易於上手和掌握。

 

2. sql寫在xml里,便於統一管理和優化。

 

3. 解除sql與程序代碼的耦合。

 

4. 提供映射標簽,支持對象與數據庫的orm字段關系映射

 

5. 提供對象關系映射標簽,支持對象關系組建維護

 

6. 提供xml標簽,支持編寫動態sql。

 

缺點:

 

1. sql工作量很大,尤其是字段多、關聯表多時,更是如此。

 

2. sql依賴於數據庫,導致數據庫移植性差。

 

3. 由於xml里標簽id必須唯一,導致DAO中方法不支持方法重載。

 

4. 字段映射標簽和對象關系映射標簽僅僅是對映射關系的描述,具體實現仍然依賴於sql。(比如配置了一對多Collection標簽,如果sql里沒有join子表或查詢子表的話,查詢后返回的對象是不具備對象關系的,即Collection的對象為null)

 

5. DAO層過於簡單,對象組裝的工作量較大。

 

6.  不支持級聯更新、級聯刪除。

 

7. 編寫動態sql時,不方便調試,尤其邏輯復雜時。

 

8 提供的寫動態sql的xml標簽功能簡單(連struts都比不上),編寫動態sql仍然受限,且可讀性低。

 

9. 若不查詢主鍵字段,容易造成查詢出的對象有“覆蓋”現象。

 

10. 參數的數據類型支持不完善。(如參數為Date類型時,容易報沒有get、set方法,需在參數上加@param)

 

11. 多參數時,使用不方便,功能不夠強大。(目前支持的方法有map、對象、注解@param以及默認采用012索引位的方式)

 

12. 緩存使用不當,容易產生臟數據。

 

 

 

總結:

 

mybatis的優點其實也是mybatis的缺點,正因為mybatis使用簡單,數據的可靠性、完整性的瓶頸便更多依賴於程序員對sql的使用水平上了。sql寫在xml里,雖然方便了修改、優化和統一瀏覽,但可讀性很低,調試也非常困難,也非常受限,無法像jdbc那樣在代碼里根據邏輯實現復雜動態sql拼接。mybatis簡單看就是提供了字段映射和對象關系映射的jdbc,省去了數據賦值到對象的步驟而已,除此以外並無太多作為,不要把它想象成hibernate那樣強大,簡單小巧易用上手,方便瀏覽修改sql就是它最大的優點了。

 

mybatis適用於小型且程序員能力較低的項目和人群使用,對於中大型項目來說我並不推薦使用,如果覺得hibernate效率低的話(實際上也是使用不當所致,hibernate是實際上是不適用於擁有高負載的工程項目),還不如直接用spring提供的jdbc簡單框架(Template),同樣支持對象映射。

 

3.什么是數據持久化以及ORM?

 

01.數據持久化的概念
  數據持久化就是將內在中的數據模型轉換為存儲模型,以及將存儲模型轉換為內在中的數據模型的統稱,數據模型可以是任何數據結構或對象模型,例如JavaBean對象;存儲模型可以是關系型數據庫表,XML文件,二進制文件等.
02.什么是ORM
  ORM(Object/Relational Mapping)中文翻譯為對象/關系型數據映射,它也可以理解為一種數據持久化技術,其主要是把對象模型,例如JavaBean對象和關系型數據庫的表建立對應關系,並且提供了一個通過JavaBean對象去操作數據庫表的機制.
03.使用ORM技術的好處
  在實際開發中,程序員使用面向對象的技術操作數據,而當要把數據存儲起來時,使用的卻是關系型數據庫,這樣就造成了很多的不便,ORM在對象模型和關系數據庫的表之間建立了一座橋梁,有了它,程序員就不需要再使用SQL語句操作數據庫中的表,直接操作JavaBean對象就可以實現數據的存儲,查詢,更改和刪除等操作,Hibernate就是這樣一種技術.

 

4請寫出MybatisUtil工具類

 

package cn.pb.util;

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 java.io.IOException;
import java.io.InputStream;

public class SessionFactoryUtil {
//01.創建需要單例的對象實例
private static SqlSessionFactory sessionFactory;


//02.私有化構造
private SessionFactoryUtil(){}

/**
* 03.對外提供訪問的接口
* 001.SqlSession的創建依賴SqlSessionFactory
* 002.SqlSessionFactory依賴於SqlSessionFactoryBuilder
* 003.SqlSessionFactoryBuilder依賴於配置文件
* 004.獲取配置文件
*/
public static synchronized SqlSession getSession(){
//給我一個文件 返回一個輸入流 到 內存中
try {
InputStream stream = Resources.getResourceAsStream("mybatis.xml");
//判斷SqlSessionFactory是否為空
if (sessionFactory==null){
sessionFactory=new SqlSessionFactoryBuilder().build(stream);
}
} catch (IOException e) {
e.printStackTrace();
}
/**
* 之前還需要寫一個finally用來關閉流! 現在不需要 為什么不需要??
* 01.查詢源碼build(stream)
* 02.SqlSessionFactoryBuilder類中已經關閉reader.close()
* 03.所以我們如果關閉流 會報錯!
*/
return sessionFactory.openSession(); //創建session返回
}
}

 

5.請使用association節點實現根據用戶id查詢用戶信息以及對應角色信息(Role實體類中有一個對象User,只寫SQL映射文件)?

 

 <!-- 01. 根據角色id 查詢出角色信息-->
<select id="selectRoleById" resultMap="roleMap">
select id,name,userid from role where id=#{xxx}
</select>

<!-- 02. 根據角色表中查詢結果中的userid 查詢用戶信息
xxx就是resultmap中傳遞來的 userid-->
<select id="selectUserByUserId" resultType="User">
select userid,name from user where userid=#{xxx}
</select>

<!--對應的roleMap 這種方式 推薦使用 因為使用延遲加載-->
<resultMap id="rolrMap" type="Role">
<id property="id" column="id"/>
<result property="name" column="name"/>
<!-- Role有一個屬性的類型是 user 域屬性
javaType:域屬性對應的類型 -->
<association property="user" javaType="User" select="selectUserByUserId"
column="userid"/>
</resultMap>

 

6.請使用collection節點實現獲取指定用戶的相關信息和地址列表(User實體類中有一個復雜類型的Address集合,只寫SQL映射文件)?

 

<!-- 01. 根據用戶id 查詢出用戶信息-->
<select id="selectUserById" resultMap="userMap">
select id,name from user where id=#{xxx}
</select>

<!-- 02. 根據用戶表中查詢結果中的userid 查詢地址信息
xxx就是resultmap中傳遞來的 userid-->
<select id="selectAddressByUserId" resultType="Address">
select id,name,userid from address where userid=#{xxx}
</select>

<!--對應的userMap 這種方式 推薦使用 因為使用延遲加載-->
<resultMap id="userMap" type="User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<!-- User有一個屬性的類型是 list
javaType:域屬性對應的類型 -->
<collection property="addresses" javaType="Address" select="selectAddressByUserId"
column="userid"/>
</resultMap>

 

7.MyBatis的一級緩存緩存的是什么,二級緩存緩存的是什么?

 

mybatis的一級緩存:
  MyBatis會在表示會話的SqlSession對象中建立一個簡單的緩存,將每次查詢到的結果結果緩存起來,
當下次查詢的時候,如果判斷先前有個完全一樣的查詢,會直接從緩存中直接將結果取出,返回給用戶,
不需要再進行一次數據庫查詢了。

 

  MyBatis會在一次會話的表示----一個SqlSession對象中創建一個本地緩存(local cache),
對於每一次查詢,都會嘗試根據查詢的條件去本地緩存中查找是否在緩存中,如果在緩存中,
就直接從緩存中取出,然后返回給用戶;否則,從數據庫讀取數據,將查詢結果存入緩存並返回給用戶。

 

  一級緩存是SqlSession級別的緩存。在操作數據庫時需要構造 sqlSession對象,在對象中有一個(內存區域)數據結構(HashMap)用於存儲緩存數據。不同的sqlSession之間的緩存數據區域(HashMap)是互相不影響的。

 

  一級緩存的作用域是同一個SqlSession,在同一個sqlSession中兩次執行相同的sql語句,第一次執行完畢會將數據庫中查詢的數據寫到緩存(內存),第二次會從緩存中獲取數據將不再從數據庫查詢,從而提高查詢效率。當一個sqlSession結束后該sqlSession中的一級緩存也就不存在了。Mybatis默認開啟一級緩存。

 

  二級緩存是mapper級別的緩存,多個SqlSession去操作同一個Mapper的sql語句,多個SqlSession去操作數據庫得到數據會存在二級緩存區域,多個SqlSession可以共用二級緩存,二級緩存是跨SqlSession的。

 

  二級緩存是多個SqlSession共享的,其作用域是mapper的同一個namespace,不同的sqlSession兩次執行相同namespace下的sql語句且向sql中傳遞參數也相同即最終執行相同的sql語句,第一次執行完畢會將數據庫中查詢的數據寫到緩存(內存),第二次會從緩存中獲取數據將不再從數據庫查詢,從而提高查詢效率。Mybatis默認沒有開啟二級緩存需要在setting全局參數中配置開啟二級緩存。

 

如果緩存中有數據就不用從數據庫中獲取,大大提高系統性能。

 

8.如何開啟MyBatis的二級緩存?

 

一個項目中肯定會存在很多共用的查詢數據,對於這一部分的數據,沒必要

 

每一個用戶訪問時都去查詢數據庫,因此配置二級緩存將是非常必要的。 

 

Mybatis的二級緩存配置相當容易,要開啟二級緩存,只需要在你的Mapper映射文件中添加一行:

 

<cache />   

 

配置完<cache/>表示該mapper映射文件中,所有的select語句都將被緩存,所有的insert、update和delete語句都將刷新緩存。但是實際中,我們並不是希望這樣,有些select不想被緩存時,可以添加select的屬性useCache=“false”;有些insert、update和delete不想讓他刷新緩存時,添加屬性flushCache=”false ”。

 

9.請根據商品名稱(模糊查詢),供應商,以及是否付款進行多條件查詢和分頁(只寫SQL映射文件)

10.#{}和${}的區別是什么?

 

01.$ 不安全 底層實現是Statement對象

select * from student where id=${id}

如果我們id傳入的是11 編譯之后

select * from student where id=11

# 安全 底層實現是PreparedStatement對象

select * from student where id=#{id}

如果我們id傳入的是11 編譯之后

select * from student where id=?

MyBatis啟用了預編譯功能,在SQL執行前,會先將上面的SQL發送給數據庫進行編譯;

執行時,如果傳入參數為#{}格式的,將傳入參數替換編譯好的sql中的占位符“?”;

如果傳入參數格式為${},則直接使用編譯好的SQL就可以了。

因為SQL注入只能對編譯過程起作用,所以使用#{}傳入參數的方式可以很好地避免了SQL注入的問題。

02.在sql語句需要排序的時候

order by ${id}

只有在需要排序的時候 使用$ 

其他時候能用#絕對不用$。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM