<table><tbody><tr><td>為什么要使用框架?使用軟件框架的優點總結</td></tr></tbody></table>
思維導圖
導學
MyBatis是一個大名鼎鼎的ORM框架,對于我們進行數據庫開發有著非常優秀的支持。 首先我們要了解,什么是框架?框架,即 framework。其實就是某種應用的半成品,就是一組組件,供你選用完成你自己的系統。簡單說就是使用別人搭好的舞臺,你來做表演。而且,框架一般是成熟的,不斷升級的軟件。
【資料圖】
打個比方,Java 框架跟建筑中的框架式結構是一樣的。使用了框架(鋼筋+混凝土)以后,你所專著的只是業務(非承重墻構建不同格局),當然是在遵守框架的協議上開發業務。
為什么要使用框架? 因為軟件系統發展到今天已經很復雜了,特別是服務器端軟件,涉及到的知識,內容,問題太多。在某些方面使用別人成熟的框架,就相當于讓別人幫你完成一些基礎工作,你只需要集中精力完成系統的業務邏輯設計。而且框架一般是成熟,穩健的,你可以處理系統很多細節問題,比如,事物處理,安全性,數據流控制等問題。還有框架一般都經過很多人使用,所以結構很好,所以擴展性也很好,而且它是不斷升級的,你可以直接享受別人升級代碼帶來的好處。 比如,我們可以自己DIY一臺電腦,這就是因為我們可以使用一個現成的主板,在這個主板上有著許多規范的接口可供其他設備加入。軟件開發中的框架
框架是可被應用開發者定制的應用骨架框架是一種規則,保證開發者遵守相同的方式開發程序框架提倡“不要重復造輪子”,對基礎功能進行封裝
使用軟件框架的優點總結
極大的提高了開發的效率統一的編碼規則,利于團隊管理靈活配置的應用,擁有更好的維護性
SSM框架介紹
Spring 對象容器框架,提供底層的對象管理,是框架的框架,其他的框架都要基于該框架進行開發。Spring MVC web開發框架,用于替代servlet,提供Web底層的交互,進行更有效的web開發。Mybatis 數據庫框架,用于簡化數據庫操作,對JDBC進行了封裝及擴展,提供了數據庫的增刪改查的便捷操作
補充介紹:SSH框架其實指的是Spring+Struts2+Hibernate框架,該框架更貼近于我們之前的Java Web學習內容,較為老舊,需要較多的配置文件,并不怎么方便。
補充介紹:常用的數據庫框架其實還有MyBatis Plus和iBatis框架等。
MyBatis框架介紹
MyBatis是優秀的持久層框架 --將內存中的數據保存在數據庫中MyBatis使用XML將SQL與程序解耦,便于維護MyBatis學習簡單,執行高效,是JDBC的延伸
對象的兩種狀態:
瞬時狀態:程序中運行的對象,對象保存在內存中,當程序中斷或者結束(計算機關閉或重啟),該狀態對象不會保留。持久化狀態:把對象數據保留在文件中,文件存儲在永久的存儲介質里(光盤、硬盤),當程序中斷或者計算機重啟斷電,該狀態的對象會永久保留。 所謂的持久化就是把瞬時狀態的對象轉換為持久化狀態的對象。
MyBatis開發流程-非xml形式
引入MyBatis依賴創建核心配置文件創建實體(Entity)類創建Mapper映射文件初始化SessionFactory利用SqlSession對象操作數據
ORM框架
O:java Object 即 Java 中的對象; R:relationship 即關系數據庫; M:mapping 將JAVA中的對象映射成關系型數據庫中的表;
MyBatis 框架是一個可以自定義 SQL 和 OR 映射的持久化框架; 框架拋棄了大部分的 JDBC 代碼,也不需要手工設置參數以及結果集的操作; 框架使用簡單的 XML 配置或者注解來映射數據類型和關系,相對于 Hibernate 框架,MyBatis 是一種半自動化的 ORM 實現。
MyBatis配置
在本課程中,MyBatis將依賴于Maven進行管理。 在MyBatis中,使用xml進行配置,有一個約定俗成的文件名叫做mybatis-config.xml,它是mybatis的一個核心配置文件。
1. Mybatis采用xml文件配置數據庫環境信息2. Mybatis環境配置標簽3. environment配置包含數據庫驅動,URL,用戶名和密碼
前期準備-新建項目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> <!-- 可能阿里云倉庫的地址會發生變化,需要查找最新的地址 --> <url>https://maven.aliyun.com/repository/public</url> </repository></repositories><dependencies> <!-- 數據庫驅動依賴 --> <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>
前期準備-數據庫設計下載地址https://pan.baidu.com/s/1xgxXH9tPn0O_Qf5QfmmbBg 提取碼 mso3設置idea連接數據庫resources目錄下設置mybatis的核心配置文件mybatis-config.xml
SqlSessionFactory & SqlSession
SqlSessionFactory是MyBatis中的一個重要的對象,它是用來創建SqlSession對象的,而SqlSession用來操作數據庫的。介紹:
SqlSessionFactory是MyBatis的核心對象SqlSessionFactory用于初始化MyBatis,讀取配置文件。是一個工廠方法,用于創建SqlSession對象。要保證SqlSessionFactory在應用全局中只存在唯一的對象,通常會使用靜態類的方式對其進行初始化。
SqlSession是MyBatis用來操作數據庫的一個核心對象,不那么嚴謹的說,可以將SqlSession看做類似于我們之前學習過的JDBC的連接接口對象(Connection)執行接口對象(PreparedStatement)的組合,用來執行CRUD操作。介紹:
SqlSession是MyBatis操作數據庫的核心對象SqlSession使用JDBC的方式與數據庫交互SqlSession對象提供了數據表的CRUD方法
示例引入Junit組件進行測試應用 依賴:
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單元測試用例類
規范存放在maven項目的test文件夾中 */ public class MyBatisTest {
@Test public void sqlSessionFactoryTest() throws IOException {//通過MyBatis提供的資源類,獲取對應的配置文件作為字符流讀取 //getResourceAsReader方法會默認的從當前classpath類路徑下加載文件 Reader reader = Resources.getResourceAsReader(“mybatis-config.xml”); //初始化SqlSessionFactory,并同時解析mybatis-config.xml文件 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); System.out.println(“SqlSessionFactory對象加載成功”); //創建SqlSession對象,用于與數據庫產生交互,注意SqlSession它是JDBC的擴展類 SqlSession sqlSession = null; try {sqlSession = sqlSessionFactory.openSession(); //在SqlSession對象底層存在Connection(java.sql)連接對象,可以通過getConnection方法得到該對象 Connection connection = sqlSession.getConnection(); //該connection對象的創建僅做演示測試用,在mybatis中,無需使用任何與JDBC有關的類 System.out.println(connection); } catch (Exception e) {e.printStackTrace(); } finally {if(sqlSession != null) {//在mybatis-config.xml文件中,dataSource節點type屬性: //如果type=“POOLED”,代表使用連接池,close則是將連接回收到連接池中 //如果type=“UNPOOLED”,代表直連,close則會調用Connection.close()方法關閉連接 //這是配置帶來的底層處理機制的不同 sqlSession.close(); } } }
}
設置MybatisUtils工具類
在之前的課程中,我們提到需要保證SqlSessionFactory在全局中保證唯一,那么如何保證該SqlSessionFactory在應用全局保證唯一呢? 通過額外創建的工具類MybatisUtils對SqlSessionFactory對象的初始化以及SqlSession對象的創建和釋放方法進行封裝 。說明:
一般工具類放在utils包下;用static代碼塊對靜態對象進行初始化;這邊我們在異常捕獲后將類的初始化的過程中產生的異常拋出,為了外界能捕獲到這個異常信息并進行后續處理,而不是直接終止運行程序,我們需要將異常拋出;提供SqlSession對象的創建與釋放方法,工具類的大多數方法要使用static進行描述。
工具類代碼
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工具類,創建全局唯一的SqlSessionFactory對象 */ public class MyBatisUtils {//設置私有靜態屬性,因為靜態內容屬于類而不屬于對象,且擁有全局唯一的特性 private static SqlSessionFactory sqlSessionFactory = null;
//利用靜態代碼塊在初始化類時實例化sqlSessionFactory屬性 static {try {Reader reader = Resources.getResourceAsReader(“mybatis-config.xml”); sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); } catch (IOException e) {e.printStackTrace(); //需要拋出初始化的異常,并且傳入捕捉到的異常,形成一條完整的異常鏈 //以便于通知調用者 throw new ExceptionInInitializerError(e); } }
/**
獲取數據庫交互SqlSession@return SqlSession對象 */ public static SqlSession openSqlSession() {return sqlSessionFactory.openSession(); }
/**
釋放一個有效的SqlSession對象@param sqlSession 準備釋放的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數據查詢
在MyBatis中,雖然我們可以使用MyBatis之前的舊形式,寫出如同JDBC那樣Java代碼和SQL代碼混合的數據操作命令,但是我們不建議大家這么做! 對于MyBatis數據查詢,可以總結出如下的步驟:1. 創建實體類(Entity)在main/java下創建com.dodoke.mybatis.entity包,entity包下創建數據庫中t_goods表對應的Goods商品實體類,將數據表中的字段對應在實體類中增加一系列的私有屬性及getter/setter方法,屬性采用駝峰命名。
/** * 數據庫t_goods表對應映射的實體類 */public class Goods { private Integer goodsId;//商品編號 private String title;//標題 private String subTitle;//子標題 private Float originalCost;//原始價格 private Float currentPrice;//當前價格 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. 創建Mapper XML說明SQL語句第二步,第三步結合使用,具體內容在第三步中。3. 在Mapper XML中增加SQL語句對應標簽在main/resources下創建新的子目錄mappers,mappers代表映射器,里面存放的都是xml文件。創建GoodsMapper.xml文件來說明實體類和數據表的對應關系(和哪個數據表對應,屬性和字段怎么對應)。 說明:A.根節點通過增加不同的命名空間namespace來區分不同的mapper文件,通常我們會將針對一張表操作的SQL語句放置在一個mapper文件中。B.語句節點的id屬性為別名,相當于SQL名稱,同一個namespace下id要唯一,不同的namespace可以重名;因此namespace的設置就很有必要,不然調用SQL的時候分不清哪個idC.語句節點的resultType屬性代表返回的對象是什么,為實體類的完整路徑,在SQL語句執行完后會自動的將得到的每一條記錄包裝成對應的實體類的對象;
select * from t_goods order by goods_id desc limit 10
4. 在mybatis-config.xml中增加Mapper XML文件聲明其實就是讓MyBatis認識新創建的GoodsMapper.xml: 在mybatis-config.xml中添加mappers標簽,這樣MyBatis在初始化的時候才知道這個GoodsMapper.xml的存在。
5. 利用SqlSession執行Mapper XML中的SQL語句
/** * select查詢語句執行 * @throws Exception */@Testpublic void testSelectAll() throws Exception { SqlSession session = null; try{ session = MyBatisUtils.openSqlSession(); //selectList代表查詢多條數據,selectOne代表查詢一條結果 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); }}
對于這樣的查詢,其實獲取到的數據是存在數據丟失的,這是因為我們的查詢結果類型字段和表中字段名不能匹配!6. 在mybatis-config.xml中開啟駝峰命名映射其實第六步應該放在第五步之前,這里只是給大家作為演示。
goodsId -->
MyBatis的SQL傳參
在實現CRUD等操作的時候,有很多的SQL條件數據其實是通過接受前臺動態傳遞過來的參數決定的。那么如何設置這些SQL語句的參數呢? 在數據操作節點中,可以添加parameterType屬性指定參數類型,并采用#{param}的形式接受傳入的參數。 示例: GoodsMapper.xml
select * from t_goods where goods_id = #{value}
測試:
/** * 傳遞單個SQL參數 * @throws Exception */@Testpublic void testSelectById() throws Exception { SqlSession session = null; try{ session = MyBatisUtils.openSqlSession(); //傳入的參數類型需要和對應數據操作節點中指明的參數類型一致 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參數@throws Exception */ @Test public void
testSelectByPriceRange() throws Exception {SqlSession session = null;
try{session = MyBatisUtils.openSqlSession(); Map param = new HashMap();
//map中的key-value的key值,需要和數據操作節點中參數名一致 param.put(“min”,100); param.put(“max” ,
500); param.put(“limt” , 10); List
多表關聯查詢
在之前的學習中,我們針對的都是一個表的查詢,那么如何針對多表進行聯合查詢呢? 其實我們可以將返回的結果變為Map類型,這樣MyBatis就會將結果封裝為Map集合中對應的鍵值對
select g.* , c.category_name from t_goods g , t_category c where g.category_id = c.category_id
/** * 利用Map接收關聯查詢結果 * @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); }}
我們可以看到,該方法返回的結果為數據庫中表對應的原始字段名為key值,而且查詢到的結果的順序是混亂的。 為了保證我們等到的結果的順序和數據庫中的順序一致,我們需要使用LinkedHashMap。
LinkedHashMap是采用鏈表形式的HashMap,他在進行數據提取的時候是按照插入數據時的順序進行提取保存的,不會出現亂序的情況。使用LinkedHashMap來接收數據是常用的,因為公司的數據結構較為復雜,需要多表關聯查詢,LinkedHashMap可以有效進行數據的擴展,非常靈活。缺點:太過靈活,任何查詢結果都會被LinkedHashMap包裝在內,相比較實體類而言,缺少了編譯時檢查,是很容易出錯的。
select g.* , c.category_name,"1" as test from t_goods g , t_category c where g.category_id = c.category_id
其實針對于這樣的多表查詢,我們還可以通過修改實體類來實現,顯得不夠靈活,但是卻可以保證在編譯的時候進行檢查。具體選用哪種方式可以根據實際情況進行選擇。 PS:注意,在之前我們的學習中,我們是利用在mybaits-config.xml文件中設置駝峰映射的方式,來解決字段和實體類屬性名稱不能匹配的問題的,但是我們也可以設置在查詢的時候起別名的方式,解決這個問題。
ResultMap結果映射
介紹:
ResultMap可以將查詢結果映射為復雜類型的Java對象。ResultMap適用于Java對象保存多表關聯結果ResultMap是MyBatis關聯的核心所在,支持對象關聯查詢等高級特性
在上節課程中,我們也提到過,可以為了查詢結果去修改實體類。但是,這種方式在標準的mybatis開發下是不太建議的。實體類僅僅和數據表對應就好,不要添加一些冗余的屬性,但是在實際開發中,我們有時為了方便,實際上較多的還是采用修改實體類的形式。 但是,采用DTO,數據擴展類開發的形式,我們同學們必須掌握。 在com.dodoke.mybatis包下面新建一個dto包,新建GoodsDTO類。
DTO是一個特殊的JavaBean,數據傳輸對象。對原始對象進行擴展,用于數據保存和傳遞。
/** * 擴展類,數據傳輸對象 */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屬性,添加結果映射
select g.* , c.*,"1" as test from t_goods g , t_category c where g.category_id = c.category_id
測試
/** * 利用ResultMap進行結果映射 * @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); }}
其實我們可以繼續擴展,比如我現在不僅僅想要得到category_name產品名稱,還想要獲得其他屬性,那么我們該怎么辦呢? 新建t_category表的實體類
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數據對象
package com.dodoke.mybatis.dto;
import com.dodoke.mybatis.entity.Category; import com.dodoke.mybatis.entity.Goods;
/**
擴展類,數據傳輸對象 */ 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; } }
修改映射結果集
select g.* , c.*,"1" as test from t_goods g , t_category c where g.category_id = c.category_id
MyBatis數據寫入
在之前的課程中,我們實現了MyBatis的數據查詢工作,接下來,我們來看看如何實現數據的新增,修改和刪除工作。
數據庫事務
提到數據庫的寫入操作,就離不開數據庫的事務。數據庫事務是保證數據操作完整性的基礎所有從客戶端發來的新增修改刪除操作,都會被事務日志所記錄,我們形象的將事務日志看成流水賬,它記錄客戶端發來的所有寫操作的前后順序, 當客戶端向MySQL服務器發起了一個commit提交命令的時候,事務日志才會將這三個數據同時的寫入到數據表中,在commit的時候才是真正的往數據表寫入的過程,當這三條數據都被成功寫入到數據表中后,剛才所產生的事務日志都會被清空掉。 假設如果客戶端在處理這些數據的時候,數據1和數據2執行成功,數據3因為各種原因沒有執行成功的話,客戶端會發起一個rollback回滾命令,當MySQL收到了rollback回滾命令后,當前事務日志中的所有已經產生的數據都會被清除,這就意味著前面已經產生的數據1和數據2不會放入到數據表中,只有當所有數據都完成的時候,在由客戶端發起commit提交,數據才能成功的寫入。要么數據全部寫入成功,要么中間出現了任何問題,全部回滾,保證了數據的完整性
案例
修改MyBatisUtils
/** * 獲取數據庫交互SqlSession * @return SqlSession對象 */public static SqlSession openSqlSession() { //默認SqlSession對自動提交事務數據(commit) //設置false代表關閉自動提交,改為手動提交事務數據 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()
/** * 新增數據 * @throws Exception */@Testpublic void testInsert() throws Exception { SqlSession session = null; try{ session = MyBatisUtils.openSqlSession(); Goods goods = new Goods(); goods.setTitle("測試商品"); goods.setSubTitle("測試子標題"); goods.setOriginalCost(200f); goods.setCurrentPrice(100f); goods.setDiscount(0.5f); goods.setIsFreeDelivery(1); goods.setCategoryId(43); //insert()方法返回值代表本次成功插入的記錄總數 int num = session.insert("com.dodoke.mybatis.resources.mappers.GoodsMapper.insert", goods); session.commit();//提交事務數據 System.out.println(goods.getGoodsId()); }catch (Exception e){ if(session != null){ session.rollback();//回滾事務 } throw e; }finally { MyBatisUtils.closeSqlSession(session); }}
我們在上述代碼中可以利用selectKey標簽獲得對應的新增主鍵,其實我們還可以利用另外一個屬性userGenerateKeys實現獲得新增主鍵,它們的區別在哪里呢?
SelectKey適用于所有數據庫,但需要根據不同的數據庫編寫對應的獲得最后改變主鍵值得查詢語句userGenerateKeys只支持“自增主鍵”的數據庫(DB2,Oracle等沒有自增主鍵約束),但使用簡單,會根據不同的數據庫驅動自動編寫查詢語句,以下是該屬性的使用方法
insert 語句
如果要在Oracle中獲得新增后的主鍵,需要借助序列來實現,其實是通過序列在執行新增語句之前生成一個新的序列值并保存到主鍵字段中。更新與刪除
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}
/** * 更新數據 * @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();//提交事務數據 }catch (Exception e){ if(session != null){ session.rollback();//回滾事務 } throw e; }finally { MyBatisUtils.closeSqlSession(session); }}/** * 刪除數據 * @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();//提交事務數據 }catch (Exception e){ if(session != null){ session.rollback();//回滾事務 } throw e; }finally { MyBatisUtils.closeSqlSession(session); }}
預防SQL注入攻擊
在之前的學習中,我們了解到什么是SQL注入攻擊,并且在JDBC課程中也去實現了如何預防SQL注入攻擊。那么,在MyBatis中如何去進行SQL注入攻擊的預防呢? 其實,SQL注入攻擊的原理非常簡單,就在在接收用戶輸入的時候,不對接收的數據進行任何的判斷和轉義,導致在接收時可能全盤接收到諸如單引號、or等一些SQL關鍵字。 所以,預防SQL注入攻擊需要的是對接收數據進行判斷和轉義。在MyBatis中,這些工作其實早就已經為我們準備好了。MyBatis兩種傳值方式
${}文本替換,未經任何處理對SQL文本替換#{}預編譯傳值,使用預編譯傳值可以預防SQL注入
在我們的實際使用中,更多的還是通過#{}的形式進行傳值
標簽:
相關推薦:
精彩放送:
- []今日觀點!世茂股份擬召開債券持有人會議,所有存續公司債12月9日開市起停牌
- []多家房企拋出股權融資方案 地產行業困境反轉?
- []消息!又一家大行看多!摩根士丹利:中國股票將跑贏全球
- []金溢科技:關于股東人數情況,詳見公司最近一期定期報告
- []格力地產調整重組方案:募集配套資金超8億元,明日復牌
- []【播資訊】“小步快跑”供地風向標顯現 武漢率先開啟第六批集中供地
- []世界熱點評!45個重點城市城鎮化率:這六個城市超90%
- []世界熱文:星輝娛樂:(1)近兩年,受多種因素影響,公司收入和凈利潤有所下滑
- []全球速訊:被六?。ㄊ校┘{入新冠肺炎診療方案的化痰止咳中藥是怎樣煉成的?
- []博雅生物:公司一直在積極推進漿站拓展工作,申請新設漿站存在不確定性,如公司獲批新設,將及時披露
- []原油交易提醒:美國料陷入技術性衰退,需求減弱拖累油價五連陰
- []當前資訊!融創發布境外債務初步重組框架:擬將30至40億美元借款轉為普通股等
- []世界快看點丨內蒙一機:公司民品業務涉及鐵路車輛及相關零部件,訂單任務充足,重要合同簽訂情況均在臨時公告中有披露
- []世界頭條:二手房買家因賣家換掉家具拒付尾款遭起訴,法院:出賣人構成違約
- []2022財年虧損18.16億,靠港府“續命”的香港海洋公園能走多遠?
- []每日快看:大葉股份:公司綜合考慮質量、性能、交期、價格等多個因素,汽油割草機零部件為全球化采購
- []晉億實業:公司主要從事各類緊固件的研究和開發,生產銷售各類緊固件、鐵道扣件等產品,產品遠銷國內外
- []融創公布境外債重組重大進展 加速回到健康發展軌道
- []新力被債權人放棄了
- []房企融資“三箭齊發”,置業信心能否回暖?
- []【環球速看料】國際油價 7日 顯著下跌
- []獨立儲能電站商業投資價值的識別與分析
- []甘肅多措并舉保障冬季電力供應
- []天天快報!電化學儲能是什么意思?電化學儲能主要包括哪些?
- []焦點!成立1年,業務覆蓋30+國家和地區!這家儲能公司怎么這么猛?
- []今日看點:車險年底買是否優惠些 年底買車保險會不會優惠些
- []【全球熱聞】美股異動 | 中概教育股普漲 新東方(EDU.US)漲超9%
- []【天天新要聞】定向增發+公司債 大名城拋出約50億元再融資方案
- []保險報案有效期是多久 一般保險報案的有效期限是多長時間
- []保險不續費自動退保嗎 保險要是不續費會自行退保嗎
- []參保人就是被保險人嗎 被保險人是不是參保人
- []公積金一定要留余額嗎 公積金必須留余額嗎
- []歲寶百貨深圳宏發大世界購物廣場門店提前終止租賃協議
- []天天滾動:2023年Q1全球計劃運力預計達12億,法國境內短途航班取消將為對手創造機會
- []頭條:川潤股份:12月7日公司高管李輝減持公司股份合計5.37萬股
- []零售云平臺多點數智赴港IPO 騰訊IDG是股東
- []【環球熱聞】新湖中寶擬引入衢州國資 由控股股東出讓不超過10%股權
- []科藍軟件:12月7日公司高管王安京減持公司股份合計14.84萬股
- []全球快訊:龍佰集團:12月7日公司高管張海濤增持公司股份合計1600股
- []世界球精選!歷時八個月 南京正式實施商品房預售資金監管新政
- []當前信息:北京銀行與重點房地產企業簽約,提供意向性融資總額2500億元
- []環球焦點!格力地產重啟收購珠海免稅 構建三大業務板塊
- []美國房地產大起大落后迎來投資機會
- []每日視點!新柴股份:12月7日公司高管周高峰減持公司股份合計2000股
- []北京銀行:為萬科、中海、招商等重點房企提供意向性融資總額2500億元
- []快資訊丨佳力奇:加大自主創新力度 持續鞏固技術堡壘
- []當前播報:群興玩具:截止目前,公司未存在籌劃重大資產重組等事項
- []現貨黃金持穩,市場權衡兩大前景,警惕通脹“掛自動擋”
- []環球今日報丨中指院: A股ESG報告披露率較低
- []人福醫藥:12月7日徐華斌減持公司股份合計13萬股
- []每日快訊!越秀地產前11月合同銷售1029.4億元 完成年度銷售目標83%
- []交建股份:11月28日至12月1日公司高管胡先寬、儲根法、曹振明、陳明洋、施秀瑩減持公司股份合計72.02萬股
- []物業流拍、招租進行中,天橋百貨覓新生
- []當前關注:合生創展前11月總合約銷售額281.13億元 同比下降27.73%
- []全球觀熱點:中指院:二十城物業服務收費穩中略升
- []新化股份:12月6日至12月7日公司高管方軍偉減持公司股份合計8000股
- []寶龍地產前11月合約銷售總額約379.3億元
- []【天天新要聞】萬通發展擬投資5億元設立通信業務全資子公司
- []全球速讀:沃森生物:公司近年來持續從銷售體系建設、消費者教育、終端服務和渠道布局多維度打造產品品牌和市場影響力
- []大名城擬定增不超過30億元 主要投向上海5個項目
- []天天熱文:黃山膠囊:我公司根據相關法律、法規及規范性文件的規定標準進行信息披露
- []黃山膠囊:我公司與熊去氧膽酸膠囊暫無合作
- []【新要聞】中南建設三只債券獲持有人會議通過 豁免美元債交叉違約
- []每日快報!大名城擬發行本金不超過20億元的公司債券
- []全球即時看!落子布局電池租賃!寧德時代或許將用換電服務深度綁定車企
- []越秀地產:前11月合同銷售額約為人民幣1029.4億元
- []環球快看:中華企業擬非公開發行股票不超過總股本30% 用于“保交樓“項目
- []德藝文創:截至2022年11月30日(目前最新數據)的股東人數為12,383
- []全球熱門:中駿集團提前匯出12.87億以兌付購房尾款ABS本息 年內公開債務“零違約”
- []環球報道:杭州規定保租房租金應低于同類房源市場價格 2023年1月5日起施行
- []全球動態:奧馬電器:公司產品為冰箱冷柜,冰箱冷柜為居民生活必備的耐用消費品
- []全球速看:合肥搭建線上服務平臺 開啟“二手房互換”新模式
- []每日資訊:金石亞藥:目前公司產能及備貨充足,能夠滿足市場需求
- []實至名歸,箭牌家居榮獲行業唯一“2022國際CMF設計獎”金獎!
- []快資訊:雖遲但到 | 2022 環球旅訊峰會,12月底上海見
- []天天速遞!圖解貴金屬及外匯:多空成本+最單邊押注(2022/12/08周四)
- []熱資訊!中駿安全度過行業低谷期,年內償還境內外公開債務超70億元
- []世界熱門:豪森股份:公司2022年度向特定對象發行A股股票的定價基準日為發行期首日
- []財面兒丨中駿集團控股1-11月實現累計合同銷售金額約544.42億元
- []天天新動態:西安飲食:該公司并未實際開展業務
- []青島中程:公司印尼工業園現場員工,克服多方困難,全力推進RKEF鎳電項目剩余工程的建設,爭取早日交付
- []天天日報丨財面兒|德信中國前11月累計合約銷售金額336億元
- []全球看熱訊:物業丨卓越商企服務:全資附屬公司收到仲裁通知書
- []【新要聞】比特幣概念股票有哪些?2021年比特幣概念股一覽?
- []快消息!核電股票有哪些?2018核電概念股龍頭有哪些?
- []當前快訊:股市熔斷機制是什么意思?股市熔斷機制有什么意義?
- []今日要聞!物業丨華潤萬象生活:與華潤置地訂立商業運營服務框架協議之補充協議
- []全球熱議:鉬板概念股是哪些?鉬板股票一覽?
- []資訊推薦:合力泰:公司目前未涉及該業務
- []全球熱推薦:甲醇概念上市公司有哪些?甲醇概念股一覽?
- []全球短訊!2020年股市休市放假怎么安排的?A股全年休市一覽?
- []2020新能源電池概念股票有哪些?2020新能源電池概念股票一覽?
- []全球實時:哪些是智能家居概念股?智能家居概念股名單一覽?
- []全球消息!抄底是什么意思?抄底的四大形態是怎樣的?
- []【熱聞】磷化工股票有哪些?相關磷化工概念股票有哪些?
- []【世界新要聞】面板概念龍頭股有哪些?2021年面板概念股有哪些?
- []碳中和是什么概念?碳中和概念股有哪些?
- []每日消息!太陽能電池背板上市公司有哪些?太陽能電池背板概念股一覽
- []全球滾動:虛擬現實板塊股票有哪些?虛擬現實概念股票一覽?
- []全球動態:橡膠股票龍頭股有哪些?橡膠股票有哪些?
- B站注冊資本增幅400%至5億 目前由陳睿全資持股
- 光源資本出任獨家財務顧問 沐曦集成電路10億元A輪融資宣告完成
- 巨輪智能2021年上半年營收11.24億元 期內研發費用投入增長19.05%
- 紅棗期貨尾盤拉升大漲近6% 目前紅棗市場總庫存約30萬噸
- 嘉銀金科發布2021年Q2財報 期內凈利潤達1.27億元同比增長208%
- 成都銀行2021上半年凈利33.89億元 期內實現營收同比增長17.27億元
- 汽車之家發布2021年第二季度業績 期內新能源汽車品牌收入增長238%
- 中信銀行上半年實現凈利潤290.31億元 期末不良貸款余額706.82億元
- 光伏概念掀起漲停潮交易價格創新高 全天成交額達1.29億元
- 上半年生物藥大增45% 關鍵財務指標好轉營收賬款持續下降
- 世界快看:俄油上限剛出臺沖擊就已顯現?俄羅斯原油出口出現急劇減少
- 電纜上市公司有哪些?相關上市公司龍頭有哪些?
- 世界快看:核電板塊龍頭股票有哪些?核電概念股票有哪些?
- 世界微資訊!食用油板塊龍頭股票有哪些?食用油板塊龍頭股票有哪些?
- 環球視訊!2021年騰訊概念股票有哪些?騰訊概念股一覽?
- 森馬服飾股票屬于什么板塊?森馬服飾股票屬于哪些概念股?
- MINE's TALK對話祝羽捷,「一個自己的房間」 傳遞自洽生活哲學
- 世界今頭條!國際油價多頭須盡快離場,該指標暗示需求擔憂仍唱主角
- 中交路橋建設20億元綠色公司債券已提交注冊
- 世界熱推薦:中建信息10億元應收賬款資產支持ABS已獲受理
- 產業物流線上季快訊 | 王少華:險資在物流上的投資機會將增多
- 綠城房地產擬發行90億元中票 項目狀態為“預評中”
- 上海地鐵全線受理云閃付乘車碼“一碼通行”功能
- 焦點快播:粵萬年青:公司產品消炎利膽片功能主治為“清熱,祛濕,利膽
- 精彩看點:味知香:公司新產能預計前期先進行部分投產,后期根據生產運營情況,逐步釋放產能
- 香港發展局:一般項目由“生地”變成可建屋“熟地”的時間減至4年
- 環球百事通!錫裝股份:公司沒有上述高送轉的計劃。感謝您的關心支持!
- 焦點短訊!金價有望繼續走強!世界黃金協會稱全球央行繼續購金,三季度購買量猛增至400噸
- 加碼歐洲儲能市場 優能新能源發布新一代儲能逆變器
- 今熱點:Expedia:國際旅行和商旅有望在2023年恢復元氣
- 世界熱點!美原油交易策略:經濟衰退擔憂籠罩市場,油價跌勢難改
- 頭條焦點:國際金價持穩,市場擔心美聯儲繼續維持強硬鷹派立場
- 當前速看:現貨黃金交易策略:初請數據來襲,關注200日均線阻力
- 攜程發布“2023旅游振興A計劃”,三“重”戰略促萬億消費
- 天天即時看!冬季冰雪游升溫,同程旅行冰雪搜索熱度增長150%
- 全球要聞:國際金價或回踩1772美元
- 環球即時:ThinkBook16p對比聯想小新 Pro16 2021款哪個值得更好?詳細評測
- 焦點熱文:北京樓市,變了
- 場景化營銷精準發力 錢小樂持續優化金融服務質效
- 環球熱頭條丨Excel函數之VLOOKUP()怎么使用?一文搞懂Excel函數之VLOOKUP()使用
- “新十條”發布后,這個省份開始搶游客了
- 全球最新:魏小安:旅游業大局三個月可定,六個月可起
- 環球百事通!FFT是什么意思?FFT的詳解
- 天天微頭條丨disable怎么運用?disable簡單易理解用法
- 環球快報:格式化時間是什么?抽象類DateFormat是什么?
- 焦點!中駿集團:前11月合同銷售額約544.42億元
- 全球即時:order by是什么意思?order by的詳解
- 天天熱消息:java.lang.NullPointerException解決方案是什么?
- 焦點消息!誅仙3新手卡怎么領?。空D仙3新手卡領取中心
- 弘陽地產前11月合約銷售額同比減少56.98% 單月同比跌64.3%
- 天天要聞:主板測試卡代碼a2是什么?主板測試卡代碼 常見代碼總結
- UML建模怎么用?UML建模之用例圖
- 環球百事通!國產搞笑電視劇排行榜你看過幾個?愛情公寓只能排倒數第三
- 【世界快播報】工廠模式是什么?工廠模式的詳解
- 世界通訊!黃淮學院最低錄取分數線是多少?2022文理科最低分及位次
- 最美夕陽紅 攜手度余生——富德生命人壽十堰中支用鏡頭為老人定格相濡以沫的愛情
- 速訊:使用Icon圖標的幾種方式是啥?Icon圖標怎么使用?
- 速看:歌名最長的網絡歌曲是什么?歌名最長的中文歌
- fm2015是什么?fm2010戰術
- 【獨家】.NET Core是什么?NET Core有哪些用處?
- Trans系列是啥?基于翻譯模型(Trans系列)的知識表示學習
- 尼康d800與d810哪個好?尼康d800與d810有哪些區別?
- 快看點丨Internal問題解決流程 Internal server error 500 問題解決思路
- 【環球播資訊】12月8日天元股份漲停分析:可降解塑料,包裝印刷概念熱股
- 每日快播:12月8日焦點科技漲停分析:跨境電商,職業教育,教育概念熱股
- 12月8日千紅制藥漲停分析:肝素,化學原料藥,抗原自測概念熱股
- 微速訊:轉動慣量是什么意思?轉動慣量的含義
- 當前焦點!歉疚的意思是什么?歉疚一詞詳情介紹
- 西米是什么米?西米露和西米是一樣的嗎?
- 興民智通:公司目前不觸及 st 相關條款
- 世界頂級昂貴音響有哪些?世界頂級昂貴音響介紹
- 世界今日報丨如何正確使用系統清理bat程序?清理bat程序的方法技巧
- 天天微動態丨11月百城二手住宅市場均價穩中趨降
- 【世界熱聞】12月8日國光連鎖漲停分析:新零售概念熱股
- 頭條焦點:文章目錄是什么?選擇排序怎么設置?
- 世界微資訊!網絡的利與弊是什么?網絡的利弊分析
- 天天快資訊丨吸血鬼狂刀技能搭配詳情 吸血鬼狂刀攻略)
- 世界動態:磁條讀寫器多少錢?磁條讀寫器使用方法介紹
- Modbus通信協議是什么?Modbus通信協議詳解
- JSONObject是什么意思?JSONObject的詳情介紹
- 世界關注:iPad Air(iPad5)什么時候上市?iPad Air(iPad5)的上市時間
- 安徽大專學校推薦!安徽大專院校排名前十詳細介紹含分數線
- 每日熱聞!BOW是什么意思?為什么要用BOW模型描述圖像?
- 環球快資訊:鉛球世界紀錄2019 女子男子鉛球世界紀錄分別是多少?
- 熱門看點:分析賓得645d怎么樣?賓得公司詳情介紹
- 觀察:梯度(gradient)是什么?梯度的概念是建立在哪方面?
- 焦點播報:程子土包子來的時候歌廳的dj叫什么名字?海燕KTV
- 世界視訊!信號的基本概念是什么?信號的分類有哪些?
- 環球實時:電腦電源額定功率要多少才合適?電腦電源的額定功率
- 全球快消息!4399生死狙擊萬人號賬號2021 4399生死狙擊好號和密碼免費永久2021
- 焦點訊息:OneNote是什么?OneNote的功能有哪些?
- 世界今頭條!多普達手機都有哪些型號?多普達最新手機大全詳情
- 揮著翅膀的女孩英文版叫什么?揮著翅膀的女孩英語版歌詞翻譯
- lol怎么在游戲里回復好友?lol游戲回復技巧
- 今日精選:碧海青天的意思是什么?碧海青天一詞出自哪里?
- 世界信息:圖片或手寫簽名轉電子簽名怎么轉?手寫簽名轉電子簽名教程
- 世界要聞:44歲賈靜雯出席活動耳朵被燙傷 修杰楷很是心疼
- 當前視點!手機QQ接收電腦端好友發送的文件存儲在什么地方?手機文件儲存路徑
- 天天速讀:語義分割:基于openCV和深度學習(二)
- 支付寶網上銀行如何付款?網上銀行付款操作流程
- 天天微頭條丨用VC6.0實現上位機串口通信
- 全球速看:寶寶毛衣怎么編織?寶寶毛衣編織圖解
- 魂鎖典獄長二技能怎么用?lol魂鎖典獄長背景以及皮膚介紹
- 基礎版本的基礎版本 直方圖均衡化系列
- 天天觀速訊丨用身份證辦的移動手機號碼可以跨省改歸屬地嗎?是不可以的
- 攝像頭遠程監控步驟是什么?手機遠程監控攝像頭設置方法
- Android中LayoutParams是什么?Android中LayoutParams總結和用法
- 歌詞里有我真的很不錯是什么兒歌?歌詞我真的很不錯是什么兒歌?
- 全球新資訊:會議panel是什么意思?醫學術語中的panel到底是指什么?
- 當前動態:顏料墨水和染料墨水的區別是什么?顏料墨水和染料墨水簡介