摘要:什么是本是的一個開源項目年這個項目由遷移到了,并且改名為。如下的代碼,如果有多個條件的話,那么拼接起來很容易出錯查詢語句根據(jù)是否為來判斷是否是條件查詢。而如果我們使用的話,就可以免去查詢助手類了。
什么是MyBatis
MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,并且改名為MyBatis。是一個基于Java的持久層框架為什么我們要用Mybatis?
無論是Mybatis、Hibernate都是ORM的一種實現(xiàn)框架,都是對JDBC的一種封裝!
到目前為止,我們已經(jīng)在持久層中學了幾種技術了...
Hibernate
jdbc
SpringDAO
那我們?yōu)樯哆€要學Mybatis呢???現(xiàn)在Mybatis在業(yè)內(nèi)大行其道,那為啥他能那么火呢??
Hibernate是一個比較老舊的框架,用過他的同學都知道,只要你會用,用起來十分舒服...啥sql代碼都不用寫...但是呢,它也是有的缺點::處理復雜業(yè)務時,靈活度差, 復雜的HQL難寫難理解,例如多表查詢的HQL語句
而JDBC很容易理解,就那么幾個固定的步驟,就是開發(fā)起來太麻煩了,因為什么都要我們自己干..
而SpringDAO其實就是JDBC的一層封裝,就類似于dbutils一樣,沒有特別出彩的地方....
我們可以認為,Mybatis就是jdbc和Hibernate之間的一個平衡點...畢竟現(xiàn)在業(yè)界都是用這個框架,我們也不能不學呀!
Mybatis快速入門其實我們已經(jīng)學過了Hibernate了,對于Mybatis入門其實就非常類似的。因此就很簡單就能掌握基本的開發(fā)了...
導入開發(fā)包導入Mybatis開發(fā)包
mybatis-3.1.1.jar
commons-logging-1.1.1.jar
log4j-1.2.16.jar
cglib-2.2.2.jar
asm-3.3.1.jar
導入mysql/oracle開發(fā)包
mysql-connector-java-5.1.7-bin.jar
Oracle 11g 11.2.0.1.0 JDBC_ojdbc6.jar
準備測試工作創(chuàng)建一張表
create table students( id int(5) primary key, name varchar(10), sal double(8,2) );
創(chuàng)建實體:
/** * Created by ozc on 2017/7/21. */ public class Student { private Integer id; private String name; private Double sal; public Student() { } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Double getSal() { return sal; } public void setSal(Double sal) { this.sal = sal; } }創(chuàng)建mybatis配置文件
創(chuàng)建mybatis的配置文件,配置數(shù)據(jù)庫的信息....數(shù)據(jù)庫我們可以配置多個,但是默認的只能用一個...
編寫工具類測試是否獲取到連接
使用Mybatis的API來創(chuàng)建一個工具類,通過mybatis配置文件與數(shù)據(jù)庫的信息,得到Connection對象
package cn.itcast.javaee.mybatis.util; import java.io.IOException; import java.io.Reader; import java.sql.Connection; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; /** * 工具類 * @author AdminTC */ public class MybatisUtil { private static ThreadLocal創(chuàng)建實體與映射關系文件threadLocal = new ThreadLocal (); private static SqlSessionFactory sqlSessionFactory; /** * 加載位于src/mybatis.xml配置文件 */ static{ try { Reader reader = Resources.getResourceAsReader("mybatis.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * 禁止外界通過new方法創(chuàng)建 */ private MybatisUtil(){} /** * 獲取SqlSession */ public static SqlSession getSqlSession(){ //從當前線程中獲取SqlSession對象 SqlSession sqlSession = threadLocal.get(); //如果SqlSession對象為空 if(sqlSession == null){ //在SqlSessionFactory非空的情況下,獲取SqlSession對象 sqlSession = sqlSessionFactory.openSession(); //將SqlSession對象與當前線程綁定在一起 threadLocal.set(sqlSession); } //返回SqlSession對象 return sqlSession; } /** * 關閉SqlSession與當前線程分開 */ public static void closeSqlSession(){ //從當前線程中獲取SqlSession對象 SqlSession sqlSession = threadLocal.get(); //如果SqlSession對象非空 if(sqlSession != null){ //關閉SqlSession對象 sqlSession.close(); //分開當前線程與SqlSession對象的關系,目的是讓GC盡早回收 threadLocal.remove(); } } /** * 測試 */ public static void main(String[] args) { Connection conn = MybatisUtil.getSqlSession().getConnection(); System.out.println(conn!=null?"連接成功":"連接失敗"); } }
配置實體與表的映射關系
現(xiàn)在我們已經(jīng)有了Mybatis的配置文件和表與實體之前的映射文件了,因此我們要將配置文件和映射文件關聯(lián)起來
在測試類上,我們是可以獲取得到連接的
編寫DAOpublic class StudentDao { public void add(Student student) throws Exception { //得到連接對象 SqlSession sqlSession = MybatisUtil.getSqlSession(); sqlSession.insert(); } public static void main(String[] args) throws Exception { StudentDao studentDao = new StudentDao(); Student student = new Student(1, "zhongfucheng", 10000D); studentDao.add(student); } }
到現(xiàn)在為止,我們實體與表的映射文件僅僅映射了實體屬性與表的字段的關系...
我們在Hibernate中如果想要插入數(shù)據(jù)什么的,只要調(diào)用save()方法就行了。Hibernate是自動化屏蔽掉了數(shù)據(jù)庫的差異,而我們Mybatis是需要自己手動編寫SQL代碼的...
那么SQL代碼是寫在哪里的呢???明顯地,我們作為一個框架,不可能在程序中寫SQL,我們是在實體與表的映射文件中寫的!
Mybatis實體與表的映射文件中提供了insert標簽【SQL代碼片段】供我們使用
//在JDBC中我們通常使用?號作為占位符,而在Mybatis中,我們是使用#{}作為占位符 //parameterType我們指定了傳入?yún)?shù)的類型 //#{}實際上就是調(diào)用了Student屬性的get方法INSERT INTO ZHONGFUCHENG.STUDENTS (ID, NAME, SAL) VALUES (#{id},#{name},#{sal});
在程序中調(diào)用映射文件的SQL代碼片段
public void add(Student student) throws Exception { //得到連接對象 SqlSession sqlSession = MybatisUtil.getSqlSession(); try{ //映射文件的命名空間.SQL片段的ID,就可以調(diào)用對應的映射文件中的SQL sqlSession.insert("StudentID.add", student); sqlSession.commit(); }catch(Exception e){ e.printStackTrace(); sqlSession.rollback(); throw e; }finally{ MybatisUtil.closeSqlSession(); } }
值得注意的是:Mybatis中的事務是默認開啟的,因此我們在完成操作以后,需要我們手動去提交事務!
Mybatis工作流程通過Reader對象讀取Mybatis配置文件
通過SqlSessionFactoryBuilder對象創(chuàng)建SqlSessionFactory對象
獲取當前線程的SQLSession
事務默認開啟
通過SQLSession讀取映射文件中的操作編號,從而讀取SQL語句
提交事務
關閉資源
完成CRUD操作我們在上面中已經(jīng)簡單知道了Mybatis是怎么使用的以及工作流程了,這次我們使用Mybatis來完成CRUD的操作,再次鞏固Mybatis的開發(fā)步驟以及一些細節(jié)
包與類之間的結構
增加學生配置文件
映射文件
INSERT INTO ZHONGFUCHENG.STUDENTS (ID, NAME, SAL) VALUES (#{id},#{name},#{sal});
插入數(shù)據(jù)
public class StudentDao { public void add(Student student) throws Exception { //得到連接對象 SqlSession sqlSession = MybatisUtil.getSqlSession(); try{ //映射文件的命名空間.SQL片段的ID,就可以調(diào)用對應的映射文件中的SQL sqlSession.insert("StudentID.add", student); sqlSession.commit(); }catch(Exception e){ e.printStackTrace(); sqlSession.rollback(); throw e; }finally{ MybatisUtil.closeSqlSession(); } } public static void main(String[] args) throws Exception { StudentDao studentDao = new StudentDao(); Student student = new Student(3, "zhong3", 10000D); studentDao.add(student); } }根據(jù)ID查詢數(shù)據(jù)
增加select標簽
查詢出來的結果是一個Student對象,我們調(diào)用SelectOne方法
public Student findById(int id) throws Exception { //得到連接對象 SqlSession sqlSession = MybatisUtil.getSqlSession(); try{ //映射文件的命名空間.SQL片段的ID,就可以調(diào)用對應的映射文件中的SQL return sqlSession.selectOne("StudentID.findById",id); }catch(Exception e){ e.printStackTrace(); sqlSession.rollback(); throw e; }finally{ MybatisUtil.closeSqlSession(); } } public static void main(String[] args) throws Exception { StudentDao studentDao = new StudentDao(); Student student = studentDao.findById(1); System.out.println(student.getName()); }查詢所有數(shù)據(jù)
我們查詢出來的結果不單單只有一個對象了,因此我們使用的是SelectList這個方法
public List根據(jù)id刪除findAll() throws Exception { //得到連接對象 SqlSession sqlSession = MybatisUtil.getSqlSession(); try{ //映射文件的命名空間.SQL片段的ID,就可以調(diào)用對應的映射文件中的SQL return sqlSession.selectList("StudentID.findAll"); }catch(Exception e){ e.printStackTrace(); sqlSession.rollback(); throw e; }finally{ MybatisUtil.closeSqlSession(); } } public static void main(String[] args) throws Exception { StudentDao studentDao = new StudentDao(); List students = studentDao.findAll(); System.out.println(students.size()); }
DELETE FROM STUDENTS WHERE id=#{id};
調(diào)用delete方法刪除
public void delete(int id ) throws Exception { //得到連接對象 SqlSession sqlSession = MybatisUtil.getSqlSession(); try{ //映射文件的命名空間.SQL片段的ID,就可以調(diào)用對應的映射文件中的SQL sqlSession.delete("StudentID.delete", id); sqlSession.commit(); }catch(Exception e){ e.printStackTrace(); sqlSession.rollback(); throw e; }finally{ MybatisUtil.closeSqlSession(); } } public static void main(String[] args) throws Exception { StudentDao studentDao = new StudentDao(); studentDao.delete(1); }修改
update students set name=#{name},sal=#{sal} where id=#{id};
查詢出對應的對象,對其進行修改
public void update(Student student ) throws Exception { //得到連接對象 SqlSession sqlSession = MybatisUtil.getSqlSession(); try{ //映射文件的命名空間.SQL片段的ID,就可以調(diào)用對應的映射文件中的SQL sqlSession.update("StudentID.update", student); sqlSession.commit(); }catch(Exception e){ e.printStackTrace(); sqlSession.rollback(); throw e; }finally{ MybatisUtil.closeSqlSession(); } } public static void main(String[] args) throws Exception { StudentDao studentDao = new StudentDao(); Student student = studentDao.findById(2); student.setName("fucheng"); student.setSal(2000D); studentDao.update(student); }小細節(jié)
Mybatis分頁
分頁是一個非常實用的技術點,我們也來學習一下使用Mybatis是怎么分頁的...
我們的分頁是需要多個參數(shù)的,并不是像我們之前的例子中只有一個參數(shù)。當需要接收多個參數(shù)的時候,我們使用Map集合來裝載!
public Listpagination(int start ,int limit) throws Exception { //得到連接對象 SqlSession sqlSession = MybatisUtil.getSqlSession(); try{ //映射文件的命名空間.SQL片段的ID,就可以調(diào)用對應的映射文件中的SQL /** * 由于我們的參數(shù)超過了兩個,而方法中只有一個Object參數(shù)收集 * 因此我們使用Map集合來裝載我們的參數(shù) */ Map map = new HashMap(); map.put("start", start); map.put("limit", limit); return sqlSession.selectList("StudentID.pagination", map); }catch(Exception e){ e.printStackTrace(); sqlSession.rollback(); throw e; }finally{ MybatisUtil.closeSqlSession(); } } public static void main(String[] args) throws Exception { StudentDao studentDao = new StudentDao(); List students = studentDao.pagination(0, 3); for (Student student : students) { System.out.println(student.getId()); } }
那么在實體與表映射文件中,我們接收的參數(shù)就是map集合
動態(tài)SQL
何為動態(tài)SQL??回顧一下我們之前寫的SSH項目中,有多條件查詢的情況,如下圖
我們當時剛開始做的時候,是需要在Controller中判斷SQL是否已經(jīng)有條件了,因為SQL語句需要拼接起來....這樣干的話,就非常容易出錯的。
如下的代碼,如果有多個條件的話,那么拼接起來很容易出錯!
public String listUI() { //查詢語句 String hql = "FROM Info i "; List
后來,我們覺得這樣不好,于是就專門寫了一個查詢助手類:
package zhongfucheng.core.utils; import java.util.ArrayList; import java.util.List; /** * Created by ozc on 2017/6/7. */ public class QueryHelper { private String fromClause = ""; private String whereClause = ""; private String orderbyClause = ""; private List
這樣一來的話,我們就不用自己手動拼接了,給我們的查詢助手類去拼接就好了。
而如果我們使用Mybatis的話,就可以免去查詢助手類了。因為Mybatis內(nèi)部就有動態(tài)SQL的功能【動態(tài)SQL就是自動拼接SQL語句】!
動態(tài)查詢查詢出來小于9000塊的人
public List動態(tài)更新findByCondition(String name,Double sal) throws Exception { //得到連接對象 SqlSession sqlSession = MybatisUtil.getSqlSession(); try{ //映射文件的命名空間.SQL片段的ID,就可以調(diào)用對應的映射文件中的SQL /** * 由于我們的參數(shù)超過了兩個,而方法中只有一個Object參數(shù)收集 * 因此我們使用Map集合來裝載我們的參數(shù) */ Map map = new HashMap(); map.put("name", name); map.put("sal", sal); return sqlSession.selectList("StudentID.findByCondition", map); }catch(Exception e){ e.printStackTrace(); sqlSession.rollback(); throw e; }finally{ MybatisUtil.closeSqlSession(); } } public static void main(String[] args) throws Exception { StudentDao studentDao = new StudentDao(); List students = studentDao.findByCondition(null,9000D); for (Student student : students) { System.out.println(student.getId() + "---" + student.getName() + "----" + student.getSal()); } }
update students where id = #{id} name = #{name}, sal = #{sal},
給出三個更新的字段
public void updateByConditions(int id,String name,Double sal) throws Exception { //得到連接對象 SqlSession sqlSession = MybatisUtil.getSqlSession(); try{ //映射文件的命名空間.SQL片段的ID,就可以調(diào)用對應的映射文件中的SQL /** * 由于我們的參數(shù)超過了兩個,而方法中只有一個Object參數(shù)收集 * 因此我們使用Map集合來裝載我們的參數(shù) */ Map動態(tài)刪除map = new HashMap(); map.put("id", id); map.put("name", name); map.put("sal", sal); sqlSession.update("StudentID.updateByConditions", map); sqlSession.commit(); }catch(Exception e){ e.printStackTrace(); sqlSession.rollback(); throw e; }finally{ MybatisUtil.closeSqlSession(); } } public static void main(String[] args) throws Exception { StudentDao studentDao = new StudentDao(); studentDao.updateByConditions(2,"haha",500D); }
以前我們使用JDBC也好,Hibernate也好,想要批量刪除的時候,總是使用的是循環(huán)刪除。而我們現(xiàn)在使用的是Mybatis,SQL語句是自己寫的。所以我們可以寫下如下的SQL來進行刪除
delete from students where id in (?,?,?,?);
而我們的Mybatis又支持動態(tài)SQL,所以刪除起來就非常方便了!
delete from students where id in #{ids}
刪除編號為2,3,4的記錄
public void deleteByConditions(int... ids) throws Exception { //得到連接對象 SqlSession sqlSession = MybatisUtil.getSqlSession(); try{ //映射文件的命名空間.SQL片段的ID,就可以調(diào)用對應的映射文件中的SQL /** * 由于我們的參數(shù)超過了兩個,而方法中只有一個Object參數(shù)收集 * 因此我們使用Map集合來裝載我們的參數(shù) */ sqlSession.delete("StudentID.deleteByConditions", ids); sqlSession.commit(); }catch(Exception e){ e.printStackTrace(); sqlSession.rollback(); throw e; }finally{ MybatisUtil.closeSqlSession(); } } public static void main(String[] args) throws Exception { StudentDao studentDao = new StudentDao(); studentDao.deleteByConditions(2,3,4); }動態(tài)插入
我們要想動態(tài)插入的話,就比其他的DML語句稍微復雜一點,因為它有兩部分是不確定的,平常的SQL語句是這樣的:
insert into student(id,name,sal) values(?,?,?)
SQL代碼塊是不能像之前那樣幫我們自動去除多余的逗號的,因此我們需要使用trim標簽來自己手動去除...
編寫insertSQL語句的時候,不要忘了寫()括號。
id, name, sal, #{id}, #{name}, #{sal}, insert into students ( ) values ( )
測試三個不同內(nèi)容的數(shù)據(jù)
public void insertByConditions(Student student) throws Exception { //得到連接對象 SqlSession sqlSession = MybatisUtil.getSqlSession(); try{ //映射文件的命名空間.SQL片段的ID,就可以調(diào)用對應的映射文件中的SQL sqlSession.insert("StudentID.insertByConditions", student); sqlSession.commit(); }catch(Exception e){ e.printStackTrace(); sqlSession.rollback(); throw e; }finally{ MybatisUtil.closeSqlSession(); } } public static void main(String[] args) throws Exception { StudentDao studentDao = new StudentDao(); studentDao.insertByConditions(new Student(55, null, null));//name和sal為空 studentDao.insertByConditions(new Student(66, "haxi", null));//sal為空 studentDao.insertByConditions(new Student(77, null, 3999d));//name為空 }總結
Mybatis的準備工作與Hibernate差不多,都需要一個總配置文件、一個映射文件。
Mybatis的SQLSession工具類使用ThreadLocal來對線程中的Session來進行管理。
Mybatis的事務默認是開啟的,需要我們手動去提交事務。
Mybatis的SQL語句是需要手寫的,在程序中通過映射文件的命名空間.sql語句的id來進行調(diào)用!
在Mybatis中,增刪改查都是需要我們自己寫SQL語句的,然后在程序中調(diào)用即可了。SQL由于是我們自己寫的,于是就相對Hibernate靈活一些。
如果需要傳入多個參數(shù)的話,那么我們一般在映射文件中用Map來接收。
由于我們在開發(fā)中會經(jīng)常用到條件查詢,在之前,我們是使用查詢助手來幫我們完成對SQL的拼接的。而Mybatis的話,我們是自己手寫SQL代碼的。
Mybatis也支持一些判斷標簽,于是我們就可以通過這些標簽來完成動態(tài)CRUD的操作了。
值得注意的是,我們的sql片段代碼是需要我們自己手動去分割,號的。
如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關注微信公眾號:Java3y
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/68761.html
摘要:采用完全獨立于任何程序語言的文本格式,使成為理想的數(shù)據(jù)交換語言為什么需要提到,我們就應該和來進行對比。也是一種存儲和交換文本信息的手段。那么好在哪里呢比更小更快,更易解析。使用的時候,也支持將轉成但是,我們不一定使用框架來做開發(fā)呀。 什么是JSON JSON:JavaScript Object Notation 【JavaScript 對象表示法】 JSON 是存儲和交換文本信息的語法...
摘要:目錄前言架構安裝第一個爬蟲爬取有道翻譯創(chuàng)建項目創(chuàng)建創(chuàng)建解析運行爬蟲爬取單詞釋義下載單詞語音文件前言學習有一段時間了,當時想要獲取一下百度漢字的解析,又不想一個個漢字去搜,復制粘貼太費勁,考慮到爬蟲的便利性,這篇文章是介紹一個爬蟲框架, 目錄 前言 架構 安裝 第一個爬蟲:爬取有道翻譯 創(chuàng)建項目 創(chuàng)建Item 創(chuàng)建Spider 解析 運行爬蟲-爬取單詞釋義 下載單詞語音文件 ...
摘要:前言由于寫的文章已經(jīng)是有點多了,為了自己和大家的檢索方便,于是我就做了這么一個博客導航。 前言 由于寫的文章已經(jīng)是有點多了,為了自己和大家的檢索方便,于是我就做了這么一個博客導航。 由于更新比較頻繁,因此隔一段時間才會更新目錄導航哦~想要獲取最新原創(chuàng)的技術文章歡迎關注我的公眾號:Java3y Java3y文章目錄導航 Java基礎 泛型就這么簡單 注解就這么簡單 Druid數(shù)據(jù)庫連接池...
摘要:相信很多人在格式化字符串的時候都用的語法,提出一種更先進的格式化方法并成為的標準用來替換舊的格式化語法,從開始已經(jīng)實現(xiàn)了這一方法其它解釋器未考證。 showImg(https://segmentfault.com/img/remote/1460000018650325); 相信很多人在格式化字符串的時候都用%s % v的語法,PEP 3101 提出一種更先進的格式化方法 str.for...
閱讀 2733·2021-09-02 15:11
閱讀 905·2019-08-26 18:18
閱讀 1867·2019-08-26 11:57
閱讀 3317·2019-08-23 16:59
閱讀 1993·2019-08-23 16:51
閱讀 2305·2019-08-23 16:11
閱讀 3120·2019-08-23 14:58
閱讀 1106·2019-08-23 11:34