SSM
目錄- SSM
- Spring
- IOC(控制反轉)& DI(依賴注入)
- Bean注入方式
- AOP(面向切面編程)
- 一、AOP編程思想
- 1.1 什么是AOP
- 1.2 為什么需要AOP
- 1.3 AOP實作方法分類
- 二、AOP的專有名詞
- 三、認識SpringAOP
- 3.1 SpringAOP的特點
- 3.2 SpringAOP使用與實作
- 一、AOP編程思想
- 代理模式
- 靜態代理
- JDK動態代理
- CGlib動態代理
- IOC(控制反轉)& DI(依賴注入)
- SPring MVC
- SpringMVC核心組件
- SpringMVC第一個程式
- 處理請求以及回應
- 引數傳遞
- 回應 頁面跳轉
- SpringMVC基本配置
- SpringMVC檔案上傳
- Restful風格介面
- SpringMVC作業流程
- MyBAtis
- 實作原理:工廠模式
- 簡單工廠
- 工廠方法
- 抽象工廠
- MyBatis基本應用
- MyBatis的基本配置(MyBatis-config.xml)
- MyBatis資料源配置
- 資料庫連接池 (druid c3p0)
- 映射檔案配置
- 其他配置
- MyBatis整合Log4J
- MyBatis資料源配置
- MyBatis主要構件
- MyBatis的基本配置(MyBatis-config.xml)
- MyBatis映射檔案
- 基本標簽
- 動態SQL
- ResultMap
- 基礎查詢 - 基本映射
- 外聯查詢 - 一對一查詢
- 外聯查詢 - 一對多查詢
- MyBatis 一級快取與二級快取
- 實作原理:工廠模式
- 事務管理
- Spring事務管理
- 事務的特性(ACID)
- 事務的隔離級別
- Spring事務
- 編程式事務
- 宣告式事務
- 事務傳播機制
- Spring事務管理
- Spring
Spring
IOC(控制反轉)& DI(依賴注入)
IOC是容器,用來裝Spring創建的Bean物件,
Bean注入方式
- Set方法注入
- 構造器注入
- @Autowared自動注入
<!-- SpringBean的注入方式 -->
<!-- 手動裝配 -->
<!-- == set方法注入 -->
<bean id="hello" >
<property name="userCode" value="https://www.cnblogs.com/ATRIQAQ/p/hello"></property>
<property name="userName" value="https://www.cnblogs.com/ATRIQAQ/p/Spring"></property>
<property name="role">
<bean >
<property name="roleCode" value="https://www.cnblogs.com/ATRIQAQ/p/這里是注入的實體物件"></property>
<property name="roleName" value="https://www.cnblogs.com/ATRIQAQ/p/這里是注入的實體物件的值"></property>
</bean>
</property>
<property name="role" ref="myRole"></property>
</bean>
<bean name="myRole" >
<property name="roleName" value="https://www.cnblogs.com/ATRIQAQ/p/管理員"></property>
<property name="roleCode" value="https://www.cnblogs.com/ATRIQAQ/p/SMBMS_ADMIN"></property>
</bean>
<!-- == 帶參構造器注入 -->
<bean name="constructor" >
<constructor-arg name="userName" value="https://www.cnblogs.com/ATRIQAQ/p/這是通過構造器注入的userName"></constructor-arg>
<constructor-arg name="userCode" value="https://www.cnblogs.com/ATRIQAQ/p/這是通過構造器注入的userCode"></constructor-arg>
</bean>
<!-- 自動裝配 -->
<!-- == 配置包掃描,并使用注解進行注入 -->
<context:component-scan base-package="com.dzqc.smbms">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
IOC和DI的區別:
IOC是什么:是控制反轉,將new物件的權力由呼叫程式交給第三方IOC容器,控制權被轉移給了IOC容器,在呼叫程式看來,new物件的動作由主動變成了被動,所以叫做控制反轉,
DI是什么:依賴注入,將IOC容器中new出來的物件注入進呼叫程式,
IOC和ID的區別:IOC和DI是一體的,DI是IOC的另一種表現形式,是同一事件不同層面的解讀,
AOP(面向切面編程)
一、AOP編程思想
1.1 什么是AOP
? AOP (Aspect Orient Programming),直譯過來就是 面向切面編程,AOP是一種編程思想,基于面向物件編程思想(OOP)的補充,面向物件編程將程式抽象成了各個切面,
1.2 為什么需要AOP
? 在開發程序中,存在某段多次重復的代碼,以面向程序編程方式的話,我們會將這段代碼抽象成一個方法,在需要的位置呼叫該方法,當這段代碼需要修改時,我們就只需要改變這一個方法就夠了,
? 但需求不是一成不變的,如果后期需要新增一個需求,又需要在多處進行修改,就需要再抽象一個方法,然后在需要的位置再分別呼叫這個方法,又或者,我們在業務程序中洗掉這個方法,我們就需要洗掉掉每一個地方的呼叫,
? 在這種情況之下,我們就可以通過使用AOP來解決,
1.3 AOP實作方法分類
? 首先我們要知道AOP的目的,AOP要達到在開發者不修改源代碼的前提下,去為系統中的業務添加某種通用的功能,
? AOP的實作方式大致可以分為兩類:
- 靜態AOP實作
- 靜態AOP實作是在編譯階段就對程式源代碼進行修改,生成了靜態的AOP代理類,即生成的
*.class檔案已經被修改,需要使用特定的編譯方式進行編譯,代表性的靜態AOP實作方式如:AspectJ
- 靜態AOP實作是在編譯階段就對程式源代碼進行修改,生成了靜態的AOP代理類,即生成的
- 動態AOP實作
- AOP框架在運行階段動態生成代理物件,即在記憶體中以JDK動態代理的方式,或CGlib動態生成AOP代理類,典型的技術如:SpringAOP,
| 類別 | 機制 | 原理 |
|---|---|---|
| 靜態AOP | 靜態織入 | 在編譯前,切面直接以位元組碼的形式編譯入目標代碼的位元組碼檔案中,對性能無影響,但靈活性不夠, |
| 動態AOP | JDK動態代理 | 在運行期間,目標類加載之后為介面動態生成代理類,將切面織入到代理類中,相對于靜態AOP更靈活一些,但切入點需要實作介面,對系統的性能有一定影響, |
| 動態位元組碼生成 | CGlib | 在運行期間,目標類加載之后,動態生成目標類的子類,然后將切面的邏輯加入到子類中,相對于JDK動態代理的方式,CGlib不需要介面也可以實作織入,但是當擴展類的實體方法使用final修飾時無法進行織入, |
二、AOP的專有名詞
AOP中的特性術語大致有一下幾種:
- 增強|建議(Advice):AOP框架中的增強處理,通知表述了切面在何時執行以及如何執行增強處理,
- 連接點(join point) :連切點表示應用程式執行程序中能夠插入切面的一個點,這個點可以是方法的呼叫、例外的拋出,在SpringAOP中,連接點總是方法的呼叫,
- 切點(PointCut):可以插入增強處理的連接點,
- 切面(Aspect):切面是增強和切點的結合,
- 引入(Introduction):引入允許我們想現有的類添加新的方法或屬性,
- 織入(Weaving):將增強處理添加到目標物件中,并創建一個被增強物件,這個程序就是織入,
- 目標物件(Target):增強的目標物件,原始物件,
- 代理物件(Proxy):加入了增強的物件,是由AOP增強后生成的代理物件,
SpringAOP在AOP的基礎上又多出幾個延伸概念:
- 前置增強(MethodBeforeAdvice):在連接點執行前進行增強,
- 環繞增強(MethodInterceptor):在連接點前后都執行增強,
- 例外增強(ThrowsAdvice):連接點拋出例外時進行增強,
- 回傳值增強(AfterReturingAdvice):連接點產生回傳值后進行增強,
三、認識SpringAOP
3.1 SpringAOP的特點
? AOP的框架有很多,實作方式各不相同,Spring的AOP則是通過動態代理進行實作的,下面簡單對代理模式進行介紹,
3.2 SpringAOP使用與實作
- Spring原生API:實作 MethodBeforeAdvice介面、AfterReturningAdvice介面,重寫對應的方法,并配置增強類與切入點類,可以實作AOP操作,
- 自定義切面類:自定義切面類與增強方法,使用配置宣告切面類并關聯切點,實作AOP
- 注解實作AOP:使用@Aspect宣告切面類,@Pointcut宣告切入點,使用@Before@After....注解實作增強方法,并配置自動代理,來實作AOP,
Execution運算式:
? 宣告具體方法的位置的運算式 :回傳值 包路徑.類名.方法名(引數串列)
代理模式
? 代理模式分為兩種:
- 靜態代理:需要為每個角色創建對應的代理物件,
- 動態代理:自動為每個目標角色生成對應的代理物件,
靜態代理
? 被代理類介面:
package com.dzqc.smbms.proxy;
/**
* 游戲介面
*/
public interface Game {
public void gameStart();
public void gameOver();
}
被代理類:
package com.dzqc.smbms.proxy;
public class Mario implements Game{
@Override
public void gameStart() {
System.out.println("超級馬里奧,游戲開始!");
}
@Override
public void gameOver() {
System.out.println("夠不著旗桿,游戲結束");
}
}
代理類:
package com.dzqc.smbms.proxy;
/**
* 本類為 靜態代理 類
* 代理類 需要 持有 目標物件
*/
public class GameStaticProxy implements Game{
private Game targetGame;
public Game getProxy(Game targetGame){
this.targetGame = targetGame;
return this;
}
@Override
public void gameStart() {
System.out.println("游戲機啟動");
System.out.println("游戲啟動!");
targetGame.gameStart();
System.out.println("游戲進行中,mario他跳起來了");
}
@Override
public void gameOver() {
System.out.println("mario 打敗了魔王,找到了旗桿,要爬旗桿, ");
targetGame.gameOver();
System.out.println("真菜,不玩了,破游戲什么時候關服!");
}
}
測驗類:
package com.dzqc.smbms.proxy;
import org.junit.Test;
import java.lang.reflect.Proxy;
public class ProxyTest {
@Test
public void staticProxy(){
Mario mario = new Mario();
GameStaticProxy gameStaticProxy = new GameStaticProxy();
Game marioProxy = gameStaticProxy.getProxy(mario);
marioProxy.gameStart();
marioProxy.gameOver();
}
}
測驗結果:
游戲機啟動
游戲啟動!
超級馬里奧,游戲開始! //原始內容
游戲進行中,mario他跳起來了
mario 打敗了魔王,找到了旗桿,要爬旗桿,
夠不著旗桿,游戲結束 //原始內容
真菜,不玩了,破游戲什么時候關服!
JDK動態代理
? JDK動態代理的實作邏輯大致如下:
介面與被代理類與上述一致,
代理類:
package com.dzqc.smbms.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* JDK代理類
*/
public class GameJDKProxy implements InvocationHandler {
private Game targetGame;
public GameJDKProxy(Game targetGame){
this.targetGame = targetGame;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName();
if (name.equals("gameStart")){
Object o = gameStart(method, args);
}else {
Object o = gameOver(method, args);
}
return null;
}
private Object gameStart(Method method , Object[] args) throws Throwable{
System.out.println("mario游戲啟動了");
Object invoke = method.invoke(targetGame, args);
System.out.println("正在操作mario通水管");
return null;
}
private Object gameOver(Method method , Object[] args) throws Throwable{
System.out.println("水管打不通");
Object invoke = method.invoke(targetGame, args);
System.out.println("什么破游戲!");
return null;
}
}
測驗類:
package com.dzqc.smbms.proxy;
import org.junit.Test;
import java.lang.reflect.Proxy;
public class ProxyTest {
@Test
public void jdkProxy(){
Mario mario = new Mario();
GameJDKProxy gameJDKProxy = new GameJDKProxy(mario);
// 使用JDK動態代理類獲取代理物件
Game marioProxy = (Game) Proxy.newProxyInstance(
this.getClass().getClassLoader(), //類加載器
new Class[]{Game.class}, // 代理介面的位元組碼檔案
gameJDKProxy// 自己的代理類,進行目標方法擴充
);
marioProxy.gameStart();
marioProxy.gameOver();
}
}
測驗結果
mario游戲啟動了
超級馬里奧,游戲開始! //原始內容
正在操作mario通水管
水管打不通
夠不著旗桿,游戲結束 //原始內容
什么破游戲!
? 由上述代碼不難看出,動態代理的實作需要以下幾點:
- JDK動態代理需要宣告介面,想要創建一個動態代理類,就必須給這個類宣告一個介面,否則無法在Proxy.newProxyInstance時傳入對應的介面類位元組碼檔案,
- 在代理類中需要通過構造傳入原有的
bean,因為處理完附加功能外,需要執行原有bean中的方法,以實作代理的目的,
CGlib動態代理
代理類:
package com.dzqc.smbms.proxy;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class GameCglibProxy implements MethodInterceptor {
private Game targetGame;
public GameCglibProxy(Game targetGame){
this.targetGame = targetGame;
}
/**
* 獲取代理物件
* @return
*/
public Game getProxy(){
// 獲取cglib操作類
Enhancer enhancer = new Enhancer();
// 指定代理類 的 父型別別,要代理哪個類就使用哪個類做代理類的父類
enhancer.setSuperclass(Mario.class);
// 指定代理物件,把當前代理類作為代理物件
enhancer.setCallback(this);
// 創建并回傳代理物件
return (Game) enhancer.create();
}
/**
* 代理增強的實際操作處
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
String name = method.getName();
if (name.equals("gameStart")){
gameStart(method , objects);
}else {
gameOver(method , objects);
}
return null;
}
private Object gameStart(Method method , Object[] args) throws Throwable{
System.out.println("魂斗羅啟動!!!!");
Object invoke = method.invoke(targetGame, args);
System.out.println("正在操作Mario和魂斗羅兄弟決斗");
return null;
}
private Object gameOver(Method method , Object[] args) throws Throwable{
System.out.println("Mario挖了下水道,坑了魂斗羅兄弟");
Object invoke = method.invoke(targetGame, args);
System.out.println("不要串臺!");
return null;
}
}
測驗類:
package com.dzqc.smbms.proxy;
import org.junit.Test;
import java.lang.reflect.Proxy;
public class ProxyTest {
@Test
public void cglibProxy(){
Mario mario = new Mario();
GameCglibProxy gameCglibProxy = new GameCglibProxy(mario);
Game proxy = gameCglibProxy.getProxy();
proxy.gameStart();
proxy.gameOver();
}
}
測驗結果:
魂斗羅啟動!!!!
超級馬里奧,游戲開始! //原始內容
正在操作Mario和魂斗羅兄弟決斗
Mario挖了下水道,坑了魂斗羅兄弟
夠不著旗桿,游戲結束 //原始內容
不要串臺!
? 由上述代碼不難看出,CGlib在進行動態代理的程序中,對被實作的類要求較少,而且更為靈活,使用者可以根據實際情況進行選擇,
SPring MVC
MVC是什么?MVC是設計模式,包含Model(模型)、View(視圖)、Controller(控制器),
SpringMVC就是基于MVC設計模式創建的一個控制層框架,用來簡化視圖與后臺的資料互動作業,并且規范開發方式,SpringMVC是對Servlet的封裝,可將SpringMVC的本質看作Servlet,
SpringMVC核心組件
- 前端控制器|中央處理器(DispatcherServlet):用來調度整個MVC的請求走向,
- 處理器配接器(HandlerAdapter):用來適配請求路徑對應的處理器
- 處理器映射器(HandlerMapping):用來查找請求路徑對應的處理器方法
- 處理器(Controller | Handler):處理請求的方法
- 視圖決議器(ViewResolver):決議視圖、回傳路徑、請求轉發與回應的決議器
- 視圖(View):頁面
- 攔截器(Interceptor):攔截請求
SpringMVC第一個程式
處理請求以及回應
引數傳遞
類需要使用@Controller注解,在類中宣告一個Handler方法,在方法的引數串列中宣告需要的引數,在Handler方法被呼叫時,就可以正確傳入對應的引數,
- 常用簡單資料型別:String,Integer,Char,Boolean,Byte,Short,Long,Float,Double,
- 復雜資料型別:
- 物件:物件在進行引數傳遞時,引數串列中宣告的為物件,在傳參的程序中,傳遞的是物件中宣告的屬性名,
- 陣列:陣列在進行傳參時,陣列的引數名需要多次出現,每次出現給陣列賦一個 值,
- http://localhost:9999/ssm/arr?arr=name1&arr=name2&arr=name3
- List集合:在進行引數傳遞時,因為List集合是個介面,所以需要在List型別的引數前加上@RequestParam注解,在引數傳遞時,與陣列傳參方式一致,
- map集合:在進行引數傳遞時,需要加上@RequestParam注解,引數在拼接時,只需將key和value的值按照普通傳參的方式拼接在地址欄或引數串列中,
回應 頁面跳轉
- 只回應資料:資料介面,在Handler方法上需要添加@ResponseBody注解,添加完成后,回傳值不會被視圖決議器進行決議,在回傳時可以按照正常的資料進行回傳,
- 默認頁面回傳:默認的回應方式,本質上是請求轉發,在Handler方法進行return后,會將回傳的資料轉發至DispatcherServlet,然后由DispatcherServlet調度視圖決議器,決議回傳值中的資料與視圖并回應,
- 重定向:重定向可以重定向到任意路徑,只需要在回傳值上、ModelAndView的視圖名前 加上 redirect,這里的重定向與Servlet的重定向功能保持一致,流程有變動,在Handler(處理器)方法進行回傳后,將請求轉發至DispatcherServlet(中央處理器),由DispatcherServlet(中央處理器)調度HttpServletResponse(回應),由HttpServletResponse(回應)進行重定向操作,
SpringMVC基本配置
在web.xml種配置 dispatcherServlet
<!-- 配置中央處理器,與Servlet一起初始化 -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 配置SpringIOC容器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
在Spring檔案當中配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
">
<!-- 配置包掃描,掃描所有使用Controller注解的類 -->
<context:component-scan base-package="com.dzqc.smbms">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 處理器配接器 -->
<bean name="handlerAdapter"
></bean>
<!-- 處理器映射器 -->
<bean name="handlerMapping"
></bean>
<!-- 視圖決議器 -->
<bean name="viewResolver"
>
<property name="prefix" value="https://www.cnblogs.com/views/"></property>
<property name="suffix" value="https://www.cnblogs.com/ATRIQAQ/p/.jsp"></property>
</bean>
<!-- 配置靜態資源過濾器 -->
<mvc:default-servlet-handler/>
<mvc:resources location="/statics/" mapping="/static/*"></mvc:resources>
<!-- 檔案上傳決議器 -->
<bean name="multipartResolver"
>
<!-- 最大支持檔案大小,此處配置50MB大小限制 -->
<property name="maxUploadSize" value="https://www.cnblogs.com/ATRIQAQ/p/52428800"></property>
</bean>
</beans>
SpringMVC檔案上傳
依賴:
<!-- 檔案上傳 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
Restful風格介面
Rest注解:
- @RestController
- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping
- @PathVariable
SpringMVC作業流程
準備作業:
/* 在SpringMVC首次重繪或重新加載時,會呼叫SpringMVC初始化策略 */ protected void onRefresh(ApplicationContext context) { this.initStrategies(context); } /** 初始化策略方法 */ protected void initStrategies(ApplicationContext context) { this.initMultipartResolver(context); // 初始化檔案上傳決議器 this.initLocaleResolver(context); // 初始化本地決議器 this.initThemeResolver(context); // 初始化中心決議器 this.initHandlerMappings(context); // 初始化處理器映射器 this.initHandlerAdapters(context); // 初始化處理器配接器 this.initHandlerExceptionResolvers(context); // 初始化處理器例外決議器 this.initRequestToViewNameTranslator(context); // 初始化 請求視圖 翻譯器 this.initViewResolvers(context); // 初始化視圖決議器 this.initFlashMapManager(context); // 初始化 映射重繪管理器 }
2:請求處理流程
- DispathcerServlet(前端控制器)接收請求 :DispatcherServlet 通過 doService()方法 接收用戶請求,呼叫 doDispatch() 方法進行請求調度,
- DispatcherServlet(前端控制器)呼叫HandlerMapping(處理器映射器):DispatcherServlet 通過getHandler() 呼叫HandlerMapping獲取HandlerExecutionChain
- HandlerMapping將(HandlerExecutionChain)處理器執行鏈回傳給DispatcherServlet
- DispathcerServlet(前端控制器)通過HandlerAdapter(處理器配接器),獲取對應的Handler處理器方法,
- HandlerAdapter(處理器配接器)呼叫Handler處理器方法,處理用戶請求,
- Handler處理器方法將回傳值回傳給HandlerAdapter(處理器配接器)
- HandlerAdapter將Handler處理器方法的回傳值以ModelAndView的形式回傳給DispatherServlet:
- DispatcherServlet將ModelAndView交給ViewResolver(視圖決議器)決議,
- ViewResolver(視圖決議器)將ModelAndView中的資料渲染到View(視圖)中,
- ViewResolver回傳的視圖資訊到DispatcherServlet,
- DispatcherServlet將視圖資訊及回傳值回傳給客戶端,
MyBAtis
? MyBatis是一款輕量級的ORM(物件關系映射)(持久化)框架,能夠將JDBC相關的持久化代碼通過組態檔的形式實作,提高開發效率,
實作原理:工廠模式
手機工廠:MI,IPHONE,HUAWEI
簡單工廠
工廠物件:
抽象物體:
具體物體:
工廠方法
抽象工廠:
抽象產品:
物體工廠:
物體產品:
抽象工廠
MyBatis基本應用
MyBatis使用分為
- 組態檔(mybatis-config.xml)
- mapper介面
- 與mapper介面對應的mapper.xml映射檔案
MyBatis的基本配置(MyBatis-config.xml)
MyBatis資料源配置
<!-- 環境配置標簽 default中參考的為默認使用的環境 -->
<environments default="development">
<!-- 環境標簽 id 唯一,不可重復 -->
<environment id="development">
<!-- 事務管理器配置 -->
<transactionManager type="JDBC"/>
<!-- 資料源配置 type默認為POOLED(默認啟用資料庫連接池模式) ,UNPOOLED 不啟用連接池 -->
<dataSource type="POOLED">
<!-- 屬性標簽,該處屬性為資料源配置屬性 -->
<property name="driver" value="https://www.cnblogs.com/ATRIQAQ/p/com.mysql.cj.jdbc.Driver"/>
<property name="url" value="https://www.cnblogs.com/ATRIQAQ/p/jdbc:mysql://localhost:3306/smbms_3"/>
<property name="username" value="https://www.cnblogs.com/ATRIQAQ/p/root"/>
<property name="password" value="https://www.cnblogs.com/ATRIQAQ/p/root"/>
</dataSource>
</environment>
</environments>
資料庫連接池 (druid c3p0)
映射檔案配置
<mappers>
<!-- 映射檔案的地址,參考相對路徑 -->
<mapper resource="mappers/SUserMapper.xml"></mapper>
</mappers>
其他配置
<!-- MyBatis別名配置 只能配置物體類 -->
<typeAliases>
<!-- <typeAlias type="com.dzqc.smbms.entity.SUser" alias="u"></typeAlias>-->
<package name="com.dzqc.smbms.entity"/>
</typeAliases>
<settings>
<!-- 配置控制臺日志組件 -->
<setting name="logImpl" value="https://www.cnblogs.com/ATRIQAQ/p/STDOUT_LOGGING"/>
</settings>
MyBatis整合Log4J
MyBatis主要構件
獲取資源:Resources.getResourceAsStream("MyBatis-config.xml");
SqlSessionFactoryBuilder:構建工廠的建筑隊,需要給資源后,呼叫build方法才能構建工廠,
SqlSessionFactory:工廠建好后,呼叫openSession方法,產出SqlSession
SqlSession:產出的SqlSession可以通過Mapper介面的位元組碼(.class)來獲取SqlSession中生產的代理物件,從而操作資料庫,
MyBatis映射檔案
基本標簽
<select id="唯一,不可重復" parameterType="引數型別" resultType="回傳值型別" resultMap=""
>查詢SQL</select>
<insert id="唯一,不可重復" parameterType="" keyColumn="" keyProperty="" useGeneritedKeys="true">插入陳述句</insert>
<update id="唯一,不可重復" parameterType="" >修改陳述句</update>
<delete id="唯一,不可重復" parameterType="" >洗掉陳述句</delete>
動態SQL
判斷條件成立時,會向SQL后拼接的條件陳述句 自動判斷,如果where中包含的 有任意一個或多個成立,就會自動向SQL后拼接 where , 并將 中的拼接陳述句之前的關鍵字進行適當的截取, :拼接SQL的動態欄位,常用屬性有 perfix , suffix , perfixOverrides,suffixOverrides, :自動拼接Set關鍵字,并截取 中的后綴內容, :column:要遍歷的回圈體內容,item:每次回圈到的元素,open:開始時自動拼接的內容,close:結束時自動拼接的內容,seprector:分隔符,自動在每個元素后面拼接的內容,
ResultMap
resultMap是MyBatis實作ORM特性的一個最重要的標簽,
基礎查詢 - 基本映射
外聯查詢 - 一對一查詢
<association property="role" javaType="srole" column="u.userRole">
<id column="userRole" property="id"></id>
<result column="roleCode" property="roleCode"></result>
<result column="roleName" property="roleName"></result>
</association>
<association property="role" javaType="srole" column="userRole"
select="com.dzqc.smbms.mapper.SRoleMapper.selectById" >
</association>
property:物體類的屬性名
column:外關聯欄位的欄位名
javaType:property對應的物體類的型別,
select:外關聯查詢的方法
外聯查詢 - 一對多查詢
<collection property="roleUsers" column="id" javaType="list" ofType="suser"
select="com.dzqc.smbms.mapper.ISUserMapper.selectByRoleId">
</collection>
property:物體類的屬性名
column:外關聯欄位的欄位名
javaType:一對多關聯集合型別,
ofType:一對多關聯集合中存放的資料的型別,
select:外關聯查詢的方法
MyBatis 一級快取與二級快取
事務管理
Spring事務管理
什么是事務:事務的本身其實就是一組業務邏輯,在業務邏輯當中包含有針對于資料庫持久化的操作,在事務當中的所有業務邏輯被視為一個整體,
事務的特性(ACID)
- 原子性(Atomicity):事務中所有的操作,被視為一個整體,一組業務邏輯中一旦有一點出現例外或失敗,那么所有的業務邏輯都被視為失敗,原子性保證了事務當中的業務邏輯要么全部成功,要么全部失敗,
- 一致性(Consistency):事務的操作,不能破壞資料庫中的資料完整性,在事務執行之前或執行之后,資料庫都處于一致的狀態,在事務中一旦對資料進行持久化,那么持久化的資料一定符合該資料庫的所有規范,不會破壞資料庫中資料的完整性,
- 持久性(Durability):事務中的資料一旦被提交,在之后的操作中都可以查詢到,無論出現什么故障都不會導致資料的損壞或丟失(物理損壞除外,存盤介質損壞),
- 隔離性(Isolation):資料庫允許多個事務同時執行,事務之間的資料相互不會有影響,
事務的隔離級別
事務不隔離會產生的問題:
臟讀:當前事務讀到了其他事務未提交的資料
幻讀(虛讀):當前事務重復讀取同樣的資料,讀取到了其他事務新增的資料,導致短時間內兩次讀取的資料不一致,
不可重復讀:當前事務讀到了其他事務已提交的資料,在短時間,兩次查詢的結果不一致,
- 讀未提交(read-uncommitted):默認隔離級別,允許當前事務讀取其他事務未提交的資料,在該隔離級別中,臟讀、幻讀、不可重復讀都有可能出現,
- 讀已提交(read-committed):允許當前事務讀取其他事務已提交的資料,在該隔離級別下,臟讀不會出現,幻讀和不可重復讀有可能出現,
- 可重復讀(Repeatable-read):允許當前資料讀取其他事務新增的資料,不讀取其他事務提交的修改資料(不允許修改操作),在該事務隔離級別下,臟讀與不可重復讀不會出現,幻讀有可能會出現,
- 串行化(Serializable):最高的事務隔離級別,臟讀、幻讀、不可重復讀都不會出現,但是運行效率低,一般不使用,
Spring事務
編程式事務
優點:對事務的操作精細,能夠更加精確的對事務進行管理
缺點:對代碼的侵入度高,在后期進行維護、功能變更時會提高維護難度,
宣告式事務
事務傳播機制
事務傳播機制一共有7種,
- requierd:如果當前沒有事務,就新建一個事務,如果已存在一個事務中,加入到這個事務中,(事務默認傳播機制),
- supports:支持當前事務,如果沒有當前事務,就以非事務方法執行,
- mandatory:使用當前事務,如果沒有當前事務,就拋出例外,
- required_new:新建事務,如果當前存在事務,把當前事務掛起,
- not_supported:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起,
- never:以非事務方式執行操作,如果當前事務存在則拋出例外,
- nested:如果當前存在事務,則在嵌套事務內執行,如果當前沒有事務,則執行與propagation_required類似的操作
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/539590.html
標籤:Java
