Java面試-框架篇(SSM-Mybatis)


這篇博客個人內容主要整理自http://www.cnblogs.com/wang-meng/p/5701990.html 和 http://blog.csdn.net/eaphyy/article/details/71190441 

只作為我個人學習之用

 

1、#{}和${}的區別是什么?  

#{}是預編譯處理,${}是字符串替換。 Mybatis在處理#{}時,會將sql中的#{}替換為?號,調用PreparedStatement的set方法來賦值; Mybatis在處理${}時,就是把${}替換成變量的值。 使用#{}可以有效的防止SQL注入,提高系統安全性。

2、當實體類中的屬性名和表中的字段名不一樣 ,怎么辦 ? 

第1種: 通過在查詢的sql語句中定義字段名的別名,讓字段名的別名和實體類的屬性名一致
1 <select id=”selectorder” parametertype=”int” resultetype=”me.gacl.domain.order”> 
2        select order_id id, order_no orderno ,order_price price form orders where order_id=#{id}; 3     </select> 
第2種: 通過<resultMap>來映射字段名和實體類屬性名的一一對應的關系
 1  <select id="getOrder" parameterType="int" resultMap="orderresultmap">
 2         select * from orders where order_id=#{id}  3     </select>
 4    <resultMap type=”me.gacl.domain.order” id=”orderresultmap”> 
 5         <!–用id屬性來映射主鍵字段–> 
 6         <id property=”id” column=”order_id”> 
 7         <!–用result屬性來映射非主鍵字段,property為實體類屬性名,column為數據表中的屬性–> 
 8         <result property = “orderno” column =”order_no”/> 
 9         <result property=”price” column=”order_price” /> 
10     </reslutMap>

3、 模糊查詢like語句該怎么寫?  

第1種:在Java代碼中添加sql通配符。

1  string wildcardname = “%smi%”; 2     list<name> names = mapper.selectlike(wildcardname); 3 
4     <select id=”selectlike”> 
5      select * from foo where bar like #{value} 6     </select>
第2種:在sql語句中拼接通配符,會引起sql注入
1 string wildcardname = “smi”; 2     list<name> names = mapper.selectlike(wildcardname); 3 
4     <select id=”selectlike”> 
5      select * from foo where bar like "%"#{value}"%"
6     </select>
 
        

4、通常一個Xml映射文件,都會寫一個Dao接口與之對應,請問,這個Dao接口的工作原理是什么?Dao接口里的方法,參數不同時,方法能重載嗎?

 
        
Dao接口,就是人們常說的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,接口方法內的參數,

就是傳遞給sql的參數。


Mapper接口是沒有實現類的,

當調用接口方法時,接口全限名+方法名拼接字符串作為key值,可唯一定位一個MappedStatement,

舉例:com.mybatis3.mappers.StudentDao.findStudentById,

可以唯一找到namespace為com.mybatis3.mappers.StudentDao下面id = findStudentById的MappedStatement。

在Mybatis中,每一個<select>、<insert>、<update>、<delete>標簽,都會被解析為一個MappedStatement對象。 Dao接口里的方法,是不能重載的,因為是全限名+方法名的保存和尋找策略。 Dao接口的工作原理是JDK動態代理,Mybatis運行時會使用JDK動態代理為Dao接口生成代理proxy對象,代理對象proxy會攔截接口方法,

轉而執行MappedStatement所代表的sql,然后將sql執行結果返回。
 
        

5、Mybatis是如何進行分頁的?分頁插件的原理是什么? 

Mybatis使用RowBounds對象進行分頁,它是針對ResultSet結果集執行的內存分頁,而非物理分頁,

可以在sql內直接書寫帶有物理分頁的參數來完成物理分頁功能,也可以使用分頁插件來完成物理分頁。 分頁插件的基本原理是使用Mybatis提供的插件接口,實現自定義插件,在插件的攔截方法內攔截待執行的sql,

然后重寫sql,根據dialect方言,添加對應的物理分頁語句和物理分頁參數。

6、Mybatis是如何將sql執行結果封裝為目標對象並返回的?都有哪些映射形式? 

第一種是使用<resultMap>標簽,逐一定義列名和對象屬性名之間的映射關系。

