1. 程式人生 > >Java框架-Spring的jdbc、連線池及事務管理

Java框架-Spring的jdbc、連線池及事務管理

1. Spring的AOP程式設計

1.1 純xml程式設計

<!--通知配置型別-->
<aop:config>
    <!--設定切面-->
    <aop:aspect ref="logger">
        <!--設定切入點表示式-->
        <aop:pointcut id="pt" expression="execution(* com.azure..*ServiceImpl.*(..))"></aop:pointcut>
        <!--設定通知-->
<!--前置通知--> <aop:before method="beforeLog" pointcut-ref="pt"></aop:before> <!--後置通知--> <aop:after-returning method="afterReturningLog" pointcut-ref="pt"></aop:after-returning> <!--異常通知--> <aop:after-throwing method
="afterThrowing" pointcut-ref="pt">
</aop:after-throwing> <!--最終通知--> <aop:after method="after" pointcut-ref="pt"></aop:after> </aop:aspect> </aop:config>

<!--通知配置型別-->
<aop:config>
    <!--設定切面-->
    <aop:aspect ref=
"logger"
>
<!--設定切入點表示式--> <aop:pointcut id="pt" expression="execution(* com.azure..*ServiceImpl.*(..))"></aop:pointcut> <!--設定通知--> <!--環繞通知--> <aop:around method="around" pointcut-ref="pt"></aop:around> </aop:aspect> </aop:config>

1.2 結合xml和註解程式設計

  • 需求:service層實現事務管理,包括事務執行、事務提交,事務回滾。建議使用環繞通知

1.2.1 建立專案、新增依賴

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.azure</groupId>
    <artifactId>day54projects_spring_AOP</artifactId>
    <version>1.0-SNAPSHOT</version>
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.7</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
</dependencies>
    
</project>

1.2.2 service

1.2.2.1 介面
public interface IAccountService {
    /*模擬儲存賬戶功能*/
    void save();
    String update(int id);
}
1.2.2.2 實現類
public class AccountServiceImpl implements IAccountService {
    @Override
    public void save() {
        System.out.println("執行儲存方法!");
    }

    @Override
    public String update(int id) {
        System.out.println("方法引數:"+id);
        return "Service本身方法返回值";
    }
}

1.2.4 事務切面類

/**
 * 事務切面類
 */
@Aspect //指定當前類為切面類
@Component  //建立切面類物件
public class TransactionManager {

    //定義切點表示式
    @Pointcut("execution(* com.azure.service.*.*(..))")
    public void pt(){}

    /*
    // 【前置通知】
    @Before("pt()")
    public void beginTransaction(){
        System.out.println("【前置通知】 在執行目標方法之前執行");
    }

    //【後置通知(返回後通知)】
    @AfterReturning("pt()")
    public void afterReturning(){
        System.out.println("【後置通知】執行目標方法正常結束執行");
    }

    //【異常通知】
    @AfterThrowing("pt()")
    public void afterThrowing(){
        System.out.println("【異常通知】 執行目標方法出現異常時候執行");
    }

    //【最終通知】
    @After("pt()")
    public void after() {
        System.out.println("【最終通知】在呼叫目標物件方法後始終執行");
    }
    */

    // 環繞目標物件方法執行
    @Around("pt()")
    public Object around(ProceedingJoinPoint pjp) {
        try {
            System.out.println("[環繞通知] 環繞前");
            //獲取引數
            Object[] args = pjp.getArgs();
            //修改引數
            args[0] = 898;
            //執行方法
            Object retV = pjp.proceed(args);
            System.out.println("[環繞通知] 環繞後");
            //返回方法執行結果,還能修改結果
            return retV + "~~~想不到吧";
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            System.out.println("[環繞通知] 環繞異常");
            return null;
        } finally {
            System.out.println("[環繞通知] 環繞最終");
        }
    }
}

1.2.5 測試類

public class TestApp {
    public static void main(String[] args) {
        //建立物件
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //因為service實現介面,故採用jdk動態代理。必須用介面接收。如果用實現類接收會報錯!
        IAccountService service = (IAccountService) ac.getBean("accountServiceImpl");
        //class com.sun.proxy.$Proxy18
        System.out.println(service.getClass());
        String result = service.update(999);
        System.out.println(result);
    }
}

1.3 純註解程式設計

  • 需求:改造上述案例程式碼,使用純註解實現

