一区二区三区电影_国产伦精品一区二区三区视频免费_亚洲欧美国产精品va在线观看_国产精品一二三四

聯(lián)系我們 - 廣告服務(wù) - 聯(lián)系電話:
您的當(dāng)前位置: > 關(guān)注 > > 正文

<table><tbody><tr><td>為什么要使用框架?使用軟件框架的優(yōu)點(diǎn)總結(jié)</td></tr></tbody></table>

來源:CSDN 時間:2022-12-09 15:26:40

思維導(dǎo)圖

導(dǎo)學(xué)

MyBatis是一個大名鼎鼎的ORM框架,對于我們進(jìn)行數(shù)據(jù)庫開發(fā)有著非常優(yōu)秀的支持。 首先我們要了解,什么是框架?框架,即 framework。其實(shí)就是某種應(yīng)用的半成品,就是一組組件,供你選用完成你自己的系統(tǒng)。簡單說就是使用別人搭好的舞臺,你來做表演。而且,框架一般是成熟的,不斷升級的軟件。


【資料圖】

打個比方,Java 框架跟建筑中的框架式結(jié)構(gòu)是一樣的。使用了框架(鋼筋+混凝土)以后,你所專著的只是業(yè)務(wù)(非承重墻構(gòu)建不同格局),當(dāng)然是在遵守框架的協(xié)議上開發(fā)業(yè)務(wù)。

為什么要使用框架? 因?yàn)檐浖到y(tǒng)發(fā)展到今天已經(jīng)很復(fù)雜了,特別是服務(wù)器端軟件,涉及到的知識,內(nèi)容,問題太多。在某些方面使用別人成熟的框架,就相當(dāng)于讓別人幫你完成一些基礎(chǔ)工作,你只需要集中精力完成系統(tǒng)的業(yè)務(wù)邏輯設(shè)計(jì)。而且框架一般是成熟,穩(wěn)健的,你可以處理系統(tǒng)很多細(xì)節(jié)問題,比如,事物處理,安全性,數(shù)據(jù)流控制等問題。還有框架一般都經(jīng)過很多人使用,所以結(jié)構(gòu)很好,所以擴(kuò)展性也很好,而且它是不斷升級的,你可以直接享受別人升級代碼帶來的好處。 比如,我們可以自己DIY一臺電腦,這就是因?yàn)槲覀兛梢允褂靡粋€現(xiàn)成的主板,在這個主板上有著許多規(guī)范的接口可供其他設(shè)備加入。軟件開發(fā)中的框架

框架是可被應(yīng)用開發(fā)者定制的應(yīng)用骨架框架是一種規(guī)則,保證開發(fā)者遵守相同的方式開發(fā)程序框架提倡“不要重復(fù)造輪子”,對基礎(chǔ)功能進(jìn)行封裝

使用軟件框架的優(yōu)點(diǎn)總結(jié)

極大的提高了開發(fā)的效率統(tǒng)一的編碼規(guī)則,利于團(tuán)隊(duì)管理靈活配置的應(yīng)用,擁有更好的維護(hù)性

SSM框架介紹

Spring 對象容器框架,提供底層的對象管理,是框架的框架,其他的框架都要基于該框架進(jìn)行開發(fā)。Spring MVC web開發(fā)框架,用于替代servlet,提供Web底層的交互,進(jìn)行更有效的web開發(fā)。Mybatis 數(shù)據(jù)庫框架,用于簡化數(shù)據(jù)庫操作,對JDBC進(jìn)行了封裝及擴(kuò)展,提供了數(shù)據(jù)庫的增刪改查的便捷操作

補(bǔ)充介紹:SSH框架其實(shí)指的是Spring+Struts2+Hibernate框架,該框架更貼近于我們之前的Java Web學(xué)習(xí)內(nèi)容,較為老舊,需要較多的配置文件,并不怎么方便。

補(bǔ)充介紹:常用的數(shù)據(jù)庫框架其實(shí)還有MyBatis Plus和iBatis框架等。

MyBatis框架介紹

MyBatis是優(yōu)秀的持久層框架 --將內(nèi)存中的數(shù)據(jù)保存在數(shù)據(jù)庫中MyBatis使用XML將SQL與程序解耦,便于維護(hù)MyBatis學(xué)習(xí)簡單,執(zhí)行高效,是JDBC的延伸

對象的兩種狀態(tài):

瞬時狀態(tài):程序中運(yùn)行的對象,對象保存在內(nèi)存中,當(dāng)程序中斷或者結(jié)束(計(jì)算機(jī)關(guān)閉或重啟),該狀態(tài)對象不會保留。持久化狀態(tài):把對象數(shù)據(jù)保留在文件中,文件存儲在永久的存儲介質(zhì)里(光盤、硬盤),當(dāng)程序中斷或者計(jì)算機(jī)重啟斷電,該狀態(tài)的對象會永久保留。 所謂的持久化就是把瞬時狀態(tài)的對象轉(zhuǎn)換為持久化狀態(tài)的對象。

MyBatis開發(fā)流程-非xml形式

引入MyBatis依賴創(chuàng)建核心配置文件創(chuàng)建實(shí)體(Entity)類創(chuàng)建Mapper映射文件初始化SessionFactory利用SqlSession對象操作數(shù)據(jù)