第二種是使用sql列的別名功能,將列別名書寫為對象屬性名,比如T_NAME AS NAME,對象屬性名一般是name,小寫,

但是列名不區分大小寫,Mybatis會忽略列名大小寫,智能找到與之對應對象屬性名,你甚至可以寫成T_NAME AS NaMe,Mybatis一樣可以正常工作。 有了列名與屬性名的映射關系后,Mybatis通過反射創建對象,同時使用反射給對象的屬性逐一賦值並返回,那些找不到映射關系的屬性,是無法完成賦值的。

7、如何執行批量插入?

  首先,創建一個簡單的insert語句: 

1 <insert id=”insertname”> 
2  insert into names (name) values (#{value}) 3  </insert>
然后在java代碼中像下面這樣執行批處理插入: 
 1 list<string> names = new arraylist();  2  names.add(“fred”);  3  names.add(“barney”);  4  names.add(“betty”);  5  names.add(“wilma”);  6 
 7     // 注意這里 executortype.batch 
 8     sqlsession sqlsession = sqlsessionfactory.opensession(executortype.batch);  9     try { 10      namemapper mapper = sqlsession.getmapper(namemapper.class); 11      for (string name : names) { 12  mapper.insertname(name); 13  } 14  sqlsession.commit(); 15     } finally { 16  sqlsession.close(); 17     }

8、如何獲取自動生成的(主)鍵值?

insert 方法總是返回一個int值 - 這個值代表的是插入的行數。 而自動生成的鍵值在 insert 方法執行完后可以被設置到傳入的參數對象中。 示例: 
 1 <insert id=”insertname” usegeneratedkeys=”true” keyproperty=”id”> 
 2  insert into names (name) values (#{name})  3     </insert>
 4 
 5     name name = new name();  6  name.setname(“fred”);  7 
 8     int rows = mapper.insertname(name);  9     // 完成后,id已經被設置到對象中 
10     system.out.println(“rows inserted = ” + rows); 11     system.out.println(“generated key value = ” + name.getid());

9、在mapper中如何傳遞多個參數? 

第1種:
1 //DAO層的函數
2 
3 Public UserselectUser(String name,String area); 4 
5 //對應的xml,#{0}代表接收的是dao層中的第一個參數,#{1}代表dao層中第二參數,更多參數一致往后加即可。
6 
7 <select id="selectUser"resultMap="BaseResultMap">  
8     select *  fromuser_user_t   whereuser_name = #{0} anduser_area=#{1} 9 </select> 
第2種:使用 @param 注解: 
1 import org.apache.ibatis.annotations.param; 2         public interface usermapper { 3  user selectuser(@param(“username”) string username, 4  @param(“hashedpassword”) string hashedpassword); 5         }
然后,就可以在xml像下面這樣使用(推薦封裝為一個map,作為單個參數傳遞給mapper):
1 <select id=”selectuser” resulttype=”user”> 
2  select id, username, hashedpassword 3  from some_table 4          where username = #{username} 5          and hashedpassword = #{hashedpassword} 6     </select>

10、Mybatis動態sql是做什么的?都有哪些動態sql?能簡述一下動態sql的執行原理不?

Mybatis動態sql可以讓我們在Xml映射文件內,以標簽的形式編寫動態sql,完成邏輯判斷和動態拼接sql的功能。 Mybatis提供了9種動態sql標簽:trim|where|set|foreach|if|choose|when|otherwise|bind。 其執行原理為,使用OGNL從sql參數對象中計算表達式的值,根據表達式的值動態拼接sql,以此來完成動態sql的功能。

11、Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重復?

不同的Xml映射文件,如果配置了namespace,那么id可以重復;如果沒有配置namespace,那么id不能重復;畢竟namespace不是必須的,只是最佳實踐而已。 原因就是namespace+id是作為Map<String, MappedStatement>的key使用的,如果沒有namespace,就剩下id,

那么,id重復會導致數據互相覆蓋。有了namespace,自然id就可以重復,namespace不同,namespace+id自然也就不同。

12、為什么說Mybatis是半自動ORM映射工具?它與全自動的區別在哪里? 

Hibernate屬於全自動ORM映射工具,使用Hibernate查詢關聯對象或者關聯集合對象時,可以根據對象關系模型直接獲取,所以它是全自動的。

而Mybatis在查詢關聯對象或關聯集合對象時,需要手動編寫sql來完成,所以,稱之為半自動ORM映射工具。

13、 一對一、一對多的關聯查詢 ?

 1 <mapper namespace="com.lcb.mapping.userMapper">  
 2     <!--association  一對一關聯查詢 -->  
 3     <select id="getClass" parameterType="int" resultMap="ClassesResultMap">  
 4         select * from class c,teacher t where c.teacher_id=t.t_id and c.c_id=#{id}  5     </select>  
 6     <resultMap type="com.lcb.user.Classes" id="ClassesResultMap">  
 7         <!-- 實體類的字段名和數據表的字段名映射 -->  
 8         <id property="id" column="c_id"/>  
 9         <result property="name" column="c_name"/>  
10         <association property="teacher" javaType="com.lcb.user.Teacher">  
11             <id property="id" column="t_id"/>  
12             <result property="name" column="t_name"/>  
13         </association>  
14     </resultMap>  
15 
16     <!--collection  一對多關聯查詢 -->  
17     <select id="getClass2" parameterType="int" resultMap="ClassesResultMap2">  
18         select * from class c,teacher t,student s where c.teacher_id=t.t_id and c.c_id=s.class_id and c.c_id=#{id} 19     </select>  
20     <resultMap type="com.lcb.user.Classes" id="ClassesResultMap2">  
21         <id property="id" column="c_id"/>  
22         <result property="name" column="c_name"/>  
23         <association property="teacher" javaType="com.lcb.user.Teacher">  
24             <id property="id" column="t_id"/>  
25             <result property="name" column="t_name"/>  
26         </association>  
27         <collection property="student" ofType="com.lcb.user.Student">  
28             <id property="id" column="s_id"/>  
29             <result property="name" column="s_name"/>  
30         </collection>  
31     </resultMap>  
32 
33 </mapper>  

 

  補充內容

1.JDBC編程有哪些不足之處,MyBatis是如何解決這些問題的?

① 數據庫鏈接創建、釋放頻繁造成系統資源浪費從而影響系統性能,如果使用數據庫鏈接池可解決此問題。
解決:在SqlMapConfig.xml中配置數據鏈接池,使用連接池管理數據庫鏈接。

② Sql語句寫在代碼中造成代碼不易維護,實際應用sql變化的可能較大,sql變動需要改變java代碼。
解決:將Sql語句配置在XXXXmapper.xml文件中與java代碼分離。

③ 向sql語句傳參數麻煩,因為sql語句的where條件不一定,可能多也可能少,占位符需要和參數一一對應。
解決: Mybatis自動將java對象映射至sql語句。

④ 對結果集解析麻煩,sql變化導致解析代碼變化,且解析前需要遍歷,如果能將數據庫記錄封裝成pojo對象解析比較方便。
解決:Mybatis自動將sql執行結果映射至java對象。

2.MyBatis編程步驟是什么樣的?

① 創建SqlSessionFactory 
② 通過SqlSessionFactory創建SqlSession 
③ 通過sqlsession執行數據庫操作 
④ 調用session.commit()提交事務 
⑤ 調用session.close()關閉會話

3.MyBatis與Hibernate有哪些不同? 

Mybatis和hibernate不同,它不完全是一個ORM框架,因為MyBatis需要程序員自己編寫Sql語句,不過mybatis可以通過XML或注解方式靈活配置要運行的sql語句,

並將java對象和sql語句映射生成最終執行的sql,最后將sql執行的結果再映射生成java對象。 Mybatis學習門檻低,簡單易學,程序員直接編寫原生態sql,可嚴格控制sql執行性能,靈活度高,非常適合對關系數據模型要求不高的軟件開發,

例如互聯網軟件、企業運營類軟件等,因為這類軟件需求變化頻繁,一但需求變化要求成果輸出迅速。但是靈活的前提是mybatis無法做到數據庫無關性,

如果需要實現支持多種數據庫的軟件則需要自定義多套sql映射文件,工作量大。 Hibernate對象
/關系映射能力強,數據庫無關性好,對於關系模型要求高的軟件(例如需求固定的定制化軟件)如果用hibernate開發可以節省很多代碼,提高效率。


但是Hibernate的缺點是學習門檻高,要精通門檻更高,而且怎么設計O/R映射,在性能和對象模型之間如何權衡,以及怎樣用好Hibernate需要具有很強的經驗和能力才行。
總之,按照用戶的需求在有限的資源環境下只要能做出維護性、擴展性良好的軟件架構都是好架構,所以框架只有適合才是最好。

4.使用MyBatis的mapper接口調用時有哪些要求? 

①  Mapper接口方法名和mapper.xml中定義的每個sql的id相同 
②  Mapper接口方法的輸入參數類型和mapper.xml中定義的每個sql 的parameterType的類型相同 
③  Mapper接口方法的輸出參數類型和mapper.xml中定義的每個sql的resultType的類型相同 
④  Mapper.xml文件中的namespace即是mapper接口的類路徑。

5.SqlMapConfig.xml中配置有哪些內容?

SqlMapConfig.xml中配置的內容和順序如下: 
properties(屬性)
settings(配置)
typeAliases(類型別名)
typeHandlers(類型處理器)
objectFactory(對象工廠)
plugins(插件)
environments(環境集合屬性對象)
environment(環境子屬性對象)
transactionManager(事務管理)
dataSource(數據源)
mappers(映射器)

6.簡單的說一下MyBatis的一級緩存和二級緩存? 

Mybatis首先去緩存中查詢結果集,如果沒有則查詢數據庫,如果有則從緩存取出返回結果集就不走數據庫。

Mybatis內部存儲緩存使用一個HashMap,key為hashCode+sqlId+Sql語句。value為從查詢出來映射生成的java對象 Mybatis的二級緩存即查詢緩存,它的作用域是一個mapper的namespace,即在同一個namespace中查詢sql可以從緩存中獲取數據。二級緩存是可以跨SqlSession的。

7.Mapper編寫有哪幾種方式?  

①接口實現類繼承SqlSessionDaoSupport

    使用此種方法需要編寫mapper接口,mapper接口實現類、mapper.xml文件

1、在sqlMapConfig.xml中配置mapper.xml的位置 <mappers>
    <mapper resource="mapper.xml文件的地址" />
    <mapper resource="mapper.xml文件的地址" />
</mappers>
 
2、定義mapper接口 3、實現類集成SqlSessionDaoSupport mapper方法中可以this.getSqlSession()進行數據增刪改查。 4、spring 配置 <bean id=" " class="mapper接口的實現">
    <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>

②使用org.mybatis.spring.mapper.MapperFactoryBean

 

1、在sqlMapConfig.xml中配置mapper.xml的位置 如果mapper.xml和mappre接口的名稱相同且在同一個目錄,這里可以不用配置 <mappers>
    <mapper resource="mapper.xml文件的地址" />
    <mapper resource="mapper.xml文件的地址" />
</mappers>
 
2、定義mapper接口 注意 1、mapper.xml中的namespace為mapper接口的地址 2、mapper接口中的方法名和mapper.xml中的定義的statement的id保持一致 3、 Spring中定義 <bean id="" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="mapperInterface"   value="mapper接口地址" /> 
    <property name="sqlSessionFactory" ref="sqlSessionFactory" /> 
</bean>

 

③使用mapper掃描器

1、mapper.xml文件編寫, 注意: mapper.xml中的namespace為mapper接口的地址 mapper接口中的方法名和mapper.xml中的定義的statement的id保持一致 如果將mapper.xml和mapper接口的名稱保持一致則不用在sqlMapConfig.xml中進行配置 2、定義mapper接口 注意mapper.xml的文件名和mapper的接口名稱保持一致,且放在同一個目錄 3、配置mapper掃描器 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="mapper接口包地址"></property>
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> 
</bean>
4、使用掃描器后從spring容器中獲取mapper的實現對象 掃描器將接口通過代理方法生成實現對象,要spring容器中自動注冊,名稱為mapper 接口的名稱。


免責聲明!

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



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