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