使用JDBC和Spring訪問關係資料
本指南將引導您完成使用Spring訪問關係資料的過程。
你要構建什麼
您將使用Spring構建一個JdbcTemplate 應用程式來訪問儲存在關係資料庫中的資料。
你需要什麼
- 大約15分鐘
- 最喜歡的文字編輯器或IDE
- JDK 1.8 或更高版本
- Gradle 4+ 或Maven 3.2+
-
您還可以將程式碼直接匯入IDE:
如何完成本指南
與大多數Spring入門指南 一樣,您可以從頭開始並完成每個步驟,或者您可以繞過您已熟悉的基本設定步驟。無論哪種方式,您最終都會使用工作程式碼。
要從頭開始 ,請繼續使用Gradle構建。
要跳過基礎知識 ,請執行以下操作:
- 下載 並解壓縮本指南的源儲存庫,或使用Git克隆它:
git clone https://github.com/spring-guides/gs-relational-data-access.git
- 進入gs-relational-data-access/initial
- 跳轉到建立Customer物件。
完成後,可以根據gs-relational-data-access/complete 中的程式碼檢查結果。
使用Gradle構建
首先,設定一個基本的構建指令碼。在使用Spring構建應用程式時,您可以使用任何您喜歡的構建系統,但此處包含了使用Gradle 和Maven 所需的程式碼。如果您不熟悉這兩者,請參閱使用Gradle構建Java專案 或使用Maven構建Java專案 。
建立目錄結構
在您選擇的專案目錄中,建立以下子目錄結構;例如,在*nix系統上使用mkdir -p src/main/java/hello :
└── src └── main └── java └── hello
建立Gradle構建檔案
下面是最初的Gradle構建檔案 。
buildscript { repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.3.RELEASE") } } apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'idea' apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' bootJar { baseName = 'gs-relational-data-access' version ='0.1.0' } repositories { mavenCentral() } sourceCompatibility = 1.8 targetCompatibility = 1.8 dependencies { compile("org.springframework.boot:spring-boot-starter") compile("org.springframework:spring-jdbc") compile("com.h2database:h2") testCompile("junit:junit") }
在Spring Boot gradle plugin 提供了許多便捷的功能:
- 它收集類路徑上的所有jar並構建一個可執行的“über-jar”,這使得執行和傳輸服務更加方便。
- 它搜尋public static void main() 標記為可執行類的方法。
- 它提供了一個內建的依賴項解析器,它設定版本號以匹配Spring Boot依賴項 。您可以覆蓋任何您希望的版本,但它將預設為Boot的所選版本集。
使用Maven構建
首先,設定一個基本的構建指令碼。在使用Spring構建應用程式時,您可以使用任何您喜歡的構建系統,但此處包含了使用Maven 所需的程式碼。如果您不熟悉Maven,請參閱使用Maven構建Java專案 。
建立目錄結構
在您選擇的專案目錄中,建立以下子目錄結構;例如,在*nix系統上使用mkdir -p src/main/java/hello :
└── src └── main └── java └── hello
pom.xml
<?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>org.springframework</groupId> <artifactId>gs-relational-data-access</artifactId> <version>0.1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.3.RELEASE</version> </parent> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
在Spring Boot gradle plugin 提供了許多便捷的功能:
- 它收集類路徑上的所有jar並構建一個可執行的“über-jar”,這使得執行和傳輸服務更加方便。
- 它搜尋public static void main() 標記為可執行類的方法。
- 它提供了一個內建的依賴項解析器,它設定版本號以匹配Spring Boot依賴項 。您可以覆蓋任何您希望的版本,但它將預設為Boot的所選版本集。
使用IDE構建
- 閱讀如何將本指南直接匯入使用STS構建/匯入入門指南 。
- 閱讀使用IntelliJ IDEA匯入入門指南 中如何使用本指南。
建立一個Customer物件
您將在下面使用的簡單資料訪問邏輯管理客戶的名字和姓氏。要在應用程式級別表示此資料,請建立一個Customer類。
package hello; public class Customer { private long id; private String firstName, lastName; public Customer(long id, String firstName, String lastName) { this.id = id; this.firstName = firstName; this.lastName = lastName; } @Override public String toString() { return String.format( "Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName); } // getters & setters omitted for brevity }
儲存和檢索資料
Spring提供了一個名為JdbcTemplate 的模板類,可以輕鬆使用SQL關係資料庫和JDBC。大多數JDBC程式碼都陷入資源獲取,連線管理,異常處理和一般錯誤檢查之中,這與程式碼要實現的內容完全無關,JdbcTemplate負責這一切。您所要做的就是專注於手頭的任務。
src/main/java/hello/Application.java
package hello; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.jdbc.core.JdbcTemplate; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @SpringBootApplication public class Application implements CommandLineRunner { private static final Logger log = LoggerFactory.getLogger(Application.class); public static void main(String args[]) { SpringApplication.run(Application.class, args); } @Autowired JdbcTemplate jdbcTemplate; @Override public void run(String... strings) throws Exception { log.info("Creating tables"); jdbcTemplate.execute("DROP TABLE customers IF EXISTS"); jdbcTemplate.execute("CREATE TABLE customers(" + "id SERIAL, first_name VARCHAR(255), last_name VARCHAR(255))"); // Split up the array of whole names into an array of first/last names List<Object[]> splitUpNames = Arrays.asList("John Woo", "Jeff Dean", "Josh Bloch", "Josh Long").stream() .map(name -> name.split(" ")) .collect(Collectors.toList()); // Use a Java 8 stream to print out each tuple of the list splitUpNames.forEach(name -> log.info(String.format("Inserting customer record for %s %s", name[0], name[1]))); // Uses JdbcTemplate's batchUpdate operation to bulk load data jdbcTemplate.batchUpdate("INSERT INTO customers(first_name, last_name) VALUES (?,?)", splitUpNames); log.info("Querying for customer records where first_name = 'Josh':"); jdbcTemplate.query( "SELECT id, first_name, last_name FROM customers WHERE first_name = ?", new Object[] { "Josh" }, (rs, rowNum) -> new Customer(rs.getLong("id"), rs.getString("first_name"), rs.getString("last_name")) ).forEach(customer -> log.info(customer.toString())); } }
@SpringBootApplication 是一個便利註釋,添加了以下所有內容:
- @Configuration 標記該類作為應用程式上下文的bean定義的源。
- @EnableAutoConfiguration 告訴Spring Boot開始根據類路徑設定,其他bean和各種屬性設定新增bean。
- @ComponentScan 告訴Spring在包中尋找其他元件,配置和服務,允許它找到控制器。
main()方法使用Spring Boot的SpringApplication.run() 方法來啟動應用程式。您是否注意到沒有一行XML?也沒有web.xml檔案。此Web應用程式是100%純Java,您無需處理配置任何管道或基礎結構。
main()方法使用Spring Boot的SpringApplication.run()方法來啟動應用程式。您是否注意到沒有一行XML?也沒有web.xml檔案。此Web應用程式是100%純Java,您無需處理配置任何管道或基礎結構。
Spring Boot支援H2 ,一種記憶體中的關係資料庫引擎,並自動建立連線。因為我們使用的是spring-jdbc,Spring Boot會自動建立一個JdbcTemplate。@Autowired 自動載入JdbcTemplate 並使其可用。
這個Application類實現了Spring BootCommandLineRunner ,這意味著它將run()在載入應用程式上下文後執行該方法。
首先,使用JdbcTemplate’s `execute 方法安裝一些DDL 。
其次,您獲取字串列表並使用Java 8流,將它們拆分為Java陣列中的firstname/lastname對。
然後使用JdbcTemplate’s `batchUpdate 方法在新建立的表中安裝一些記錄。方法呼叫的第一個引數是查詢字串,最後一個引數(Objects 的陣列)包含要替換為“?”字元的查詢的變數。
對於單個插入語句,JdbcTemplate’s `insert方法很好。但對於多個,最好使用batchUpdate。
使用?的引數,以避免SQL注入攻擊 通過指示JDBC來繫結變數。
最後,使用query方法在表中搜索與條件匹配的記錄。您再次使用“?”引數為查詢建立引數,在進行呼叫時傳入實際值。最後一個引數是用於將每個結果行轉換為新Customer物件的Java 8 lambda 。
Java 8 lambdas很好地對映到單個方法介面,如Spring的RowMapper。如果您使用的是Java 7或更早版本,則可以輕鬆插入匿名介面實現,並具有與lambda expresion正文所包含的相同的方法體,並且它可以毫不費力地使用Spring。
構建可執行的JAR
您可以使用Gradle或Maven從命令列執行該應用程式。或者,您可以構建一個包含所有必需依賴項,類和資源的可執行JAR檔案,並執行該檔案。這使得在整個開發生命週期中,跨不同環境等將服務作為應用程式釋出,版本和部署變得容易。
如果您使用的是Gradle,則可以使用執行該應用程式./gradlew bootRun 。或者您可以使用構建JAR檔案./gradlew build 。然後你可以執行JAR檔案:
java -jar build/libs/gs-relational-data-access-0.1.0.jar
如果您使用的是Maven,則可以使用該應用程式執行該應用程式./mvnw spring-boot:run 。或者您可以使用構建JAR檔案./mvnw clean package 。然後你可以執行JAR檔案:
java -jar target/gs-relational-data-access-0.1.0.jar
上面的過程將建立一個可執行的JAR。您也可以選擇構建經典WAR檔案 。
顯示日誌輸出,您可以從日誌中看到它在後臺執行緒上。您應該每隔5秒鐘看到計劃任務:
2015-06-19 10:58:31.152INFO 67731 --- [main] hello.Application: Creating tables 2015-06-19 10:58:31.219INFO 67731 --- [main] hello.Application: Inserting customer record for John Woo 2015-06-19 10:58:31.220INFO 67731 --- [main] hello.Application: Inserting customer record for Jeff Dean 2015-06-19 10:58:31.220INFO 67731 --- [main] hello.Application: Inserting customer record for Josh Bloch 2015-06-19 10:58:31.220INFO 67731 --- [main] hello.Application: Inserting customer record for Josh Long 2015-06-19 10:58:31.230INFO 67731 --- [main] hello.Application: Querying for customer records where first_name = 'Josh': 2015-06-19 10:58:31.242INFO 67731 --- [main] hello.Application: Customer[id=3, firstName='Josh', lastName='Bloch'] 2015-06-19 10:58:31.242INFO 67731 --- [main] hello.Application: Customer[id=4, firstName='Josh', lastName='Long'] 2015-06-19 10:58:31.244INFO 67731 --- [main] hello.Application: Started Application in 1.693 seconds (JVM running for 2.054)
概要
恭喜!您剛剛使用Spring開發了一個簡單的JDBC客戶端。