1.3.1 配置管理類

/**
 * 配置管理類
 * [email protected]     指定該類為配置管理類,建立容器時候只要載入當前類位元組碼就可以?
 * [email protected]    開啟註解掃描,可指定多個@ComponentScan,實現掃描多個包
 *                          註解多個包的時候,要把所有包放在{}中,每個包之間用逗號分隔
 * [email protected]     開啟註解掃描,掃描一個包(子包)
 * [email protected]  開啟AOP自動代理
 */
@Configuration
@ComponentScans({
        @ComponentScan(basePackages = "com.azure.service"),
        @ComponentScan(basePackages = "com.azure.utils")
})
@EnableAspectJAutoProxy
public class SpringConfiguration {
}

1.3.2 測試類

@RunWith(SpringJUnit4ClassRunner.class)//使用spring的junit
@ContextConfiguration(classes = SpringConfiguration.class)	//載入配置類
public class TestApp2 {
    //從容器中獲取物件
    @Autowired
    private IAccountService service;

    @Test
    public void test() {
        System.out.println(service.getClass());
        String result = service.update(999);
        System.out.println(result);
    }
}

2. 事務回顧

2.1 事務概念

  • 事務指一組執行單元,該單元的各個組成部分要不同時執行成功,要不同時執行失敗。

2.2 事務特性ACID

  • A-原子性(Automicity):事務是不可再分割的最小工作單位;
  • C-一致性(Consistency):事務必須是資料庫狀態從一個一致性狀態,轉變成另外一個一致性狀態。類似能量守恆定律
  • I-隔離性(Isolation):一個事務的執行不能受到其它事務的影響。事務間相互獨立。
  • D-永續性(Durability):一個事務一旦提交,則它對資料庫中的資料的改變將會永久儲存

3. Spring宣告式事務管理

  • 宣告式事務管理式作用於業務層的事務處理
  • Spring的事務管理控制是基於AOP的,可以使用程式設計方式也可使用配置方式。

3.1 String事務控制的API

  • PlatformTransactionManager介面是Spring的事務管理器,提供獲取事務狀態資訊、提交事務、回滾事務的方法。
  • 實際開發中使用其實現類
  1. 使用 SpringJDBCiBatis 進行持久化資料時使用:
    org.springframework.jdbc.datasource.DataSourceTransactionManager

  2. Hibernate 版本進行持久化資料時使用org.springframework.orm.hibernate5.HibernateTransactionManager

3.1.1 TransactionDefinition

  • 事務的定義資訊物件

  • 包含以下方法:

    - String getName()		獲取事務物件名稱
    - int getIsolationLevel()	獲取事務隔離級
    - int getPropagationBehavior()	獲取事務傳播行為
    - int getTimeout()	獲取事務超時時間
    - boolean isReadOnly()	獲取事務是否只讀
    
  • 事務的傳播行為有7種,常用的有以下三種

    REQUIRED 
    1. 預設值
    2. 表示當前執行方法必須有事務環境
    3. 如果當前執行方法沒有事務環境,則建立新的事務;如果當前執行方法有事務環境,則加入當前事務,就不建立新的事務。
    4. 應用:新增、修改、刪除需要指定事務的傳播行為是REQUIRED
    
    SUPPORTS
    1. 支援事務
    2. 當前執行方法有事務環境則支援,沒有事務環境也可以執行。事務可有可無。
    3. 應用:查詢
    
    REQUERS_NEW
    1. 表示當前執行方法必須有事務環境
    2. 不管當前方法有沒有事務環境,都會建立一個新的事務。
    
  • 超時時間

    預設值是-1,沒有超時限制。如果有,以秒為單位進行設定。

  • 是否是隻讀事務

    增刪改是讀寫事務,查詢設定為只讀

3.1.2 TransactionStatus

  • 事務具體的執行狀態,提交事務和回滾事務的方法需要傳入此引數

3.2 xml配置方式實現事務管理(重要)

  • 作用於service層
  • 實現事務程式碼與業務程式碼完全解耦,或者說完全分離

下面以service層呼叫dao層方法儲存使用者為例,如果儲存兩個使用者的方法之間存在錯誤程式碼,而應用事務之後資料庫沒有變化,說明事務有生效

3.2.0 建立表格

  • 此處省略