ORM框架

O:java Object 即 Java 中的對象; R:relationship 即關(guān)系數(shù)據(jù)庫; M:mapping 將JAVA中的對象映射成關(guān)系型數(shù)據(jù)庫中的表;

MyBatis 框架是一個可以自定義 SQL 和 OR 映射的持久化框架; 框架拋棄了大部分的 JDBC 代碼,也不需要手工設(shè)置參數(shù)以及結(jié)果集的操作; 框架使用簡單的 XML 配置或者注解來映射數(shù)據(jù)類型和關(guān)系,相對于 Hibernate 框架,MyBatis 是一種半自動化的 ORM 實(shí)現(xiàn)。

MyBatis配置

在本課程中,MyBatis將依賴于Maven進(jìn)行管理。 在MyBatis中,使用xml進(jìn)行配置,有一個約定俗成的文件名叫做mybatis-config.xml,它是mybatis的一個核心配置文件。

1. Mybatis采用xml文件配置數(shù)據(jù)庫環(huán)境信息2. Mybatis環(huán)境配置標(biāo)簽3. environment配置包含數(shù)據(jù)庫驅(qū)動,URL,用戶名和密碼

前期準(zhǔn)備-新建項(xiàng)目pom.xml

4.0.0<groupId>com.dodoke</groupId><artifactId>mybatis</artifactId><version>1.0.0-SNAPSHOT</version><repositories>    <repository>        <id>aliyun</id>        <name>aliyun</name>        <!-- 可能阿里云倉庫的地址會發(fā)生變化,需要查找最新的地址 -->        <url>https://maven.aliyun.com/repository/public</url>    </repository></repositories><dependencies>    <!-- 數(shù)據(jù)庫驅(qū)動依賴 -->    <dependency>        <groupId>mysql</groupId>        <artifactId>mysql-connector-java</artifactId>        <version>8.0.18</version>    </dependency>    <!-- mybatis依賴 -->    <dependency>        <groupId>org.mybatis</groupId>        <artifactId>mybatis</artifactId>        <version>3.5.5</version>    </dependency></dependencies>

 

前期準(zhǔn)備-數(shù)據(jù)庫設(shè)計(jì)下載地址https://pan.baidu.com/s/1xgxXH9tPn0O_Qf5QfmmbBg 提取碼 mso3設(shè)置idea連接數(shù)據(jù)庫resources目錄下設(shè)置mybatis的核心配置文件mybatis-config.xml

                                                        

 

SqlSessionFactory & SqlSession

SqlSessionFactory是MyBatis中的一個重要的對象,它是用來創(chuàng)建SqlSession對象的,而SqlSession用來操作數(shù)據(jù)庫的。介紹:

SqlSessionFactory是MyBatis的核心對象SqlSessionFactory用于初始化MyBatis,讀取配置文件。是一個工廠方法,用于創(chuàng)建SqlSession對象。要保證SqlSessionFactory在應(yīng)用全局中只存在唯一的對象,通常會使用靜態(tài)類的方式對其進(jìn)行初始化。

SqlSession是MyBatis用來操作數(shù)據(jù)庫的一個核心對象,不那么嚴(yán)謹(jǐn)?shù)恼f,可以將SqlSession看做類似于我們之前學(xué)習(xí)過的JDBC的連接接口對象(Connection)執(zhí)行接口對象(PreparedStatement)的組合,用來執(zhí)行CRUD操作。介紹:

SqlSession是MyBatis操作數(shù)據(jù)庫的核心對象SqlSession使用JDBC的方式與數(shù)據(jù)庫交互SqlSession對象提供了數(shù)據(jù)表的CRUD方法

示例引入Junit組件進(jìn)行測試應(yīng)用 依賴:

junitjunit4.12

測試代碼:

package com.dodoke.mybatistest;

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.Test;

import java.io.IOException; import java.io.Reader; import java.sql.Connection;

