1 Mybatis教程(一)
學習過的持久層框架:DBUtils , Hibernate
Mybatis就是類似於hibernate的orm持久層框架。
為什么學Mybatis?
- 目前最主流的持久層框架為hibernate與mybatis,而且國內目前情況使用Mybatis的公司比hibernate要多。
- Hibernate學習門檻不低,要精通門檻更高。門檻高在怎么設計O/R映射,在性能和對象模型之間如何權衡取得平衡,以及怎樣用好Hibernate緩存與數據加載策略方面需要你的經驗和能力都很強才行。國內目前前的情況精通hibernate技術大牛非常少。
- sql優化方面,Hibernate的查詢會將表中的所有字段查詢出來,這一點會有性能消耗。當然了,Hibernate也可以自己寫SQL來指定需要查詢的字段,但這樣就破壞了Hibernate開發的簡潔性。說得更深入一些,如果有個查詢要關聯多張表,比如5張表,10張表時,而且,我們要取的字段只是其中幾張表的部分字段。這時用hibernate時就會顯得非常力不從心。就算用hibernate的sqlquery,后續的維護工作也會讓人發狂。
2 JDBC編程回顧與存在的問題分析
2.1 開發步驟:
- 導入數據腳本,在課前資料中有
- 創建工程,導入mysql jar包
- 編碼
- //加載數據庫驅動
- //創建數據庫連接
- //創建statement
- //設置sql語句
- //設置查詢參數
- //執行查詢,得到ResultSet
- //解析結果集ResultSet
- //釋放資源
2.2 Jdbc訪問數據庫的過程:
2.3 Jdbc存在的問題:
- 頻繁創建和打開、關閉數據連接,太消耗資源
- Sql語句存在硬編碼,不利於維護
- Sql參數設置硬編碼,不利於維護
- 結果集獲取與遍歷復雜,存在硬編碼,不利於維護,期望能夠查詢后返回一個java對象
3 Mybatis介紹
MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,並且改名為MyBatis 。2013年11月遷移到Github。
Mybatis是面向sql的持久層框架,他封裝了jdbc訪問數據庫的過程,我們開發,只需專注於sql語句本身的拼裝,其它復雜的過程全部可以交給mybatis去完成。
4 Mybaits入門
4.1 需求列表
根據用戶ID查詢用戶信息
根據用戶名查找用戶列表
添加用戶
修改用戶
刪除用戶
4.2 工程搭建
- 導入依賴jar包。
- 配置SqlMapConfig.xml。
- 配置log4j.properties。
- 編寫pojo到工程目錄下。
- 配置sql查詢的映射文件。
- 加載映射文件。
4.3 完成需求
4.3.1 需求完成步驟
- 編寫sql語句
- 配置user映射文件
- 編寫測試程序
4.3.2 根據用戶ID查詢用戶信息
4.3.2.1 映射文件與sql
<!-- id:statementId resultType:查詢結果集的數據類型 parameterType:查詢的入參 --> <select id="getUserById" parameterType="int" resultType="com.itheima.mybatis.pojo.User" > SELECT * FROM USER WHERE id = #{id1} </select>
4.3.2.2 MyBatis訪問數據庫代碼
@Test public void testGetUserByid() throws IOException { // 創建SqlSessionFactoryBuilder對象 SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder(); // 查找配置文件創建輸入流 InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); // 加載配置文件,創建SqlSessionFactory對象 SqlSessionFactory sqlSessionFactory = sfb.build(inputStream); // 創建SqlSession對象 SqlSession sqlSession = sqlSessionFactory.openSession(); // 執行查詢,參數一:要查詢的statementId ,參數二:sql語句入參 User user = sqlSession.selectOne("user.getUserById", 1); // 輸出查詢結果 System.out.println(user); // 釋放資源 sqlSession.close(); }
4.3.3 抽取SqlSessionFactoryUtils工具類,共享SqlSessionFactory創建過程
/** * SqlSessionFactory工具類 * * @author Steven * */ public class SqlSessionFactoryUtils { /** * 單例SqlSessionFactory */ private static SqlSessionFactory sqlSessionFactory; static { // 創建SqlSessionFactoryBuilder對象 SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder(); try { // 查找配置文件創建輸入流 InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); // 加載配置文件,創建SqlSessionFactory對象 sqlSessionFactory = sfb.build(inputStream); } catch (IOException e) { e.printStackTrace(); } } /** * 獲取單例SqlSessionFactory * @return */ public static SqlSessionFactory getSqlSessionFactory() { return sqlSessionFactory; } }
4.3.4 根據用戶名查找用戶列表
4.3.4.1映射文件與sql
<!-- resultType:如果要返回數據集合,只需設定為每一個元素的數據類型 --> <select id="getUserByName" parameterType="string" resultType="com.itheima.mybatis.pojo.User"> <!-- SELECT * FROM USER WHERE username LIKE #{name} --> SELECT * FROM USER WHERE username LIKE '%${value}%' </select>
4.3.4.2MyBatis訪問數據庫代碼
@Test public void getUserByName() { SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession(); //List<User> users = sqlSession.selectList("user.getUserByName", "%張%"); List<User> users = sqlSession.selectList("user.getUserByName", "張"); for (User user : users) { System.out.println(user); } // 釋放資源 sqlSession.close(); } 4.3.5
添加用戶
4.3.5.1映射文件與sql
<insert id="insertUser" parameterType="com.itheima.mybatis.pojo.User"> INSERT INTO USER (`username`, `birthday`, `sex`, `address`) VALUES (#{username}, #{birthday}, #{sex}, #{address}); </insert>
4.3.5.2MyBatis訪問數據庫代碼
@Test public void testInsertUser() throws IOException { // 創建SqlSession對象 SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession(); User user = new User(); user.setUsername("張飛"); user.setAddress("深圳市黑馬"); user.setBirthday(new Date()); user.setSex("1"); // 執行插入 sqlSession.insert("user.insertUser", user); // 提交事務 sqlSession.commit(); // 釋放資源 sqlSession.close(); }
4.3.5.3Mysql自增返回
<!-- useGeneratedKeys:標識插入使用自增id keyProperty:與useGeneratedKeys配套使用,用於綁定主鍵接收的pojo屬性 --> <insert id="insertUserKey" parameterType="com.itheima.mybatis.pojo.User" useGeneratedKeys="true" keyProperty="id"> <!-- selectKey:用於配置主鍵返回 keyProperty:要綁定的pojo屬性 resultType:屬性數據類型 order:指定什么時候執行,AFTER之后 --> <!-- <selectKey keyProperty="id" resultType="int" order="AFTER"> SELECT LAST_INSERT_ID() </selectKey> --> INSERT INTO USER (`username`, `birthday`, `sex`, `address`, `uuid2`) VALUES (#{username}, #{birthday}, #{sex}, #{address}, #{uuid2}); </insert>
4.3.5.4Mysql的uuid返回主鍵
注:在使用uuid之前數據庫user表要先加上uuid2字段、user的pojo也要加上相應屬性
<!-- useGeneratedKeys:標識插入使用自增id keyProperty:與useGeneratedKeys配套使用,用於綁定主鍵接收的pojo屬性 --> <insert id="insertUserUUID" parameterType="com.itheima.mybatis.pojo.User"> <!-- selectKey:用於配置主鍵返回 keyProperty:要綁定的pojo屬性 resultType:屬性數據類型 order:指定什么時候執行,BEFORE之前 --> <selectKey keyProperty="uuid2" resultType="string" order="BEFORE"> SELECT UUID() </selectKey> INSERT INTO USER (`username`, `birthday`, `sex`, `address`, `uuid2`) VALUES (#{username}, #{birthday}, #{sex}, #{address}, #{uuid2}); </insert>
4.3.6 修改用戶
<update id="updateUser" parameterType="com.itheima.mybatis.pojo.User"> UPDATE USER SET username = #{username} WHERE id = #{id} </update>
4.3.7 刪除用戶
<delete id="deleteUser" parameterType="int"> DELETE FROM `user` WHERE `id` = #{id1} </delete>
4.4 Mybatis入門小結與Mybatis架構圖
5 Mybatis Dao開發方式
5.1 Dao需求
根據用戶ID查詢用戶信息
根據用戶名查找用戶列表
添加用戶
5.2 原始Dao開發方法
5.2.1 使用原有的user映射文件,不需修改
5.2.2 新建個UserDao接口
public interface UserDao { /**根據用戶ID查詢用戶信息 * @param id * @return */ User getUserById(Integer id); /** * 根據用戶名查找用戶列表 * @param name * @return */ List<User> getUserByUserName(String name); /** * 添加用戶 * @param user */ void insertUser(User user); }
5.2.3 新建個UserDaoImpl接口實現類
public class UserDaoImpl implements UserDao { @Override public User getUserById(Integer id) { SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession(); User user = sqlSession.selectOne("user.getUserById", id); sqlSession.close(); return user; } @Override public List<User> getUserByUserName(String name) { SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession(); List<User> list = sqlSession.selectList("user.getUserByName", name); sqlSession.close(); return list; } @Override public void insertUser(User user) { SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession(); sqlSession.insert("user.insertUser", user); sqlSession.commit(); sqlSession.close(); } }
5.2.4 使用dao測試
public class UserDaoTest { @Test public void testGetUserById() { UserDao userDao = new UserDaoImpl(); User user = userDao.getUserById(30); System.out.println(user); } @Test public void testGetUserByUserName() { UserDao userDao = new UserDaoImpl(); List<User> list = userDao.getUserByUserName("張"); for (User user : list) { System.out.println(user); } } @Test public void testInsertUser() { UserDao userDao = new UserDaoImpl(); User user = new User(); user.setUsername("張飛3"); user.setAddress("深圳市黑馬"); user.setBirthday(new Date()); user.setSex("1"); userDao.insertUser(user); } }
5.3 官方推薦,接口動態代理
5.3.1 動態代理dao開發規則
- namespace必需是接口的全路徑名
- 接口的方法名必需與映射文件的sql id一致
- 接口的輸入參數必需與映射文件的parameterType類型一致
- 接口的返回類型必須與映射文件的resultType類型一致
- 創建UserMapper.xml映射文件(把原來的user.xml復制按開發規則要求修改一下)
- 創建UserMapper接口(把原來的UserDao.java復制按開發規則要求修改一下)
- 加載UserMapper.xml
5.3.2 動態代理dao開發步驟
- 測試動態代理Dao
public class UserMapperTest { @Test public void testGetUserById() { // 加載配置得到SqlSession SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession(); // 獲取代理對象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 查詢數據 User user = userMapper.getUserById(30); System.out.println(user); // 關閉資源 sqlSession.close(); } @Test public void testGetUserByUserName() { SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession(); // 獲取代理對象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 查詢數據 List<User> list = userMapper.getUserByName("張"); for (User user : list) { System.out.println(user); } // 關閉資源 sqlSession.close(); } @Test public void testInsertUser() { SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = new User(); user.setUsername("張飛飛"); user.setAddress("深圳市黑馬"); user.setBirthday(new Date()); user.setSex("1"); userMapper.insertUser(user); // 提交事務 sqlSession.commit(); // 關閉資源 sqlSession.close(); } }
6 SqlMapConf.xml配置
6.1 properties
6.1.1 屬性核心文件配置
<!-- 加載規則,首先加載標簽內部屬性,再加載外部文件,名稱相同時,會替換相同名稱的內容 --> <properties resource="jdbc.properties"> <property name="jdbc.username" value="root1"/> <property name="jdbc.password" value="root"/> </properties>
6.1.2 jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root
6.2 typeAliases
mybatis默認支持java基本數據類型的別名識別詳細參考教案。
自定義別名
<typeAliases> <!-- 單個別名定義 --> <!-- <typeAlias type="com.itheima.mybatis.pojo.User" alias="user"/> --> <!-- 別名包掃描器(推薦使用此方式),整個包下的類都被定義別名,別名為類名,不區分大小寫--> <package name="com.itheima.mybatis.pojo"/> </typeAliases>
6.3 mappers
<mappers> <!-- 第一種方式,加載 resource--> <mapper resource="mapper/user.xml"/> <!-- <mapper resource="mapper/UserMapper.xml"/> --> <!-- 第二種方式,class掃描器要求: 1、映射文件與接口同一目錄下 2、映射文件名必需與接口文件名稱一致 --> <!-- <mapper class="com.itheima.mybatis.mapper.UserMapper"/> --> <!-- 第三種方式,包掃描器要求(推薦使用此方式): 1、映射文件與接口同一目錄下 2、映射文件名必需與接口文件名稱一致 --> <package name="com.itheima.mybatis.mapper"/> </mappers>

