MyBatis總結(筆面試題)
目錄
10.呼叫sqlSession.selectOne()還是SQLSession.selectList()是由mapper介面的返回值決定的
11.Mapper介面的引數:簡單型別,pojo型別包裝型別,Map,List集合等
23.Statement和PrepareStatement的區別
Mybatis
1.談談MyBatis
Mybatis是一個優秀的持久層框架,它對jdbc的操作資料庫的過程進行封裝,使得開發者只需要專注於SQL語句本身,而不用去關心註冊驅動,建立connection等,Mybatis通過xml檔案配置或者註解的方式將要執行的各種statement配置起來,並通過java物件和statement中的sql進行對映成最終執行的sql語句,最後由Mybatis框架執行sql並將結果對映成java物件並返回。
2.Mybatis分為三層
(1)API介面層:提供給外部使用的介面API
(2)資料處理層:負責具體的SQL
(3)基礎支撐層:負責最基礎的功能支撐,如連線管理,事務管理,配置載入和快取處理
3.Mybatis和jdbc的區別
相比與jdbc,Mybatis具有以下優點
(1)資料庫連結建立,釋放頻繁造成系統資源浪費會影響系統性能,使用資料庫可以解決
解決:在核心配置檔案SqlMapConfig.xml中配置資料鏈接池,使用資料鏈接池管理資料庫連結
(2)Sql寫在程式碼中不易於維護,修改需要變動java程式碼
在對映檔案XXXMapper.xml檔案中配置sql語句與Java程式碼分離
(3)向Sql語句傳輸引數麻煩,因為Sql語句的WHERE條件不一定,可能多也可能少,佔位符需要和引數一一對應
Mybatis可以自動將Java物件對映到sql語句
(4)對結果集解析麻煩,sql變化導致解析程式碼變化,且解析前需要遍歷,將資料庫記錄封裝成pojo物件解析更加方便
Mybatis可以自動將sql執行結果對映到Java物件
4.對映檔案
<mapper name="text">
<select id="FindByID" paramenterType="int" resultType="com.guigu.User">
select * from user where id=#{id}
</select>
</mapper>
namespace:名稱空間 id:根據id執行sql parameterType:入參 resultType:出參 #{id} 接收的引數
5.模糊查詢:LIKE
<selectid="findByName2"
parameterType="java.lang.String" resultType="com.gugiu.model.User">
select * from user where name like '%${value}%'
</select>
修改
<update id="updateUserById" parameterType="com.gugiu.model.User">
update user set name = #{name},age =#{age},address=#{address}
where id =#{id}
</update>
6.$和#的區別
(1)#把傳入的引數當做字串處理 $表示直接顯示
(2)#很大程度防止Sql注入(語句拼接)
(3)能用#儘量用#
7.主鍵自增
8.API
(1)SqlSessionFactoryBuilder
通過載入MyBatisde 核心配置檔案,建立SqlSessionFactory
(2)SqlSessionFactory
定義了openSession的不同過載方法
(3)sqlSession
定義了資料庫的操作,增刪改查
9.SqlSession不是執行緒安全的
10.呼叫sqlSession.selectOne()還是SQLSession.selectList()是由mapper介面的返回值決定的
List<User> findUserByName(String name); selectList()
User findUserByName(String name); selectOne()
11.Mapper介面的引數:簡單型別,pojo型別包裝型別,Map,List集合等
12.指定別名
單個檔案
<typeAliases>
<typeAlias type="com.gugiu.model.User" alias="user"/>
</typeAliases>
批量
<typeAliases>
<package name="com.guigu.model1"/>
<package name="com.guigu.model2"/>
</typeAliases>
13.隱射檔案的載入
單個檔案
<mappers>
<!—載入單個對映檔案-->
<mapper resource="com/guigu/mapper/UserMapper.xml"/>
</mappers>
批量
<mappers>
<package name="com.guigu.mapper"/>
</mappers>
14.輸入引數
(1)簡單型別
<select id="findById" parameterType="int" resultType="user" >
select * from User where id = #{id} ;
</select>
(2)pojo型別
<insert id="addUser" parameterType="com.guigu.model.User">
<selectKey keyColumn="id" order="AFTER" resultType="int">
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTO user (name,age,address)
VALUE(#{name},#{age},#{address})
</insert>
(3)pojo的包裝型別
<select id="findById" parameterType="com.guigu.model.UserVo" resultType="user">
select * from User where id = #{user.id} ;
</select>
(4)Map
<insert id="addUserMap" parameterType="hashmap">
INSERT INTO my_user(NAME,age,address) VALUE(#{name},#{age},#{address})
</insert>
15.只寫map的
<selectid="findById" parameterType="int" resultMap="userMap">
SELECT id ,name user_name FROM my_user WHERE id = #{id}
</select>
16.動態sql的編寫
(1)if
<insert id="addUserVo" parameterType="com.guigu.mybatis.pojo.UserVo">
<if test="user != null">
insert into my_user (name,age,address)
value(#{user.name},#{user.age},#{user.address})
</if>
</insert>
(2)where
<select id="findByUserVo" parameterType="UserVo"resultType="User">
select * from my_user
<where>
<iftest="user!= null">
<if test="user.id != null and user.id !='' ">
and id = #{user.id}
</if>
<if test="user.name != null and user.name !='' ">
and name like '%#{user.name}%'
</if>
</if>
</where>
</select>
(3)sql程式碼片段
<sql id="find_user_byId">
<if test="user.id != null and user.id !='' ">
and id = #{user.id}
</if>
</sql>
<sql id="find_user_byAge">
<if test="user.age != null and user.age !='' ">
and age = #{user.age}
</if>
</sql>
<select id="findByUserVo" parameterType="UserVo" resultType="User">
select * from my_user
<where>
<if test="user!= null">
<include ref id="find_user_byId"></include>
<include ref id="find_user_byAge"></include>
</if>
</where>
</select>
(4)foreach
<insert id="addUsers" parameterType="map">
insert into my_user (name,age,address)
<if test="users != null">
values
<foreach collection="users" item="user" separator=",">
(#{user.name},#{user.age},#{user.address})
</foreach>
</if>
</insert>
<select id="findByIds" parameterType="map" resultType="User">
<if test="userIds != null">
select * from my_user
<where>
<foreach collection="userIds" item="userId" separator="or">
id = #{userId}
</foreach>
</where>
</if>
</select>
17.快取
(1)一級快取(SqlSession級別)
MyBatis一級快取的作用域是同一個SqlSession,在同一個sqlSession中兩次執行
相同的sql語句,第一次執行後會將查詢到的資料儲存到快取當中,第二次會從緩
存中進行查詢,從而提高查詢效率,當一個SqlSession結束之後,一級快取也將不
存在,Mybatis預設開啟一級快取。
(2)二級快取(Mapper級別)
二級快取的作用域是mapper的同一個namespace,執行兩次相同的SQL語句,第一次執行後會將查詢到的資料儲存到快取當中,第二次會從快取中進行查詢,從而提高查詢效率,預設不開啟。
18.Mybatis的程式設計步驟
(0)建立SqlSessionFactoryBuilder
(1)通過SqlsesionFactoryBuilder建立sqlSessionFactory
(2)通過SqlSessionFactory建立sqlSession
(3)通過sqlSession執行資料庫操作
(4)呼叫session.commit()提交事務
(5)呼叫session.close()關閉會話
publicclass MyBatisUtil {
privatestatic SqlSessionFactory factory = null;
static {
try {
SqlSessionFactoryBuilder builder = newSqlSessionFactoryBuilder();
InputStream inputStream = Resources.getResourceAsStream("MyBatisConfig.xml");
//建立Session工廠
factory = builder.build(inputStream);
} catch (Exception e) {
e.printStackTrace();
}
}
publicstatic SqlSession getSqlSession(){
//獲得session會話
return factory.openSession();
}
}
19.主鍵自增問題
20.實體類中的屬性名和資料表中的列名不一致
(1)在sql語句中使用別名
(2)事先指定對映關係,這樣Mybatis也能自動完成對映。Mybatis提供了resultMap標籤
<resultMap type="User" id="UserResultMap">
<id column="id" property="id"/>
<result column="user_name" property="userName"/>
<result column="user_password" property="userPassword"/>
</resultMap>
- Mybatis提供了一個全域性屬性mapUnderscoreToCamelCase來解決兩者名字不一致的問題。
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
21.如何獲取自動生成的(主)鍵值
解決思路:通過LAST_INSERT_ID()獲取剛插入記錄的自增主鍵值,在insert語句執行後,執行select LAST_INSERT_ID()就可以獲取自增主鍵。
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<selectKey keyProperty="id" order="AFTER" resultType="int">
select LAST_INSERT_ID()
</selectKey>
INSERT INTO USER(username,birthday,sex,address)
VALUES(#{username},#{birthday},#{sex},#{address)
</insert>
22.使用MyBatis的mapper介面呼叫有哪些要求?
(1)Mapper介面方法名和mapper.xml中定義的每個sql的id相同
(2)Mapper介面中輸入的引數型別和mapper.xml中定義的每個sql的ParameterType相同
(3)Mapper介面中輸出的引數型別和mapper.xml中定義的每個sql的resultType相同
(4)Mapper.xml檔案中的namespace即是介面的類路徑
23.Statement和PrepareStatement的區別
PreparedStatement:表示預編譯的 SQL 語句的物件。
(1)PrepareStatement可以使用佔位符,是預編譯的,批處理比Statement效率高
(2)在對資料庫只執行一次性存取的時侯,用 Statement 物件進行處理。
(3)PreparedStatement的第一次執行消耗是很高的. 它的效能體現在後面的重複執行