mybatis 詳細學習記錄
MyBatis是什麼?
MyBatis 本是apache的一個開源專案iBatis, 2010年這個專案由apache software foundation 遷移到了google code,並且改名為MyBatis,實質上Mybatis對ibatis進行一些改進。 目前mybatis在github上託管。 git(分散式版本控制,當前比較流程)
MyBatis是一個優秀的持久層框架,它對jdbc的操作資料庫的過程進行封裝,使開發者只需要關注 SQL 本身,而不需要花費精力去處理例如註冊驅動、建立connection、建立statement、手動設定引數、結果集檢索等jdbc繁雜的過程程式碼。
Mybatis通過xml或註解的方式將要執行的各種statement(statement、preparedStatemnt、CallableStatement)配置起來,並通過java物件和statement中的sql進行對映生成最終執行的sql語句,最後由mybatis框架執行sql並將結果對映成java物件並返回。
mybatis架構
搭建開發環境
(1)導包
(2)匯入配置檔案
這裡我在工程檔案下新建了一個和src平級的檔案,把有關mybatis配置檔案和src檔案分離,看去介面更加清晰,因為在ssh開發中你肯定還要配置其它配置檔案
這裡的log4j.properties主要是為了在後臺輸出是更加看的清楚執行流程,這個可要可不要.
(3)配需相關檔案屬性
User.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- namespace名稱空間,為了對sql語句進行隔離,方便管理 ,mapper開發dao方式,使用namespace有特殊作用 --> <mapper namespace="test"> <!-- 在mapper.xml檔案中配置很多的sql語句,執行每個sql語句時,封裝為MappedStatement物件 mapper.xml以statement為單位管理sql語句 --> <!-- 根據id查詢使用者資訊 --> <!-- id:唯一標識 一個statement #{}:表示 一個佔位符,如果#{}中傳入簡單型別的引數,#{}中的名稱隨意 parameterType:輸入 引數的型別,通過#{}接收parameterType輸入 的引數 resultType:輸出結果 型別,不管返回是多條還是單條,指定單條記錄對映的pojo型別 --> <select id="findUserById" parameterType="int" resultType="com.study.model.User"> SELECT * FROM USER WHERE id= #{id} </select> <!-- 根據使用者名稱稱查詢使用者資訊,可能返回多條 ${}:表示sql的拼接,通過${}接收引數,將引數的內容不加任何修飾拼接在sql中。 --> <select id="findUserByName" parameterType="java.lang.String" resultType="com.study.model.User"> select * from user where username like '%${value}%' </select> <!-- 新增使用者 parameterType:輸入 引數的型別,User物件 包括 username,birthday,sex,address #{}接收pojo資料,可以使用OGNL解析出pojo的屬性值 #{username}表示從parameterType中獲取pojo的屬性值 selectKey:用於進行主鍵返回,定義了獲取主鍵值的sql order:設定selectKey中sql執行的順序,相對於insert語句來說 keyProperty:將主鍵值設定到哪個屬性 resultType:select LAST_INSERT_ID()的結果 型別 --> <insert id="insertUser" parameterType="com.study.model.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> <!-- 使用者刪除 --> <delete id="deleteUser" parameterType="int"> delete from user where id=#{id} </delete> <!-- 使用者更新 要求:傳入的user物件中包括 id屬性值 --> <update id="updateUser" parameterType="com.study.model.User"> update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id} </update> </mapper>
SqlMapConfig.xml
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 和spring整合後 environments配置將廢除--> <environments default="development"> <environment id="development"> <!-- 使用jdbc事務管理--> <transactionManager type="JDBC" /> <!-- 資料庫連線池--> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="root" /> </dataSource> </environment> </environments> <!-- 載入mapper.xml --> <mappers> <mapper resource="sqlmap/User.xml" /> </mappers> </configuration>
User.java
public class User { private int id; private String username;// 使用者姓名 private String sex;// 性別 private Date birthday;// 生日 private String address;// 地址 /* *提供set和get方法,和toString方法 * */ }
MybatisFirst 測試類,進行增刪改查
import java.io.IOException; import java.io.InputStream; import java.util.Date; import java.util.List; 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 org.junit.Before; import org.junit.Test; import com.guigu.model.User; public class MybatisFirst { // 會話工廠 private SqlSessionFactory sqlSessionFactory; // 建立工廠 @Before //before在text標籤之前執行,所以會建立好sqlSessionFactory物件 public void init() throws IOException { // 配置檔案(SqlMapConfig.xml) String resource = "SqlMapConfig.xml"; // 載入配置檔案到輸入 流 InputStream inputStream = Resources.getResourceAsStream(resource); // 建立會話工廠 sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } // 根據id查詢使用者(得到單條記錄) @Test public void testFindUserById() { // 通過sqlSessionFactory建立sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 通過sqlSession操作資料庫 // 第一個引數:statement的位置,等於namespace+statement的id // 第二個引數:傳入的引數 User user = sqlSession.selectOne("test.findUserById", 16); sqlSession.close(); System.out.println(user); } // 模糊查詢(可能是單條也可能是多條) @Test public void testFindUserByName() { // 通過sqlSessionFactory建立sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //selectList代表著返回是list集合 List<User> list = sqlSession.selectList("test.findUserByName", "小明"); sqlSession.close(); System.out.println(list.get(0).getUsername()); } // 新增使用者 @Test public void testInsertUser() { // 通過sqlSessionFactory建立sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); User user = new User(); user.setUsername("小小徐"); user.setAddress("杭州市餘杭區未來科技城"); user.setBirthday(new Date()); user.setSex("1"); //insert代表插入 sqlSession.insert("test.insertUser", user); //檢視是不需要提交事物的,但是插入和修改是需要提交事物的 sqlSession.commit(); sqlSession.close(); //這裡輸出的id竟然是0,有哪位大神解釋下嗎? System.out.println("使用者的id=" + user.getId()); }
// 根據id刪除使用者 @Test public void testDeleteUser() { // 通過sqlSessionFactory建立sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // delete代表刪除使用者 sqlSession.delete("test.deleteUser", 29); sqlSession.commit(); sqlSession.close(); } // 根據id更新使用者 @Test public void testUpdateUser() { // 通過sqlSessionFactory建立sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 建立更新資料物件,要求必須包括 id User user = new User(); user.setId(40); user.setUsername("小小鐘"); user.setAddress("杭州餘杭區東西大道"); //user.setBirthday(new Date()); user.setSex("1"); //update更新資料 sqlSession.update("test.updateUser", user); sqlSession.commit(); sqlSession.close(); System.out.println("使用者的id=" + user.getId()); } }
mybatis與hibernate重要區別
企業開發進行技術選型 ,考慮mybatis與hibernate適用場景。
mybatis:入門簡單,程式容易上手開發,節省開發成本 。mybatis需要程式設計師自己編寫sql語句,是一個不完全 的ORM框架,對sql修改和優化非常容易實現 。
mybatis適合開發需求變更頻繁的系統,比如:網際網路專案。
hibernate:入門門檻高,如果用hibernate寫出高效能的程式不容易實現。hibernate不用寫sql語句,是一個 ORM框架。
hibernate適合需求固定,物件資料模型穩定,中小型專案,比如:企業OA系統。
總之,企業在技術選型時根據專案實際情況,以降低成本和提高系統 可維護性為出發點進行技術選型。
總結
SqlMapConfig.xml
是mybatis全域性配置檔案,只有一個,名稱不固定的,主要mapper.xml,mapper.xml中配置 sql語句
mapper.xml
mapper.xml是以statement為單位進行配置。(把一個sql稱為一個statement),satatement中配置 sql語句、parameterType輸入引數型別(完成輸入對映)、resultType輸出結果型別(完成輸出對映)。還提供了parameterMap配置輸入引數型別(過期了,不推薦使用了),還提供resultMap配置輸出結果型別(完成輸出對映)
#{}
表示一個佔位符,向佔位符輸入引數,mybatis自動進行java型別和jdbc型別的轉換。程式設計師不需要考慮引數的型別,比如:傳入字串,mybatis最終拼接好的sql就是引數兩邊加單引號。#{}接收pojo資料,可以使用OGNL解析出pojo的屬性值
${}
表示sql的拼接,通過${}接收引數,將引數的內容不加任何修飾拼接在sql中。${}也可以接收pojo資料,可以使用OGNL解析出pojo的屬性值
缺點:不能防止sql注入。
selectOne
用於查詢單條記錄,不能用於查詢多條記錄,否則異常:
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 4
selectList
用於查詢多條記錄,可以用於查詢單條記錄的。