3.2.1建立專案,新增依賴

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.azure</groupId>
    <artifactId>day55projects_spring_tx_xml</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!--spring核心包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <!--aop支援包-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.9</version>
        </dependency>
        <!--事務支援包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <!--mysql驅動包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.40</version>
        </dependency>
        <!--資料庫連線池c3p0-->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
        <!--jdbctemplate-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <!--junit支援包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

    </dependencies>
</project>

3.2.2 實體類

public class Account {
    private int accountId;
    private int uid;
    private double money;
    /*省略*/
}

3.2.3 dao層

3.2.3.1 dao介面
public interface IAccountDao {
    /*儲存賬戶*/
    void save(Account account);
}
3.2.3.2 dao介面
@Repository
public class AccountDaoImpl implements IAccountDao {

    /*使用註解獲取物件*/
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public void save(Account account) {
        jdbcTemplate.update("insert into account values (null,?,?)",account.getUid(),account.getMoney());
    }
}

3.2.4 service層

3.2.4.1 service介面
public interface IAccountService {
    /*儲存賬戶*/
    void save(Account account);
}
3.2.4.2 service實現類
@Service
public class AccountServiceImpl implements IAccountService {

    /*使用註解獲取dao物件*/
    @Autowired
    private IAccountDao accountDao;

    @Override
    public void save(Account account) {
        /*模擬事務*/
        accountDao.save(account);
        int i = 1/0;
        accountDao.save(account);
    }
}

如果註釋掉int i = 1/0;,資料庫插入兩條資料,而不註釋該行程式碼資料庫無變動,說明事務控制已生效

3.2.5 bean.xml配置

思路:

  1. 需要進行資料庫操作,所以要載入資料庫連線池,而載入資料庫連線池又要先載入資料庫配置檔案;

  2. 需要進行資料庫操作,所以要載入jdbcTemplate;

  3. 因為使用到註解配置,所以要開啟註解掃描;

  4. 使用事務管理,首先要配置事務管理類(切面類),並注入連線池

    然後配置事務通知規則,攔截哪些方法,對這些方法進行什麼管理(讀寫?只讀?)

    因為事務的原理是AOP,所以要配置AOP,裡面包含切入點表示式,還有重要的一點,將事務通知規則與切入點表示式建立起關係

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--0.載入資料庫配置檔案,context標籤-->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
    <!--0.開啟註解掃描-->
    <context:component-scan base-package="com.azure"></context:component-scan>

    <!--1.配置資料庫連線池-->
    <bean 
            
           

相關推薦

Java框架-Spring的jdbc連線事務管理

1. Spring的AOP程式設計 1.1 純xml程式設計 <!--通知配置型別--> <aop:config> <!--設定切面--> <aop:aspect ref="logger"> <!-

JDBC(資料庫的驅動連線java程式操作資料庫事務隔離級別連線等)

java操作資料庫的思想:連上資料庫,傳送sql語句。在連上資料庫之前,要先用程式啟動資料庫,因此,可以通過反射載入類驅動(com.jdbc.mysql.Driver)。通過驅動管理類的靜態方法傳遞資料庫的url來獲取一個連線物件(connection)。有三個過載的方法,第一個user和p

java 偏向鎖輕量級鎖重量級鎖synchronized原理

bubuko 固定 使用情況 防止 不能 image 過程 記錄 原因 Java對象頭與Monitor java對象頭是實現synchronized的鎖對象的基礎,synchronized使用的鎖對象是存儲在Java對象頭裏的。 對象頭包含兩部分:Mark Word 和

spring-data-mono java註解方式mongo連線帶認證配置

import com.mongodb.MongoClient; import com.mongodb.MongoClientOptions; import com.mongodb.MongoCredential; import com.mongodb.ServerAddress; import or

JVM (二)--Java程式編譯類載入執行

Java程式的編譯 Java程式的編譯是由Java原始碼編譯器來完成,流程圖如下: Java程式的執行 Java程式的編譯是由Java執行引擎來完成,流程圖如下:   Java程式碼編譯和執行的整個過程包含了以下三個重要的機制: Java原始

java----day30(DBUtils和連線)

DBUtils 概述 DBUtils是java程式設計中的資料庫操作實用工具,小巧簡單實用。 DBUtils封裝了對JDBC的操作,簡化了JDBC操作,可以少寫程式碼。 Dbutils三個核心功能介紹 QueryRunner中提供對sql語句操作的API.

java專案使用redis / 連線配置