/**

Junit單元測試用例類

規(guī)范存放在maven項(xiàng)目的test文件夾中 */ public class MyBatisTest {

@Test public void sqlSessionFactoryTest() throws IOException {//通過MyBatis提供的資源類,獲取對應(yīng)的配置文件作為字符流讀取 //getResourceAsReader方法會默認(rèn)的從當(dāng)前classpath類路徑下加載文件 Reader reader = Resources.getResourceAsReader(“mybatis-config.xml”); //初始化SqlSessionFactory,并同時解析mybatis-config.xml文件 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); System.out.println(“SqlSessionFactory對象加載成功”); //創(chuàng)建SqlSession對象,用于與數(shù)據(jù)庫產(chǎn)生交互,注意SqlSession它是JDBC的擴(kuò)展類 SqlSession sqlSession = null; try {sqlSession = sqlSessionFactory.openSession(); //在SqlSession對象底層存在Connection(java.sql)連接對象,可以通過getConnection方法得到該對象 Connection connection = sqlSession.getConnection(); //該connection對象的創(chuàng)建僅做演示測試用,在mybatis中,無需使用任何與JDBC有關(guān)的類 System.out.println(connection); } catch (Exception e) {e.printStackTrace(); } finally {if(sqlSession != null) {//在mybatis-config.xml文件中,dataSource節(jié)點(diǎn)type屬性: //如果type=“POOLED”,代表使用連接池,close則是將連接回收到連接池中 //如果type=“UNPOOLED”,代表直連,close則會調(diào)用Connection.close()方法關(guān)閉連接 //這是配置帶來的底層處理機(jī)制的不同 sqlSession.close(); } } }

}

設(shè)置MybatisUtils工具類

在之前的課程中,我們提到需要保證SqlSessionFactory在全局中保證唯一,那么如何保證該SqlSessionFactory在應(yīng)用全局保證唯一呢? 通過額外創(chuàng)建的工具類MybatisUtils對SqlSessionFactory對象的初始化以及SqlSession對象的創(chuàng)建和釋放方法進(jìn)行封裝 。說明:

一般工具類放在utils包下;用static代碼塊對靜態(tài)對象進(jìn)行初始化;這邊我們在異常捕獲后將類的初始化的過程中產(chǎn)生的異常拋出,為了外界能捕獲到這個異常信息并進(jìn)行后續(xù)處理,而不是直接終止運(yùn)行程序,我們需要將異常拋出;提供SqlSession對象的創(chuàng)建與釋放方法,工具類的大多數(shù)方法要使用static進(jìn)行描述。

工具類代碼

package com.dodoke.mybatis;

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 java.io.IOException; import java.io.Reader;

/**

MyBatisUtils工具類,創(chuàng)建全局唯一的SqlSessionFactory對象 */ public class MyBatisUtils {//設(shè)置私有靜態(tài)屬性,因?yàn)殪o態(tài)內(nèi)容屬于類而不屬于對象,且擁有全局唯一的特性 private static SqlSessionFactory sqlSessionFactory = null;

//利用靜態(tài)代碼塊在初始化類時實(shí)例化sqlSessionFactory屬性 static {try {Reader reader = Resources.getResourceAsReader(“mybatis-config.xml”); sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); } catch (IOException e) {e.printStackTrace(); //需要拋出初始化的異常,并且傳入捕捉到的異常,形成一條完整的異常鏈 //以便于通知調(diào)用者 throw new ExceptionInInitializerError(e); } }

/**

獲取數(shù)據(jù)庫交互SqlSession@return SqlSession對象 */ public static SqlSession openSqlSession() {return sqlSessionFactory.openSession(); }

/**

釋放一個有效的SqlSession對象@param sqlSession 準(zhǔn)備釋放的SqlSession對象 */ public static void closeSqlSession(SqlSession sqlSession) {if(sqlSession != null) {sqlSession.close(); } } }

測試類單元測試代碼

/** * MyBatisUtils使用指南 * @throws Exception */@Testpublic void testMyBatisUtils() throws Exception {    SqlSession sqlSession = null;    try {        sqlSession = MyBatisUtils.openSqlSession();        Connection connection = sqlSession.getConnection();        System.out.println(connection);    }catch (Exception e){        throw e;    } finally {        MyBatisUtils.closeSqlSession(sqlSession);    }}

MyBatis數(shù)據(jù)查詢

在MyBatis中,雖然我們可以使用MyBatis之前的舊形式,寫出如同JDBC那樣Java代碼和SQL代碼混合的數(shù)據(jù)操作命令,但是我們不建議大家這么做! 對于MyBatis數(shù)據(jù)查詢,可以總結(jié)出如下的步驟:1. 創(chuàng)建實(shí)體類(Entity)在main/java下創(chuàng)建com.dodoke.mybatis.entity包,entity包下創(chuàng)建數(shù)據(jù)庫中t_goods表對應(yīng)的Goods商品實(shí)體類,將數(shù)據(jù)表中的字段對應(yīng)在實(shí)體類中增加一系列的私有屬性及getter/setter方法,屬性采用駝峰命名。

/** * 數(shù)據(jù)庫t_goods表對應(yīng)映射的實(shí)體類 */public class Goods {    private Integer goodsId;//商品編號    private String title;//標(biāo)題    private String subTitle;//子標(biāo)題    private Float originalCost;//原始價格    private Float currentPrice;//當(dāng)前價格    private Float discount;//折扣率    private Integer isFreeDelivery;//是否包郵 ,1-包郵 0-不包郵    private Integer categoryId;//分類編號public Integer getGoodsId() {    return goodsId;}public void setGoodsId(Integer goodsId) {    this.goodsId = goodsId;}public String getTitle() {    return title;}public void setTitle(String title) {    this.title = title;}public String getSubTitle() {    return subTitle;}public void setSubTitle(String subTitle) {    this.subTitle = subTitle;}public Float getOriginalCost() {    return originalCost;}public void setOriginalCost(Float originalCost) {    this.originalCost = originalCost;}public Float getCurrentPrice() {    return currentPrice;}public void setCurrentPrice(Float currentPrice) {    this.currentPrice = currentPrice;}public Float getDiscount() {    return discount;}public void setDiscount(Float discount) {    this.discount = discount;}public Integer getIsFreeDelivery() {    return isFreeDelivery;}public void setIsFreeDelivery(Integer isFreeDelivery) {    this.isFreeDelivery = isFreeDelivery;}public Integer getCategoryId() {    return categoryId;}public void setCategoryId(Integer categoryId) {    this.categoryId = categoryId;}

}

2. 創(chuàng)建Mapper XML說明SQL語句第二步,第三步結(jié)合使用,具體內(nèi)容在第三步中。3. 在Mapper XML中增加SQL語句對應(yīng)標(biāo)簽在main/resources下創(chuàng)建新的子目錄mappers,mappers代表映射器,里面存放的都是xml文件。創(chuàng)建GoodsMapper.xml文件來說明實(shí)體類和數(shù)據(jù)表的對應(yīng)關(guān)系(和哪個數(shù)據(jù)表對應(yīng),屬性和字段怎么對應(yīng))。 說明:A.根節(jié)點(diǎn)通過增加不同的命名空間namespace來區(qū)分不同的mapper文件,通常我們會將針對一張表操作的SQL語句放置在一個mapper文件中。B.語句節(jié)點(diǎn)的id屬性為別名,相當(dāng)于SQL名稱,同一個namespace下id要唯一,不同的namespace可以重名;因此namespace的設(shè)置就很有必要,不然調(diào)用SQL的時候分不清哪個idC.語句節(jié)點(diǎn)的resultType屬性代表返回的對象是什么,為實(shí)體類的完整路徑,在SQL語句執(zhí)行完后會自動的將得到的每一條記錄包裝成對應(yīng)的實(shí)體類的對象;

        select * from t_goods order by goods_id desc limit 10

4. 在mybatis-config.xml中增加Mapper XML文件聲明其實(shí)就是讓MyBatis認(rèn)識新創(chuàng)建的GoodsMapper.xml: 在mybatis-config.xml中添加mappers標(biāo)簽,這樣MyBatis在初始化的時候才知道這個GoodsMapper.xml的存在。


5. 利用SqlSession執(zhí)行Mapper XML中的SQL語句

/** * select查詢語句執(zhí)行 * @throws Exception */@Testpublic void testSelectAll() throws Exception {    SqlSession session = null;    try{        session = MyBatisUtils.openSqlSession();        //selectList代表查詢多條數(shù)據(jù),selectOne代表查詢一條結(jié)果        Listlist = session.selectList("com.dodoke.mybatis.resources.mappers.GoodsMapper.selectAll");        for(Goods g : list){            System.out.println(g.getTitle());        }    }catch (Exception e){        throw e;    }finally {        MyBatisUtils.closeSqlSession(session);    }}

對于這樣的查詢,其實(shí)獲取到的數(shù)據(jù)是存在數(shù)據(jù)丟失的,這是因?yàn)槲覀兊牟樵兘Y(jié)果類型字段和表中字段名不能匹配!6. 在mybatis-config.xml中開啟駝峰命名映射其實(shí)第六步應(yīng)該放在第五步之前,這里只是給大家作為演示。

     goodsId -->

MyBatis的SQL傳參

在實(shí)現(xiàn)CRUD等操作的時候,有很多的SQL條件數(shù)據(jù)其實(shí)是通過接受前臺動態(tài)傳遞過來的參數(shù)決定的。那么如何設(shè)置這些SQL語句的參數(shù)呢? 在數(shù)據(jù)操作節(jié)點(diǎn)中,可以添加parameterType屬性指定參數(shù)類型,并采用#{param}的形式接受傳入的參數(shù)。 示例: GoodsMapper.xml

select * from t_goods where goods_id = #{value}

測試:

/** * 傳遞單個SQL參數(shù) * @throws Exception */@Testpublic void testSelectById() throws Exception {    SqlSession session = null;    try{        session = MyBatisUtils.openSqlSession();        //傳入的參數(shù)類型需要和對應(yīng)數(shù)據(jù)操作節(jié)點(diǎn)中指明的參數(shù)類型一致        Goods goods = session.selectOne("com.dodoke.mybatis.resources.mappers.GoodsMapper.selectById" , 1603);        System.out.println(goods.getTitle());    }catch (Exception e){        throw e;    }finally {        MyBatisUtils.closeSqlSession(session);    }}

/**

傳遞多個SQL參數(shù)@throws Exception */ @Test public void testSelectByPriceRange() throws Exception {SqlSession session = null; try{session = MyBatisUtils.openSqlSession(); Map param = new HashMap(); //map中的key-value的key值,需要和數(shù)據(jù)操作節(jié)點(diǎn)中參數(shù)名一致 param.put(“min”,100); param.put(“max” , 500); param.put(“l(fā)imt” , 10); Listlist = session.selectList(“com.dodoke.mybatis.resources.mappers.GoodsMapper.selectByPriceRange”, param); for(Goods g:list){System.out.println(g.getTitle() + “:” + g.getCurrentPrice()); } }catch (Exception e){throw e; }finally {MyBatisUtils.closeSqlSession(session); } }

多表關(guān)聯(lián)查詢

在之前的學(xué)習(xí)中,我們針對的都是一個表的查詢,那么如何針對多表進(jìn)行聯(lián)合查詢呢? 其實(shí)我們可以將返回的結(jié)果變?yōu)镸ap類型,這樣MyBatis就會將結(jié)果封裝為Map集合中對應(yīng)的鍵值對

select g.* , c.category_name from t_goods g , t_category c where g.category_id = c.category_id
/** * 利用Map接收關(guān)聯(lián)查詢結(jié)果 * @throws Exception */@Testpublic void testSelectGoodsMap() throws Exception {    SqlSession session = null;    try{        session = MyBatisUtils.openSqlSession();        Listlist = session.selectList("com.dodoke.mybatis.resources.mappers.GoodsMapper.selectGoodsMap");        for(Map map : list){            System.out.println(map);        }    }catch (Exception e){        throw e;    }finally {        MyBatisUtils.closeSqlSession(session);    }}

我們可以看到,該方法返回的結(jié)果為數(shù)據(jù)庫中表對應(yīng)的原始字段名為key值,而且查詢到的結(jié)果的順序是混亂的。 為了保證我們等到的結(jié)果的順序和數(shù)據(jù)庫中的順序一致,我們需要使用LinkedHashMap。

LinkedHashMap是采用鏈表形式的HashMap,他在進(jìn)行數(shù)據(jù)提取的時候是按照插入數(shù)據(jù)時的順序進(jìn)行提取保存的,不會出現(xiàn)亂序的情況。使用LinkedHashMap來接收數(shù)據(jù)是常用的,因?yàn)楣镜臄?shù)據(jù)結(jié)構(gòu)較為復(fù)雜,需要多表關(guān)聯(lián)查詢,LinkedHashMap可以有效進(jìn)行數(shù)據(jù)的擴(kuò)展,非常靈活。缺點(diǎn):太過靈活,任何查詢結(jié)果都會被LinkedHashMap包裝在內(nèi),相比較實(shí)體類而言,缺少了編譯時檢查,是很容易出錯的。

select g.* , c.category_name,"1" as test from t_goods g , t_category c where g.category_id = c.category_id

其實(shí)針對于這樣的多表查詢,我們還可以通過修改實(shí)體類來實(shí)現(xiàn),顯得不夠靈活,但是卻可以保證在編譯的時候進(jìn)行檢查。具體選用哪種方式可以根據(jù)實(shí)際情況進(jìn)行選擇。 PS:注意,在之前我們的學(xué)習(xí)中,我們是利用在mybaits-config.xml文件中設(shè)置駝峰映射的方式,來解決字段和實(shí)體類屬性名稱不能匹配的問題的,但是我們也可以設(shè)置在查詢的時候起別名的方式,解決這個問題。

ResultMap結(jié)果映射

介紹:

ResultMap可以將查詢結(jié)果映射為復(fù)雜類型的Java對象。ResultMap適用于Java對象保存多表關(guān)聯(lián)結(jié)果ResultMap是MyBatis關(guān)聯(lián)的核心所在,支持對象關(guān)聯(lián)查詢等高級特性

在上節(jié)課程中,我們也提到過,可以為了查詢結(jié)果去修改實(shí)體類。但是,這種方式在標(biāo)準(zhǔn)的mybatis開發(fā)下是不太建議的。實(shí)體類僅僅和數(shù)據(jù)表對應(yīng)就好,不要添加一些冗余的屬性,但是在實(shí)際開發(fā)中,我們有時為了方便,實(shí)際上較多的還是采用修改實(shí)體類的形式。 但是,采用DTO,數(shù)據(jù)擴(kuò)展類開發(fā)的形式,我們同學(xué)們必須掌握。 在com.dodoke.mybatis包下面新建一個dto包,新建GoodsDTO類。

DTO是一個特殊的JavaBean,數(shù)據(jù)傳輸對象。對原始對象進(jìn)行擴(kuò)展,用于數(shù)據(jù)保存和傳遞。

/** * 擴(kuò)展類,數(shù)據(jù)傳輸對象 */public class GoodsDTO {    private Goods goods = new Goods();    private String categoryName;    private String test;public Goods getGoods() {    return goods;}public void setGoods(Goods goods) {    this.goods = goods;}public String getCategoryName() {    return categoryName;}public void setCategoryName(String categoryName) {    this.categoryName = categoryName;}public String getTest() {    return test;}public void setTest(String test) {    this.test = test;}

}

使用resultMap屬性,添加結(jié)果映射

    select g.* , c.*,"1" as test from t_goods g , t_category c where g.category_id = c.category_id

測試

/** * 利用ResultMap進(jìn)行結(jié)果映射 * @throws Exception */@Testpublic void testSelectGoodsDTO() throws Exception {    SqlSession session = null;    try{        session = MyBatisUtils.openSqlSession();        Listlist = session.selectList("com.dodoke.mybatis.resources.mappers.GoodsMapper.selectGoodsDTO");        for (GoodsDTO g : list) {            System.out.println(g.getGoods().getTitle());        }    }catch (Exception e){        throw e;    }finally {        MyBatisUtils.closeSqlSession(session);    }}

其實(shí)我們可以繼續(xù)擴(kuò)展,比如我現(xiàn)在不僅僅想要得到category_name產(chǎn)品名稱,還想要獲得其他屬性,那么我們該怎么辦呢? 新建t_category表的實(shí)體類

package com.dodoke.mybatis.entity;

public class Category {private Integer categoryId; private String categoryName; private Integer parentId; private Integer categoryLevel; private Integer categoryOrder;

public Integer getCategoryId() {    return categoryId;}public void setCategoryId(Integer categoryId) {    this.categoryId = categoryId;}public String getCategoryName() {    return categoryName;}public void setCategoryName(String categoryName) {    this.categoryName = categoryName;}public Integer getParentId() {    return parentId;}public void setParentId(Integer parentId) {    this.parentId = parentId;}public Integer getCategoryLevel() {    return categoryLevel;}public void setCategoryLevel(Integer categoryLevel) {    this.categoryLevel = categoryLevel;}public Integer getCategoryOrder() {    return categoryOrder;}public void setCategoryOrder(Integer categoryOrder) {    this.categoryOrder = categoryOrder;}

}

修改DTO數(shù)據(jù)對象

package com.dodoke.mybatis.dto;

import com.dodoke.mybatis.entity.Category; import com.dodoke.mybatis.entity.Goods;

/**

擴(kuò)展類,數(shù)據(jù)傳輸對象 */ public class GoodsDTO {private Goods goods = new Goods(); private Category category = new Category(); private String test;

public Goods getGoods() {return goods; }

public void setGoods(Goods goods) {this.goods = goods; }

public Category getCategory() {return category; }

public void setCategory(Category category) {this.category = category; }

public String getTest() {return test; }

public void setTest(String test) {this.test = test; } }

修改映射結(jié)果集

    select g.* , c.*,"1" as test from t_goods g , t_category c where g.category_id = c.category_id

MyBatis數(shù)據(jù)寫入

在之前的課程中,我們實(shí)現(xiàn)了MyBatis的數(shù)據(jù)查詢工作,接下來,我們來看看如何實(shí)現(xiàn)數(shù)據(jù)的新增,修改和刪除工作。

數(shù)據(jù)庫事務(wù)

提到數(shù)據(jù)庫的寫入操作,就離不開數(shù)據(jù)庫的事務(wù)。數(shù)據(jù)庫事務(wù)是保證數(shù)據(jù)操作完整性的基礎(chǔ)所有從客戶端發(fā)來的新增修改刪除操作,都會被事務(wù)日志所記錄,我們形象的將事務(wù)日志看成流水賬,它記錄客戶端發(fā)來的所有寫操作的前后順序, 當(dāng)客戶端向MySQL服務(wù)器發(fā)起了一個commit提交命令的時候,事務(wù)日志才會將這三個數(shù)據(jù)同時的寫入到數(shù)據(jù)表中,在commit的時候才是真正的往數(shù)據(jù)表寫入的過程,當(dāng)這三條數(shù)據(jù)都被成功寫入到數(shù)據(jù)表中后,剛才所產(chǎn)生的事務(wù)日志都會被清空掉。 假設(shè)如果客戶端在處理這些數(shù)據(jù)的時候,數(shù)據(jù)1和數(shù)據(jù)2執(zhí)行成功,數(shù)據(jù)3因?yàn)楦鞣N原因沒有執(zhí)行成功的話,客戶端會發(fā)起一個rollback回滾命令,當(dāng)MySQL收到了rollback回滾命令后,當(dāng)前事務(wù)日志中的所有已經(jīng)產(chǎn)生的數(shù)據(jù)都會被清除,這就意味著前面已經(jīng)產(chǎn)生的數(shù)據(jù)1和數(shù)據(jù)2不會放入到數(shù)據(jù)表中,只有當(dāng)所有數(shù)據(jù)都完成的時候,在由客戶端發(fā)起commit提交,數(shù)據(jù)才能成功的寫入。要么數(shù)據(jù)全部寫入成功,要么中間出現(xiàn)了任何問題,全部回滾,保證了數(shù)據(jù)的完整性

案例

修改MyBatisUtils

/** * 獲取數(shù)據(jù)庫交互SqlSession * @return SqlSession對象 */public static SqlSession openSqlSession() {    //默認(rèn)SqlSession對自動提交事務(wù)數(shù)據(jù)(commit)    //設(shè)置false代表關(guān)閉自動提交,改為手動提交事務(wù)數(shù)據(jù)    return sqlSessionFactory.openSession(false);}

新增

INSERT INTO t_goods(title, sub_title, original_cost, current_price, discount, is_free_delivery, category_id)    VALUES (#{title} , #{subTitle} , #{originalCost}, #{currentPrice}, #{discount}, #{isFreeDelivery}, #{categoryId})        select last_insert_id()
/** * 新增數(shù)據(jù) * @throws Exception */@Testpublic void testInsert() throws Exception {    SqlSession session = null;    try{        session = MyBatisUtils.openSqlSession();        Goods goods = new Goods();        goods.setTitle("測試商品");        goods.setSubTitle("測試子標(biāo)題");        goods.setOriginalCost(200f);        goods.setCurrentPrice(100f);        goods.setDiscount(0.5f);        goods.setIsFreeDelivery(1);        goods.setCategoryId(43);        //insert()方法返回值代表本次成功插入的記錄總數(shù)        int num = session.insert("com.dodoke.mybatis.resources.mappers.GoodsMapper.insert", goods);        session.commit();//提交事務(wù)數(shù)據(jù)        System.out.println(goods.getGoodsId());    }catch (Exception e){        if(session != null){            session.rollback();//回滾事務(wù)        }        throw e;    }finally {        MyBatisUtils.closeSqlSession(session);    }}

我們在上述代碼中可以利用selectKey標(biāo)簽獲得對應(yīng)的新增主鍵,其實(shí)我們還可以利用另外一個屬性userGenerateKeys實(shí)現(xiàn)獲得新增主鍵,它們的區(qū)別在哪里呢?

SelectKey適用于所有數(shù)據(jù)庫,但需要根據(jù)不同的數(shù)據(jù)庫編寫對應(yīng)的獲得最后改變主鍵值得查詢語句userGenerateKeys只支持“自增主鍵”的數(shù)據(jù)庫(DB2,Oracle等沒有自增主鍵約束),但使用簡單,會根據(jù)不同的數(shù)據(jù)庫驅(qū)動自動編寫查詢語句,以下是該屬性的使用方法

insert 語句

如果要在Oracle中獲得新增后的主鍵,需要借助序列來實(shí)現(xiàn),其實(shí)是通過序列在執(zhí)行新增語句之前生成一個新的序列值并保存到主鍵字段中。更新與刪除

UPDATE t_goods    SET      title = #{title} ,      sub_title = #{subTitle} ,      original_cost = #{originalCost} ,      current_price = #{currentPrice} ,      discount = #{discount} ,      is_free_delivery = #{isFreeDelivery} ,      category_id = #{categoryId}    WHERE      goods_id = #{goodsId}

delete from t_goods where goods_id = #{value}

/** * 更新數(shù)據(jù) * @throws Exception */@Testpublic void testUpdate() throws Exception {    SqlSession session = null;    try{        session = MyBatisUtils.openSqlSession();        Goods goods = session.selectOne("com.dodoke.mybatis.resources.mappers.GoodsMapper.selectById", 739);        goods.setTitle("更新測試商品");        int num = session.update("com.dodoke.mybatis.resources.mappers.GoodsMapper.update" , goods);        session.commit();//提交事務(wù)數(shù)據(jù)    }catch (Exception e){        if(session != null){            session.rollback();//回滾事務(wù)        }        throw e;    }finally {        MyBatisUtils.closeSqlSession(session);    }}/** * 刪除數(shù)據(jù) * @throws Exception */@Testpublic void testDelete() throws Exception {    SqlSession session = null;    try{        session = MyBatisUtils.openSqlSession();        int num = session.delete("com.dodoke.mybatis.resources.mappers.GoodsMapper.delete" , 739);        session.commit();//提交事務(wù)數(shù)據(jù)    }catch (Exception e){        if(session != null){            session.rollback();//回滾事務(wù)        }        throw e;    }finally {        MyBatisUtils.closeSqlSession(session);    }}

預(yù)防SQL注入攻擊

在之前的學(xué)習(xí)中,我們了解到什么是SQL注入攻擊,并且在JDBC課程中也去實(shí)現(xiàn)了如何預(yù)防SQL注入攻擊。那么,在MyBatis中如何去進(jìn)行SQL注入攻擊的預(yù)防呢? 其實(shí),SQL注入攻擊的原理非常簡單,就在在接收用戶輸入的時候,不對接收的數(shù)據(jù)進(jìn)行任何的判斷和轉(zhuǎn)義,導(dǎo)致在接收時可能全盤接收到諸如單引號、or等一些SQL關(guān)鍵字。 所以,預(yù)防SQL注入攻擊需要的是對接收數(shù)據(jù)進(jìn)行判斷和轉(zhuǎn)義。在MyBatis中,這些工作其實(shí)早就已經(jīng)為我們準(zhǔn)備好了。MyBatis兩種傳值方式

${}文本替換,未經(jīng)任何處理對SQL文本替換#{}預(yù)編譯傳值,使用預(yù)編譯傳值可以預(yù)防SQL注入

在我們的實(shí)際使用中,更多的還是通過#{}的形式進(jìn)行傳值

 

責(zé)任編輯:

標(biāo)簽:

相關(guān)推薦:

精彩放送:

新聞聚焦
Top 一区二区三区电影_国产伦精品一区二区三区视频免费_亚洲欧美国产精品va在线观看_国产精品一二三四
国产精品美女xx| 国产精品视频免费在线观看| 在线欧美一区| 一区二区三区视频在线| 久久av一区二区三区漫画| 欧美日韩一区在线播放| 亚洲第一在线综合网站| 亚洲一品av免费观看| 国产精品毛片高清在线完整版| 夜夜夜久久久| 欧美网站在线观看| 亚洲性视频h| 激情一区二区三区| 老司机aⅴ在线精品导航| 在线高清一区| 国产精品乱码久久久久久| 禁断一区二区三区在线| 欧美黑人在线观看| 欧美一区二区在线免费播放| 亚洲国产精品va在线看黑人动漫| 欧美一区二区三区日韩| 曰韩精品一区二区| 国产精品劲爆视频| 久久久久久久97| av不卡在线观看| 国产亚洲日本欧美韩国| 欧美三级网址| 麻豆精品精品国产自在97香蕉| 亚洲一区二区精品视频| 精品成人一区| 国产欧美精品一区| 国产精品美女久久久久aⅴ国产馆| 久久免费视频观看| 国产精品精品视频| 欧美xxxx在线观看| 久久中文字幕一区| 久久国产毛片| 久久久精品免费视频| 新狼窝色av性久久久久久| 99国产精品视频免费观看一公开| 亚洲高清资源综合久久精品| 国产区二精品视| 国产婷婷色一区二区三区四区| 欧美成年人视频网站| 久久只有精品| 欧美日本一区二区高清播放视频| 久久亚洲国产精品日日av夜夜| 午夜精品久久久久久久99热浪潮| 中文日韩在线视频| 性做久久久久久久免费看| 亚洲美女在线国产| 亚洲综合99| 久久理论片午夜琪琪电影网| 久久精品视频在线看| 欧美大香线蕉线伊人久久国产精品| 久久久噜噜噜久久久| 久久香蕉国产线看观看网| 欧美欧美午夜aⅴ在线观看| 欧美日韩免费一区| 国产精品高精视频免费| 久久九九久精品国产免费直播| 久久久久久久久久久久久久一区| 男人的天堂亚洲| 国产精品海角社区在线观看| 国模精品娜娜一二三区| 亚洲日本va在线观看| 国产亚洲一区二区在线观看| 亚洲激情六月丁香| 亚洲桃花岛网站| 蜜臀久久99精品久久久久久9| 欧美无乱码久久久免费午夜一区 | 欧美精品久久久久久久久老牛影院| 欧美激情一区二区三区| 狠狠v欧美v日韩v亚洲ⅴ| 亚洲欧美国产高清| 欧美午夜影院| 在线一区免费观看| 国产精品久久久久久久电影| 中文一区二区在线观看| 欧美精品 日韩| 一区二区三区国产在线观看| 欧美日韩岛国| 亚洲男人的天堂在线| 欧美区在线观看| 日韩视频在线一区二区三区| 欧美日韩高清在线播放| 在线观看视频亚洲| 久久亚洲春色中文字幕久久久| 国产精品视频yy9099| 亚洲欧美国产日韩中文字幕| 国产精品美腿一区在线看 | 亚洲永久视频| 国产一区在线播放| 欧美精品在线免费播放| 欧美一级午夜免费电影| 国产精品久久久久久久7电影| 亚洲尤物视频网| 亚洲国产精品久久人人爱蜜臀| 欧美精品成人一区二区在线观看| 亚洲一级在线| 亚洲精品在线电影| 精品成人国产| 国产日韩欧美制服另类| 国产精品一区二区三区久久久| 国产综合色一区二区三区| 国产精品久久久久久久久久免费看 | 欧美成人69| 亚洲国产视频一区二区| 91久久精品网| 在线亚洲电影| 亚洲视频免费观看| 亚洲国产天堂久久国产91| 中文在线一区| 亚洲一区二区三区精品动漫| 欧美视频在线观看免费网址| 亚洲电影有码| 欧美日韩一区成人| 久久精品成人欧美大片古装| 噜噜噜在线观看免费视频日韩| 欧美精品一区三区在线观看| 欧美日韩在线视频一区二区| 欧美 日韩 国产在线| 国产欧美精品va在线观看| 亚洲精品黄色| 老司机免费视频久久| 国内精品久久久| 欧美一二三视频| 国产精品电影在线观看| 夜夜精品视频| 欧美人与性动交a欧美精品| 亚洲国产精品久久久久婷婷884| 销魂美女一区二区三区视频在线| 欧美日韩一区精品| 99re热这里只有精品免费视频| 欧美激情一区二区三区全黄| 在线欧美福利| 欧美高清不卡在线| 99精品视频免费全部在线| 欧美日产国产成人免费图片| 亚洲精品一区二区三区99| 欧美激情中文字幕一区二区 | 久久久噜噜噜久久狠狠50岁| 国产欧美欧美| 久久精品国产91精品亚洲| 国产一区二区三区在线播放免费观看| 欧美一级在线播放| 黄网站免费久久| 欧美国产日本高清在线| 日韩天堂av| 欧美色播在线播放| 亚洲一区二区三区精品视频| 国产精品蜜臀在线观看| 欧美在线|欧美| 亚洲国产99| 欧美日韩午夜| 欧美国产亚洲另类动漫| 国产精品yjizz| 久久国产88| 欧美韩国日本一区| 国产精品一区毛片| 伊人久久亚洲美女图片| 亚洲一区影音先锋| 麻豆精品视频在线观看视频| 久久久久综合一区二区三区| 国产精品videossex久久发布| 黄色资源网久久资源365| 亚洲欧美综合国产精品一区| 一区二区在线观看视频| 狂野欧美激情性xxxx欧美| 亚洲国产欧美精品| 欧美激情国产高清| 亚洲天堂av综合网| 国产视频久久| 免费看精品久久片| 一本色道久久综合亚洲精品小说| 亚洲欧美国产va在线影院| 免费欧美在线视频| 精品1区2区| 国产精品理论片| 99在线热播精品免费| 亚洲美女淫视频| 欧美午夜宅男影院| 久久久精品国产一区二区三区 | 亚洲欧美日本国产专区一区| 国产精品美腿一区在线看| 老司机午夜精品视频| 午夜在线a亚洲v天堂网2018| 今天的高清视频免费播放成人| 欧美国产视频在线| 久久综合伊人| 欧美专区福利在线| 亚洲综合三区| 亚洲精品1区| 激情成人av在线| 欧美日韩激情小视频| 欧美一区二区三区在线视频 | 韩国成人精品a∨在线观看| 欧美日韩国产区| 欧美va天堂va视频va在线| 欧美亚洲自偷自偷|