主頁 > 後端開發 > SSM總結

SSM總結

2022-12-10 06:35:19 後端開發

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使用與實作
      • 代理模式
        • 靜態代理
        • JDK動態代理
        • CGlib動態代理
    • SPring MVC
      • SpringMVC核心組件
      • SpringMVC第一個程式
      • 處理請求以及回應
        • 引數傳遞
        • 回應 頁面跳轉
      • SpringMVC基本配置
      • SpringMVC檔案上傳
      • Restful風格介面
      • SpringMVC作業流程
    • MyBAtis
      • 實作原理:工廠模式
        • 簡單工廠
        • 工廠方法
        • 抽象工廠
      • MyBatis基本應用
        • MyBatis的基本配置(MyBatis-config.xml)
          • MyBatis資料源配置
            • 資料庫連接池 (druid c3p0)
          • 映射檔案配置
          • 其他配置
          • MyBatis整合Log4J
        • MyBatis主要構件
      • MyBatis映射檔案
        • 基本標簽
        • 動態SQL
        • ResultMap
          • 基礎查詢 - 基本映射
          • 外聯查詢 - 一對一查詢
          • 外聯查詢 - 一對多查詢
      • MyBatis 一級快取與二級快取
    • 事務管理
      • Spring事務管理
        • 事務的特性(ACID)
        • 事務的隔離級別
        • Spring事務
          • 編程式事務
          • 宣告式事務
        • 事務傳播機制

Spring

IOC(控制反轉)& DI(依賴注入)

IOC是容器,用來裝Spring創建的Bean物件,

Bean注入方式

  • Set方法注入
  • 構造器注入
  • @Autowared自動注入
<!--     SpringBean的注入方式  -->
<!--      手動裝配  -->
<!--      ==  set方法注入    -->
    <bean id="hello" >
        <property name="userCode" value="https://www.cnblogs.com/ATRIQAQ/archive/2022/12/09/hello"></property>
        <property name="userName" value="https://www.cnblogs.com/ATRIQAQ/archive/2022/12/09/Spring"></property>
        <property name="role">
            <bean >
                <property name="roleCode" value="https://www.cnblogs.com/ATRIQAQ/archive/2022/12/09/這里是注入的實體物件"></property>
                <property name="roleName" value="https://www.cnblogs.com/ATRIQAQ/archive/2022/12/09/這里是注入的實體物件的值"></property>
            </bean>
        </property>
        <property name="role" ref="myRole"></property>
    </bean>

    <bean name="myRole" >
        <property name="roleName" value="https://www.cnblogs.com/ATRIQAQ/archive/2022/12/09/管理員"></property>
        <property name="roleCode" value="https://www.cnblogs.com/ATRIQAQ/archive/2022/12/09/SMBMS_ADMIN"></property>
    </bean>

<!--      ==  帶參構造器注入  -->
    <bean name="constructor" >
        <constructor-arg name="userName" value="https://www.cnblogs.com/ATRIQAQ/archive/2022/12/09/這是通過構造器注入的userName"></constructor-arg>
        <constructor-arg name="userCode" value="https://www.cnblogs.com/ATRIQAQ/archive/2022/12/09/這是通過構造器注入的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框架在運行階段動態生成代理物件,即在記憶體中以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通水管
水管打不通
夠不著旗桿,游戲結束				 //原始內容
什么破游戲!

? 由上述代碼不難看出,動態代理的實作需要以下幾點:

  1. JDK動態代理需要宣告介面,想要創建一個動態代理類,就必須給這個類宣告一個介面,否則無法在Proxy.newProxyInstance時傳入對應的介面類位元組碼檔案,
  2. 在代理類中需要通過構造傳入原有的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的值按照普通傳參的方式拼接在地址欄或引數串列中,

回應 頁面跳轉

  1. 只回應資料:資料介面,在Handler方法上需要添加@ResponseBody注解,添加完成后,回傳值不會被視圖決議器進行決議,在回傳時可以按照正常的資料進行回傳,
  2. 默認頁面回傳:默認的回應方式,本質上是請求轉發,在Handler方法進行return后,會將回傳的資料轉發至DispatcherServlet,然后由DispatcherServlet調度視圖決議器,決議回傳值中的資料與視圖并回應,
  3. 重定向:重定向可以重定向到任意路徑,只需要在回傳值上、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/archive/2022/12/09/.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/archive/2022/12/09/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:請求處理流程

  1. DispathcerServlet(前端控制器)接收請求DispatcherServlet 通過 doService()方法 接收用戶請求,呼叫 doDispatch() 方法進行請求調度,
  2. DispatcherServlet(前端控制器)呼叫HandlerMapping(處理器映射器):DispatcherServlet 通過getHandler() 呼叫HandlerMapping獲取HandlerExecutionChain
  3. HandlerMapping將(HandlerExecutionChain)處理器執行鏈回傳給DispatcherServlet
  4. DispathcerServlet(前端控制器)通過HandlerAdapter(處理器配接器),獲取對應的Handler處理器方法,
  5. HandlerAdapter(處理器配接器)呼叫Handler處理器方法,處理用戶請求,
  6. Handler處理器方法將回傳值回傳給HandlerAdapter(處理器配接器)
  7. HandlerAdapter將Handler處理器方法的回傳值以ModelAndView的形式回傳給DispatherServlet:
  8. DispatcherServlet將ModelAndView交給ViewResolver(視圖決議器)決議,
  9. ViewResolver(視圖決議器)將ModelAndView中的資料渲染到View(視圖)中,
  10. ViewResolver回傳的視圖資訊到DispatcherServlet,
  11. DispatcherServlet將視圖資訊及回傳值回傳給客戶端,

image-20221204094023826

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/archive/2022/12/09/com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="https://www.cnblogs.com/ATRIQAQ/archive/2022/12/09/jdbc:mysql://localhost:3306/smbms_3"/>
            <property name="username" value="https://www.cnblogs.com/ATRIQAQ/archive/2022/12/09/root"/>
            <property name="password" value="https://www.cnblogs.com/ATRIQAQ/archive/2022/12/09/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/archive/2022/12/09/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特性的一個最重要的標簽,

基礎查詢 - 基本映射

代表主鍵列 :column - 資料庫列名 , property:物體類屬性名

普通列 :column - 資料庫列名 , property:物體類屬性名

外聯查詢 - 一對一查詢
<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種,

  1. requierd:如果當前沒有事務,就新建一個事務,如果已存在一個事務中,加入到這個事務中,(事務默認傳播機制),
  2. supports:支持當前事務,如果沒有當前事務,就以非事務方法執行,
  3. mandatory:使用當前事務,如果沒有當前事務,就拋出例外,
  4. required_new:新建事務,如果當前存在事務,把當前事務掛起,
  5. not_supported:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起,
  6. never:以非事務方式執行操作,如果當前事務存在則拋出例外,
  7. nested:如果當前存在事務,則在嵌套事務內執行,如果當前沒有事務,則執行與propagation_required類似的操作

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/539606.html

標籤:其他

上一篇:想早點下班?試試Aorm庫吧,更方便的進行Go資料庫操作

下一篇:朝花夕拾-鏈表(二)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more