1. pom                   <dependency>     <groupId>

Mysql密碼更改連線MySQL常用命令

12月5日任務 13.1 設定更改root密碼 13.2 連線mysql 13.3 mysql常用命令   設定更改root密碼 要進行mysql資料庫操作,需要啟動mysql服務,執行ps aux進行檢視 [[email protected]

hibernate框架之DBCP連線配置

hibernate配置資料庫連線池的三種方法https://blog.csdn.net/super712/article/details/52823192  以下是hibernate配置檔案裡面配置dbcp的demo; <?xml version="1.0" encodi

Java框架Mybatis的工作流程原理

Mybatis簡介:        MyBatis 是一款優秀的持久層框架,它支援定製化 SQL、儲存過程以及高階對映。MyBatis 避免了幾乎所有的 JDBC 程式碼和手動設定引數以及獲取結果集。MyBatis 可以使用簡單的 XML 或註解來配置

Java中DriverManager跟DataSource獲取getConnection有什麼不同(Java中資料來源和連線的區別)

一、理解什麼是資料來源和連線池 資料來源:資料的源頭,需要設定資料庫url,使用者名稱和密碼,此時就相當於一個代理資料庫;它包含連線池和連線池管理兩個部分;               Java中的資料來源就是javax.

關於“”機制的思考(執行緒程序連線等)

“池”機制的兩大核心 重用 緩衝 統一管理“池”裡的物件 (這個不能作為核心) 。。。。。 【1】“池”機制有個定長的容器。 【2】初始化時容器中儲存有定量的“池”物件(在此用“池”物件統稱“池”中的執行緒、程序或者連結等,下文同)。 【3

Java——Lambda表示式方法引用內建函式式介面

1.Lambda表示式 面向物件的基礎上支援函數語言程式設計 1.1 約束: 介面有且僅有一個抽象方法,如果存在兩個抽象方法,則無法使用函數語言程式設計。 介面有且僅有一個抽象方法,且想要轉化為lambda表示式,加註解 @FunctionalInterface

關於 PHP MySQL 長連線連線的一些探索

hp連線mysql的方式,用的多的是mysql擴充套件、mysqli擴充套件、pdo_mysql擴充套件,是官方提供的。php的執行機制是頁面執行完會釋放所有該php程序中的所有資源的,如果有多個併發訪問本地的測試頁面 http://127.0.0.1/1.ph

OkHttp3的連線連線建立過程分析

如我們前面在 OkHttp3 HTTP請求執行流程分析 中的分析,OkHttp3通過Interceptor鏈來執行HTTP請求,整體的執行過程大體如下: OkHttp Flow 這些Interceptor中每一個的職責,這裡不再贅述。 在OkHttp3中,Str

Spring boot2.0以上整合Druid連線監控資訊配置

1. Springboot 2.0選擇HikariCP作為預設資料庫連線池 理由參考: 2. 資料庫連線池效能比對(hikari druid c3p0 dbcp jdbc) 本文是整合Druid連線池,資料庫為mysql pom檔案新增druid的依

JAVA基礎26-資料庫連線

資料庫連線池         資料庫連線池負責分配,管理,釋放資料庫連線,它允許應用程式重複使用一個現有的資料庫連線,而不是重新建立一個。 編寫資料庫連線池 編寫資料庫連線池必須實現java.sql.DataSource介面 在Da

springboot2配置使用Druid連線使用的時候出現的連線問題

最近在springboot2專案中使用了Druid連線池,在此記錄一下,整合過程 首先:引入Maven配置項 <dependency> <groupId>com.alibaba</groupId> <artifac

Spring框架中獲取連線的方式

1、連線池概述  資料庫連線是一種關鍵的有限的昂貴的資源,這一點在多使用者的網頁應用程式中體現得尤為突出。對資料庫連線的管理能顯著影響到整個應用程式的伸縮性和健壯性,影響到程式的效能指標。資料庫連線池正是針對這個問題提出來的。      資料庫連線池負責分配、管理和釋放資料庫

java操作mongodb(連線

Mongo的例項其實就是一個數據庫連線池,這個連線池裡預設有10個連結。我們沒有必要重新實現這個連結池,但是我們可以更改這個連線池的配置。因為Mongo的例項就是一個連線池,所以,專案中最好只存在一個Mongo的例項。 常見的配置引數: connectionsPerHost