譯 4. 事務管理

1. 打開咱們的STS, New————> Import Spring Getting Started Contenthtml

2. 輸入ma ,選擇Managing Transactionsjava

3. 建立一個booking Servicegit

首先,使用BookingService類建立一個基於JDBC的服務,將人員按名稱登陸到系統中。github

src/main/java/hello/BookingService.javaweb

package hello;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@Component
public class BookingService {

    private final static Logger logger = LoggerFactory.getLogger(BookingService.class);

    private final JdbcTemplate jdbcTemplate;

    public BookingService(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Transactional
    public void book(String... persons) {
        for (String person : persons) {
            logger.info("Booking " + person + " in a seat...");
            jdbcTemplate.update("insert into BOOKINGS(FIRST_NAME) values (?)", person);
        }
    }

    public List<String> findAllBookings() {
        return jdbcTemplate.query("select FIRST_NAME from BOOKINGS",
                (rs, rowNum) -> rs.getString("FIRST_NAME"));
    }

}
 該代碼有一個自動裝配的JdbcTemplate,這是一個方便的模板類,用於執行下面代碼所需的全部數據庫交互。

你也有一個預訂方法,旨在預訂多我的。 它循環遍歷人員列表,而且使用JdbcTemplate將它們插入到BOOKINGS表中。 此方法使用@Transactional進行標記,這意味着任何失敗都會致使整個操做回滾到以前的狀態,並從新拋出原始異常。 這意味着若是一我的未能被添加,則沒有人會被添加到預訂中。spring

您還有一個findAllBookings方法來查詢數據庫。 從數據庫中提取的每一行都被轉換爲一個字符串,而後組合成一個List。sql

構建一個應用程序數據庫

src/main/java/hello/Application.java架構

package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

@SpringBootApplication是一個方便的註解,它增長了如下全部內容:mvc

  • @Configuration將類標記爲應用程序上下文的bean定義的來源。
  • @EnableAutoConfiguration通知Spring Boot根據類路徑設置,其餘bean和各類屬性設置開始添加bean。
  • 一般你會爲Spring MVC應用程序添加@EnableWebMvc,但Spring Boot在類路徑中看到spring-webmvc時會自動添加。 這將該應用程序標記爲Web應用程序並激活關鍵行爲,例如設置DispatcherServlet。
  • @ComponentScan告訴Spring在hello包中查找其餘組件,配置和服務,以便找到控制器。

main()方法使用Spring Boot的SpringApplication.run()方法啓動應用程序。 你有沒有注意到沒有一行XML? 沒有web.xml文件。 這個Web應用程序是100%純Java,您沒必要處理配置任何管道或基礎設施。

您的應用程序其實是零配置。 Spring Boot會檢測類路徑和h2上的spring-jdbc,並自動爲您建立一個DataSource和一個JdbcTemplate。 因爲這樣的基礎架構如今可用而且沒有專門的配置,所以還會爲您建立一個DataSourceTransactionManager:這是攔截@Transactional批註方法(例如BookingService上的書)的組件。 BookingService經過類路徑掃描進行檢測。

本指南中演示的另外一個Spring Boot功能是在啓動時初始化模式的能力

src/main/resources/schema.sql

drop table BOOKINGS if exists;
create table BOOKINGS(ID serial, FIRST_NAME varchar(5) NOT NULL);

還有一個CommandLineRunner注入BookingService並展現各類事務用例。

src/main/java/hello/AppRunner.java

package hello;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

@Component
class AppRunner implements CommandLineRunner {

    private final static Logger logger = LoggerFactory.getLogger(AppRunner.class);

    private final BookingService bookingService;

    public AppRunner(BookingService bookingService) {
        this.bookingService = bookingService;
    }

    @Override
    public void run(String... args) throws Exception {
        bookingService.book("Alice", "Bob", "Carol");
        Assert.isTrue(bookingService.findAllBookings().size() == 3,
                "First booking should work with no problem");
        logger.info("Alice, Bob and Carol have been booked");
        try {
            bookingService.book("Chris", "Samuel");
        } catch (RuntimeException e) {
            logger.info("v--- The following exception is expect because 'Samuel' is too " +
                    "big for the DB ---v");
            logger.error(e.getMessage());
        }

        for (String person : bookingService.findAllBookings()) {
            logger.info("So far, " + person + " is booked.");
        }
        logger.info("You shouldn't see Chris or Samuel. Samuel violated DB constraints, " +
                "and Chris was rolled back in the same TX");
        Assert.isTrue(bookingService.findAllBookings().size() == 3,
                "'Samuel' should have triggered a rollback");

        try {
            bookingService.book("Buddy", null);
        } catch (RuntimeException e) {
            logger.info("v--- The following exception is expect because null is not " +
                    "valid for the DB ---v");
            logger.error(e.getMessage());
        }

        for (String person : bookingService.findAllBookings()) {
            logger.info("So far, " + person + " is booked.");
        }
        logger.info("You shouldn't see Buddy or null. null violated DB constraints, and " +
                "Buddy was rolled back in the same TX");
        Assert.isTrue(bookingService.findAllBookings().size() == 3,
                "'null' should have triggered a rollback");
    }
}

您可使用Gradle或Maven從命令行運行應用程序。 或者您能夠構建一個包含全部必需的依賴項,類和資源的可執行JAR文件,並運行該文件。 這使得在整個開發生命週期內跨越不一樣環境等,將服務做爲應用程序發佈,版本化和部署變得很是容易。

咱們經過STS生成可執行Jar

生成後能夠看到這個文件在target文件夾下

若是您正在使用Gradle,則可使用./gradlew bootRun運行該應用程序。 或者您可使用./gradlew構建構建JAR文件。 而後你能夠運行JAR文件:

java -jar build/libs/gs-managing-transactions-0.1.0.jar

若是您使用的是Maven,則可使用./mvnw spring-boot:run來運行該應用程序。 或者,您可使用./mvnw clean包構建JAR文件。 而後你能夠運行JAR文件:

java -jar target/gs-managing-transactions-0.1.0.jar

執行後能夠看到回顯

 

BOOKINGS表在first_name列上有兩個約束:

名稱不能超過五個字符。

名稱不能爲空。

前三個名字是愛麗絲,鮑勃和卡羅爾。 該申請聲稱有三人被添加到該表中。 若是這樣作沒有成功,申請就會提早退出。

接下來,另外一個預訂是爲克里斯和塞繆爾完成的。 塞繆爾的名字故意太長,強制插入錯誤。 交易行爲規定克里斯和塞繆爾; 也就是這個事務,應該被回滾。 所以,該表中應該只有三我的,這一說法代表了這一點。

最後,Buddy和null都被預訂了。 如輸出所示,null也會致使回滾,從而留下相同的三我的。


 源碼:點擊查看

 恭喜! 您剛剛使用Spring開發了一個包含非侵入事務的簡單JDBC應用程序。

相關文章
相關標籤/搜索