1.1 什麼是Mybatis MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,並且改名為MyBatis 。iBATIS一詞來源於“internet”和“abatis”的組合,是一個 ...
一. 什麼是Mybatis
MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,並且改名為MyBatis 。iBATIS一詞來源於“internet”和“abatis”的組合,是一個基於Java的持久層框架。iBATIS提供的持久層框架包括SQL Maps和Data Access Objects(DAO)。
MyBatis參考資料官網:https://mybatis.github.io/mybatis-3/zh/index.html。
官網對Mybatis的介紹更加具有權威性:
- MyBatis 是支持定製化SQL、存儲過程以及高級映射的優秀的持久層框架。
- MyBatis 避免了幾乎所有的 JDBC 代碼和手工設置參數以及抽取結果集。
- MyBatis 使用簡單的 XML 或註解來配置和映射基本體,將介面和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對象)映射成資料庫中的記錄。
MyBatis優點:
1)、簡單易學
mybatis本身就很小且簡單。沒有任何第三方依賴,最簡單安裝只要兩個jar文件+配置幾個sql映射文件易於學習,易於使用,通過文檔和源代碼,可以比較完全的掌握它的設計思路和實現。
2)、靈活
mybatis不會對應用程式或者資料庫的現有設計強加任何影響。 sql寫在xml里,便於統一管理和優化。通過sql基本上可以實現我們不使用數據訪問框架可以實現的所有功能,或許更多。
3)、解除sql與程式代碼的耦合
通過提供DAL層,將業務邏輯和數據訪問邏輯分離,使系統的設計更清晰,更易維護,更易單元測試。sql和代碼的分離,提高了可維護性。對開發人員而言,核心sql還是需要自己優化:sql和java編碼分開,功能邊界清晰,一個專註業務、 一個專註數據。
4)、提供映射標簽,支持對象與資料庫的orm欄位關係映射。
5)、提供對象關係映射標簽,支持對象關係組建維護。
6)、提供xml標簽,支持編寫動態sql。
MyBatis缺點:
1)、編寫SQL語句時工作量很大,尤其是欄位多、關聯表多時,更是如此。
2)、SQL語句依賴於資料庫,導致資料庫移植性差,不能更換資料庫。
3)、框架還是比較簡陋,功能尚有缺失,雖然簡化了數據綁定代碼,但是整個底層資料庫查詢實際還是要自己寫的,工作量也比較大,而且不太容易適應快速資料庫修改。
MyBatis與JDBC比較:
SQL夾在Java代碼塊里,耦合度高導致硬編碼內傷,維護不易且實際開發需求中sql是有變化,頻繁修改的情況多見。
MyBatis與Hibernate和JPA比較:
長難複雜SQL,對於Hibernate而言處理也不容易,內部自動生產的SQL,不容易做特殊優化。基於全映射的全自動框架,大量欄位的POJO進行部分映射時比較困難。 導致資料庫性能下降。
MyBatis與iBatis比較:
MyBatis是iBatis的升級版,用法有很多的相似之處,但是MyBatis進行了重要的改進。
1)、Mybatis實現了介面綁定,使用更加方便。
在ibatis2.x中我們需要在DAO的實現類中指定具體對應哪個xml映射文件, 而Mybatis實現了DAO介面與xml映射文件的綁定,自動為我們生成介面的具體實現,使用起來變得更加省事和方便。
2)、對象關係映射的改進,效率更高。
3)、MyBatis採用功能強大的基於OGNL的表達式來消除其他元素。
二. 開發第一個Mybatis查詢
1.新建一個java工程
2.添加jar包,如下圖:
3.新建包,管理代碼
4.建庫,建表
1 DROP TABLE IF EXISTS `t_user`; 2 CREATE TABLE `t_user` ( 3 `t_id` int(11) NOT NULL AUTO_INCREMENT, 4 `t_username` varchar(20) NOT NULL, 5 `t_password` varchar(8) NOT NULL, 6 PRIMARY KEY (`t_id`) 7 ) 8 9 -- ---------------------------- 10 -- Records of t_user 11 -- ---------------------------- 12 INSERT INTO `t_user` (t_username,t_password) VALUES ( 'lisi', '123456'); 13 INSERT INTO `t_user` (t_username,t_password) VALUES ( 'wanger', '654321'); 14 INSERT INTO `t_user` (t_username,t_password) VALUES ( '李四', '123123'); 15 INSERT INTO `t_user` (t_username,t_password) VALUES ( '王二', '321321');
5.在src目錄下添加全局配置文件config.xml和log4j.xml文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 <configuration> 6 <!-- 7 default="development" 開發環境 8 default="work" 發佈環境 9 --> 10 11 <environments default="development"> 12 13 <environment id="development"> 14 15 <!-- 配置事物 --> 16 <transactionManager type="JDBC"></transactionManager> 17 18 <!-- 配置數據源 --> 19 <dataSource type="POOLED"> 20 <property name="driver" value="com.mysql.jdbc.Driver"/> 21 <property name="url" value="jdbc:mysql://192.168.61.22:3306/test" /> 22 <property name="username" value="root"/> 23 <property name="password" value="123456"/> 24 25 </dataSource> 26 27 </environment> 28 29 </environments> 30 31 32 </configuration>
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> 3 4 <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> 5 6 <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"> 7 <param name="Encoding" value="UTF-8" /> 8 <layout class="org.apache.log4j.PatternLayout"> 9 <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" /> 10 </layout> 11 </appender> 12 <logger name="java.sql"> 13 <level value="debug" /> 14 </logger> 15 <logger name="org.apache.ibatis"> 16 <level value="info" /> 17 </logger> 18 <root> 19 <level value="debug" /> 20 <appender-ref ref="STDOUT" /> 21 </root> 22 </log4j:configuration>
6.編寫java實體類,生成set,get方法
1 public class User { 2 3 private Integer id; 4 private String username; 5 private String password; 6 7 } 8
7.編寫sql映射文件---------------mapper文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > 3 4 <!-- 配置SQL語句,與實體類操作的對應關係。 --> 5 <!-- 保證唯一性 --> 6 <mapper namespace="com.softjx.model.UserMapper"> 7 8 <!-- 9 將返回的數據 與對象對應。將返回的數據,按照配置組裝成對應的對象。 10 --> 11 <select id="selectAll" resultType="com.softjx.model.User"> 12 select t_id as id,t_username as username,t_password password from t_user 13 </select> 14 15 <select id="selectById" resultType="com.softjx.model.User"> 16 select t_id as id,t_username as username,t_password password from t_user where t_id=#{id}; 17 </select> 18 19 </mapper>
8.在全局配置文件中添加mapper文件的位置
<!-- 導入映射文件 --> <mappers> <mapper resource="com/softjx/model/UserMapper.xml" /> </mappers>
9.編寫測試代碼:
1 public class TestMybatis { 2 private SqlSession session; 3 4 @Before 5 public void read() throws Exception { 6 // 構建mybatis的執行對象 7 FileInputStream fis = new FileInputStream("src/config.xml"); 8 SqlSession session = new SqlSessionFactoryBuilder().build(fis) 9 .openSession(); 10 11 // InputStream inputStream = 12 // Resources.getResourceAsStream("config.xml"); 13 // SqlSession session = new 14 // SqlSessionFactoryBuilder().build(inputStream).openSession(); 15 this.session = session; 16 } 17 18 @Test 19 public void TestSelectAll() { 20 System.out.println("查詢所有用戶"); 21 try { 22 List<User> users = session 23 .selectList("com.softjx.model.UserMapper.selectAll");// 根據字元找sql語句 24 25 for (User user : users) { 26 System.out.println(user.getId() + " " + user.getUsername() 27 + " " + user.getPassword()); 28 } 29 } finally { 30 session.close(); 31 } 32 33 } 34 35 @Test 36 public void TestSelectById() { 37 System.out.println("查詢所有用戶"); 38 try { 39 User user = session 40 .selectOne("com.softjx.model.UserMapper.selectById",2);// 根據字元找sql語句 41 42 System.out.println(user.getId() + " " + user.getUsername() + " " 43 + user.getPassword()); 44 45 } finally { 46 session.close(); 47 } 48 49 } 50 51 }
10.SqlSession
SqlSession 的實例不是線程安全的,因此是不能被共用的。
SqlSession每次使用完成後需要正確關閉,這個關閉操作是必須的。
三. 第一個Mybatis程式出錯地方
1.全局配置文件沒有指定mapper文件。
2.資料庫配置出錯。
3.jdbc驅動沒有載入。
4.select 查詢語句沒有轉化javabean中屬性。
5.全局配置文件路徑不對。
6.log4j.xml文件沒有。
7.id名稱寫錯了。
四.Mybatis添加,修改,刪除
Mapper.xml文件的添加,修改,刪除
1 <insert id="insertUser"> 2 insert into t_user (t_username,t_password) 3 values (#{username},#{password}) 4 </insert> 5 6 <update id="updateUser"> 7 update t_user set 8 t_username = #{username}, 9 t_password = #{password} 10 where t_id = #{id} 11 </update> 12 13 <delete id="deleteUser"> 14 delete from t_user where t_id = #{id} 15 </delete>
測試添加,修改,刪除
1 @Test 2 public void TestInserUser() { 3 System.out.println("添加一個用戶"); 4 try { 5 User user=new User(); 6 user.setUsername("pkd"); 7 user.setPassword("888888"); 8 int count=session.insert("com.softjx.model.UserMapper.insertUser",user);// 根據字元找sql語句 9 session.commit(); 10 System.out.println(count); 11 } finally { 12 session.close(); 13 } 14 15 } 16 17 18 19 @Test 20 public void TestUpdateUser() { 21 System.out.println("更新一個用戶"); 22 try { 23 User user=new User(); 24 user.setId(1); 25 user.setUsername("pkd"); 26 user.setPassword("888888"); 27 int count=session.update("com.softjx.model.UserMapper.updateUser",user);// 根據字元找sql語句 28 session.commit(); 29 System.out.println(count); 30 } finally { 31 session.close(); 32 } 33 34 } 35 36 37 38 @Test 39 public void TestDeleteUser() { 40 System.out.println("更新一個用戶"); 41 try { 42 int count=session.delete("com.softjx.model.UserMapper.deleteUser",1);// 根據字元找sql語句 43 session.commit(); 44 System.out.println(count); 45 } finally { 46 session.close(); 47 } 48 49 }
五. Mybatis介面式編程CRUD
- 編寫介面文件,作為dao層,只有定義介面,沒有實現,其實現交給mapper.xml文件。
- 編寫mapper.xml,註意其命名空間要是介面的路徑。
- mapper.xml文件中sql語句與以前一樣。
- 測試代碼中使用介面的代理類對象,調用介面中的方法,實現數據處理。使用SqlSession獲取映射器進行操作
介面代碼:
1 public interface UserMapper { 2 3 4 //查詢所有用戶 5 public List<User> selectAll(); 6 7 //查詢所有用戶 8 public List<User> selectAll1(); 9 10 //查詢一個用戶 11 public User selectById(Integer id); 12 13 //添加用戶 14 public int insertUser(User user); 15 16 //修改用戶 17 public int updateUser(User user); 18 19 //刪除用戶 20 public int deleteUser(Integer id); 21 22 23 }
Mapper.xml映射文件:
1 <!-- 使用介面方式 載入命名空間 使用代理模式 --> 2 <mapper namespace="com.softjx.dao.UserMapper"> 3 4 5 6 <!-- 查詢數據表中的所有記錄,並封裝User對象集合 --> 7 <select id="selectAll" resultType="com.softjx.model.User"> 8 select t_id as id,t_username as username,t_password password from t_user 9 </select> 10 11 <select id="selectAll1" resultType="com.softjx.model.User"> 12 select * from t_user1 13 </select> 14 15 16 <!-- 根據id查詢數據表中的一條記錄,並封裝User對象 --> 17 <select id="selectById" resultType="com.softjx.model.User"> 18 select t_id as id,t_username as username,t_password password from t_user where t_id=#{id}; 19 </select> 20 21 22 <!-- 添加用戶 --> 23 <insert id="insertUser"> 24 insert into t_user (t_username,t_password) 25 values (#{username},#{password}) 26 </insert> 27 28 29 <!-- 更新用戶 --> 30 <update id="updateUser"> 31 update t_user set t_username=#{username},t_password=#{password} 32 where t_id=#{id} 33 </update> 34 35 36 <!-- 刪除用戶 --> 37 <delete id="deleteUser"> 38 delete from t_user where t_id=#{id} 39 </delete>
測試代碼:
//查詢所有 @Test public void TestSelectAll1() { System.out.println("查詢所有用戶"); //獲取介面的實現類對象 //會為介面自動的創建一個代理對象,代理對象去執行增刪改查方法 try { UserMapper mapper=session.getMapper(UserMapper.class); System.out.println(mapper); List<User> users=mapper.selectAll(); System.out.println(users); for (User user : users) { System.out.println(user.getId() + " " + user.getUsername() + " " + user.getPassword()); } } finally { session.close(); } } //查詢一個用戶 @Test public void TestSelectById() { System.out.println("查詢一個用戶"); //獲取介面的實現類對象 //會為介面自動的創建一個代理對象,代理對象去執行增刪改查方法 try { UserMapper mapper=session.getMapper(UserMapper.class); User user=mapper.selectById(2); System.out.println(user); System.out.println(user.getId() + " " + user.getUsername() + " " + user.getPassword()); } finally { session.close(); } } //添加用戶測試 @Test public void TestInserUser() { System.out.println("添加一個用戶"); try { User user=new User(); user.setUsername("pppp"); user.setPassword("666666"); UserMapper mapper=session.getMapper(UserMapper.class); int count=mapper.insertUser(user); session.commit();//這裡一定要提交,不然數據進不去資料庫中 //session.rollback(); System.out.println(count); } finally { session.close(); } } //修改用戶測試 @Test public void TestUpdateUser() { System.out.println("修改用戶"); try { User user=new User(); user.setId(10); user.setUsername("yyy"); user.setPassword("11111"); UserMapper mapper=session.getMapper(UserMapper.class); int count=mapper.updateUser(user);// 根據字元找sql語句 session.commit(); //session.rollback(); System.out.println(count); } finally { session.close(); } } //刪除用戶測試 @Test public void TestDeleteUser() { System.out.println("刪除用戶"); try { UserMapper mapper=session.getMapper(UserMapper.class); int count=mapper.deleteUser(10);// 根據字元找sql語句 session.commit(); //session.rollback(); System.out.println(count); } finally { session.close(); } }
總結:
1.SqlSession 的實例不是線程安全的,因此是不能被共用的。
2.SqlSession每次使用完成後需要正確關閉,這個關閉操作是必須的。
3.SqlSession可以直接調用方法的id進行資料庫操作,但是我們一般還是推薦使用SqlSession獲取到Dao介面的代理類,執行代理對象的方法,可以更安全的進行類型檢查操作。