Spring Boot 和 Spring Data JPA 整合基本示例
我們將構建一個將 POJO 儲存在資料庫中的應用程式。該應用程式使用 Spring Data JPA 在關聯式資料庫中儲存和檢索資料。其最引人注目的功能是能夠在執行時從儲存庫介面自動建立儲存庫實現。
主類
package org.springboot;
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);
}
}
main()
方法使用 Spring Boot 的 SpringApplication.run()
方法來啟動應用程式。請注意,沒有一行 XML。也沒有 web.xml 檔案。此 Web 應用程式是 100%純 Java,你無需處理任何管道或基礎結構的配置。
實體類
package org.springboot.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Greeting {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String text;
public Greeting() {
super();
}
public Greeting(String text) {
super();
this.text = text;
}
/* In this example, the typical getters and setters have been left out for brevity. */
}
在這裡你有一個 Greeting
類有兩個屬性,id
和 text
。你還有兩個建構函式。預設建構函式僅為 JPA 而存在。你不會直接使用它,因此可以將其指定為 protected
。另一個建構函式是你將用於建立要儲存到資料庫的 Greeting
例項的建構函式。
Greeting
類用 @Entity
註釋,表明它是 JPA 實體。由於缺少 @Table
註釋,假設該實體將對映到名為 Greeting
的表。
Greeting 的 id
屬性使用 @Id
註釋,以便 JPA 將其識別為物件的 ID。id
屬性也使用 @GeneratedValue
進行註釋,以指示應自動生成 ID。
另一個屬性 text
沒有註釋。假設它將對映到與屬性本身共享同一名稱的列。
瞬態屬性
在類似於上面的實體類中,我們可以擁有不希望在資料庫中持久儲存的屬性,或者在資料庫中建立為列的屬性,可能是因為我們只想在執行時設定它們並在我們的應用程式中使用它們,因此我們可以使用 @Transient 註釋註釋該屬性。
package org.springboot.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Transient;
@Entity
public class Greeting {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String text;
@Transient
private String textInSomeLanguage;
public Greeting() {
super();
}
public Greeting(String text) {
super();
this.text = text;
this.textInSomeLanguage = getTextTranslationInSpecifiedLanguage(text);
}
/* In this example, the typical getters and setters have been left out for brevity. */
}
這裡有一個相同的 Greeting 類,它現在有一個瞬態屬性 textInSomeLanguage
,它可以在執行時初始化和使用,不會在資料庫中持久化。
DAO 類
package org.springboot.repository;
import org.springboot.model.Greeting;
import org.springframework.data.repository.CrudRepository;
public interface GreetingRepository extends CrudRepository<Greeting, Long> {
List<Greeting> findByText(String text);
}
GreetingRepository
擴充套件了 CrudRepository
介面。它使用的實體和 ID 型別 Greeting
和 Long
在 CrudRepository
的通用引數中指定。通過擴充套件 CrudRepository
,GreetingRepository
繼承了幾種處理 Greeting
永續性的方法,包括儲存,刪除和查詢 Greeting
實體的方法。
有關 CrudRepository
, PagingAndSortingRepository
, JpaRepository
的比較,請參閱此討論 。
Spring Data JPA 還允許你通過簡單地宣告其方法簽名來定義其他查詢方法。在 GreetingRepository
的情況下,這用 findByText()
方法顯示。
在典型的 Java 應用程式中,你希望編寫一個實現 GreetingRepository
的類。但這就是使 Spring Data JPA 如此強大的原因:你不必編寫儲存庫介面的實現。Spring Data JPA 在你執行應用程式時動態建立實現。
服務類
package org.springboot.service;
import java.util.Collection
import org.springboot.model.Greeting;
public interface GreetingService {
Collection<Greeting> findAll();
Greeting findOne(Long id);
Greeting create(Greeting greeting);
Greeting update(Greeting greeting);
void delete(Long id);
}
服務 Bean
package org.springboot.service;
import java.util.Collection;
import org.springboot.model.Greeting;
import org.springboot.repository.GreetingRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class GreetingServiceBean implements GreetingService {
@Autowired
private GreetingRepository greetingRepository;
@Override
public Collection<Greeting> findAll() {
Collection<Greeting> greetings = greetingRepository.findAll();
return greetings;
}
@Override
public Greeting findOne(Long id) {
Greeting greeting = greetingRepository.findOne(id);
return greeting;
}
@Override
public Greeting create(Greeting greeting) {
if (greeting.getId() != null) {
//cannot create Greeting with specified Id value
return null;
}
Greeting savedGreeting = greetingRepository.save(greeting);
return savedGreeting;
}
@Override
public Greeting update(Greeting greeting) {
Greeting greetingPersisted = findOne(greeting.getId());
if (greetingPersisted == null) {
//cannot find Greeting with specified Id value
return null;
}
Greeting updatedGreeting = greetingRepository.save(greeting);
return updatedGreeting;
}
@Override
public void delete(Long id) {
greetingRepository.delete(id);
}
}
控制器類
package org.springboot.web.api;
import java.util.Collection;
import org.springboot.model.Greeting;
import org.springboot.service.GreetingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value = "/api")
public class GreetingController {
@Autowired
private GreetingService greetingService;
// GET [method = RequestMethod.GET] is a default method for any request.
// So we do not need to mention explicitly
@RequestMapping(value = "/greetings", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Collection<Greeting>> getGreetings() {
Collection<Greeting> greetings = greetingService.findAll();
return new ResponseEntity<Collection<Greeting>>(greetings, HttpStatus.OK);
}
@RequestMapping(value = "/greetings/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Greeting> getGreeting(@PathVariable("id") Long id) {
Greeting greeting = greetingService.findOne(id);
if(greeting == null) {
return new ResponseEntity<Greeting>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<Greeting>(greeting, HttpStatus.OK);
}
@RequestMapping(value = "/greetings", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Greeting> createGreeting(@RequestBody Greeting greeting) {
Greeting savedGreeting = greetingService.create(greeting);
return new ResponseEntity<Greeting>(savedGreeting, HttpStatus.CREATED);
}
@RequestMapping(value = "/greetings/{id}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Greeting> updateGreeting(@PathVariable("id") Long id, @RequestBody Greeting greeting) {
Greeting updatedGreeting = null;
if (greeting != null && id == greeting.getId()) {
updatedGreeting = greetingService.update(greeting);
}
if(updatedGreeting == null) {
return new ResponseEntity<Greeting>(HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<Greeting>(updatedGreeting, HttpStatus.OK);
}
@RequestMapping(value = "/greetings/{id}", method = RequestMethod.DELETE)
public ResponseEntity<Greeting> deleteGreeting(@PathVariable("id") Long id) {
greetingService.delete(id);
return new ResponseEntity<Greeting>(HttpStatus.NO_CONTENT);
}
}
MySQL 資料庫的應用程式屬性檔案
#mysql config
spring.datasource.url=jdbc:mysql://localhost:3306/springboot
spring.datasource.username=root
spring.datasource.password=Welcome@123
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
spring.jpa.hibernate.ddl-auto = update
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.DefaultNamingStrategy
#initialization
spring.datasource.schema=classpath:/data/schema.sql
SQL 檔案
drop table if exists greeting;
create table greeting (
id bigint not null auto_increment,
text varchar(100) not null,
primary key(id)
);
pom.xml 檔案
<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</groupId>
<artifactId>springboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
構建可執行的 JAR
你可以使用 Maven 從命令列執行該應用程式。或者,你可以構建一個包含所有必需依賴項,類和資源的可執行 JAR 檔案,並執行該檔案。這使得在整個開發生命週期中,跨不同環境等將服務作為應用程式釋出,版本和部署變得容易。
使用 ./mvnw spring-boot:run
執行應用程式。或者你可以使用 ./mvnw clean package
構建 JAR 檔案。然後你可以執行 JAR 檔案:
java -jar target/springboot-0.0.1-SNAPSHOT.jar