转载

[译] Spring 入门 - 通过 JPA 访问数据

原网页: https://spring.io/guides/gs/accessing-data-jpa/

你将构建

你将构建一个应用,它会保存 Customer 这个 POJO(简单Java对象) 到内存数据库中

你将需要

  • 大约15分钟

  • 一个喜欢的文本编辑器或IDE

  • JDK 1.8 或更高版本

  • Gradle 2.3+ 或 Maven 3.0+

  • 你同样可以将本指南的代码直接导入 Spring Tool Suite (STS) 并从这里开始你的工作

如何完成这个指南

如同大多数的 Spring入门指南 ,你可以从头开始并完成每一个步骤,或者可以跳过这个你已经熟悉的基本配置过程。无论哪种方式,您最终会获得可运行的代码。

从头开始 ,请看“使用Gradle构建”部分。

跳过最基本的部分 ,按下面的步骤操作:

  • 下载 然后解压本项目的代码,或者使用 Git 克隆一个代码仓库:

    git clone https://github.com/spring-guides/gs-accessing-data-jpa.git

  • cd 到 gs-accessing-data-jpa/initial 目录

  • 直接跳到“ 定义一个简单实体

当你完成这些后,你可以把你的结果与 gs-accessing-data-jpa/complete 目录中的代码进行对比。

使用Gradle构建

首先,你要创建一个基本的构建脚本。你可以使用任何你喜欢的构建系统来构建Spring应用程序,但是你所需要的Gralde和Maven构建代码已经包含在这里了。如果你对两者都不熟悉,可以参考“ 使用Gradle构建Java项目 ”或“ 使用Maven构建Java项目 ”。

创建目录结构

你需要在你选的一个用作项目目录的文件夹中,创建下面的子目录结构;例如你可以在*nix系统中使用 mkdir -p src/main/java/hello 这样的命令来完成。

└── src     └── main         └── java             └── hello 

创建Gradle的build文件

下面是initial目录下的Gradle的build文件(译注:实际这个initial指的是项目的根目录,它包含了上面所创建的src目录,以及gradle.build文件,这样执行 gradle build 命令时,gradle才能正确地找到要构建的代码)。

文件名: build.gradle

buildscript {     repositories {         mavenCentral()     }     dependencies {         classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.5.RELEASE")     } }  apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'idea' apply plugin: 'spring-boot'  jar {     baseName = 'gs-accessing-data-jpa'     version =  '0.1.0' }  repositories {     mavenCentral()     maven { url "https://repository.jboss.org/nexus/content/repositories/releases" } }  sourceCompatibility = 1.8 targetCompatibility = 1.8  dependencies {     compile("org.springframework.boot:spring-boot-starter-data-jpa")     compile("com.h2database:h2")     testCompile("junit:junit") }  task wrapper(type: Wrapper) {     gradleVersion = '2.3' } 

Spring Boot Gradle 插件 提供了许多有用的功能:

  • 它收集classpath下的所有的jar包,构建为一个单独的“超级jar包”,使你的服务在传输和运行上变得更方便。

  • 它自动搜索包含 public static void main() 的类,并标记为运行的入口。

  • 它提供了一个嵌入式以来解决方案,预设了一些符合“ Spring Boot 依赖关系 ”的版本号。你也可以用自己的版本号来覆盖它们,如果没有覆盖,那么最终会用Boot默认选择的版本。

使用Maven构建

使用IDE构建

定义一个简单实体

在这个例子中,你需要保存一个被标记为JPA实体的Customer对象。

文件名: src/main/java/hello/Customer.java

package hello;  import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id;  @Entity public class Customer {      @Id     @GeneratedValue(strategy=GenerationType.AUTO)     private long id;     private String firstName;     private String lastName;      protected Customer() {}      public Customer(String firstName, String lastName) {         this.firstName = firstName;         this.lastName = lastName;     }      @Override     public String toString() {         return String.format(                 "Customer[id=%d, firstName='%s', lastName='%s']",                 id, firstName, lastName);     }  } 

这样你就有了一个带有 idfirstNamelastName 三个属性的 Customer 类。另外还有两个构造器。默认的(第一个)构造函数只为了提供给JPA使用,你不会直接用到它,所以他被声明为 protected 。另一个构造器就是你用来创建 Customer 实例并存入数据库的。

注:在本指南中,getter和setter都因篇幅限制而省略

Customer 类被标注了 @Entity 注解来声明这是个JPA实体。因为缺少一个显式的 @Table 注解,根据约定这个实体会被映射到名为Customer的表中。

Customer 类的 id 属性被标注了 @Id 注解,这样JPA会知道这是对象的ID。id属性同样被标注了 @GenetaredValue 注解来向JPA声明这个对象的ID应该被自动生成。

另外两个属性 firstNamelastName 没被标注。根据约定这两个属性将被映射为Customer表的列。

最后, toString() 方法提供了一个很方便的方式将Customer的属性打印出来。

创建一个简单的查询

Spring Data JPA聚焦在使用JPA保存数据到关系数据库。它最引人瞩目的特点是具有在运行时通过repository api自动创建repository的实现的能力。

为了看到它们如何工作,我们来创建一个与Customer类一起工作的repository。

文件名: src/main/java/hello/CustomerRepository.java

package hello;  import java.util.List;  import org.springframework.data.repository.CrudRepository;  public interface CustomerRepository extends CrudRepository<Customer, Long> {      List<Customer> findByLastName(String lastName); } 

CustomerRepository 扩展了 CrudRepositoryCustomerLong 作为实体和id的传递给了 CrudRepository 。通过扩展 CrudRepositoryCustomerRepository 继承了多个方法来完成 Customer 的持久化工作,其中包括保存、删除和寻找 Customer 实体。

Spring Data JPA 还可以通过简单地声明他们的方法签名定义其他的查询方法。就像在这个 CustomerRepository 中的 findByLastName() 方法一样。

在一个典型Java应用程序中,你会需要写一个 CustomerRepository 类的实现。但这也是Spring Data JPA 的强大之处:现在你不需要再根据这个repository接口写一个 CustomerRepository 类的实现了。Spring Data JPA在会运行程序时为你做这些事。

让我们把他们连接起来看看怎么样。

创建Application类

现在你要创建一个Application类,带上其他所有的组件。

文件名: src/main/java/hello/Application.java

package hello;  import org.slf4j.Logger; import org.slf4j.LoggerFactory;  import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean;  @SpringBootApplication public class Application {      private static final Logger log = LoggerFactory.getLogger(Application.class);      public static void main(String[] args) {         SpringApplication.run(Application.class);     }      @Bean     public CommandLineRunner demo(CustomerRepository repository) {         return (args) -> {             // save a couple of customers             repository.save(new Customer("Jack", "Bauer"));             repository.save(new Customer("Chloe", "O'Brian"));             repository.save(new Customer("Kim", "Bauer"));             repository.save(new Customer("David", "Palmer"));             repository.save(new Customer("Michelle", "Dessler"));              // fetch all customers             log.info("Customers found with findAll():");             log.info("-------------------------------");             for (Customer customer : repository.findAll()) {                 log.info(customer.toString());             }             log.info("");              // fetch an individual customer by ID             Customer customer = repository.findOne(1L);             log.info("Customer found with findOne(1L):");             log.info("--------------------------------");             log.info(customer.toString());             log.info("");              // fetch customers by last name             log.info("Customer found with findByLastName('Bauer'):");             log.info("--------------------------------------------");             for (Customer bauer : repository.findByLastName("Bauer")) {                 log.info(bauer.toString());             }             log.info("");         };     }  } 

@SpringBootApplication 是个方便的注解,自动添加了所有以下内容:

  • @Configuration 标记这个类作为bean以定义应用程序上下文的来源。

  • @EnableAutoConfiguration 告诉SpringBoot开始添加基于classpath设置,其他Beans,以及各种属性设置的Beans。

  • 通常情况下你会给Spring MVC应用加上 @EnableWebMvc 注解,但当Spring Boot看到classpath中有 spring-webmvc 时,会自动添加这个注解。这标记该应用程序是一个Web应用程序,并激活一些关键行为,比如创建一个 DispatcherServlet

  • @ComponentScan 告诉Spring去 hello 包中寻找其他组件,配置,服务。

Application 类包括了一个 main() 函数,并加入了一些测试数据到 CustomerRepository 中。首先它从应用上下文中获取到 CustomerRepository ,然后它通过展示 save() 方法,创建了一些测试数据,来保存了几个 Customer 对象。然后调用 findAll() 来从数据库中获得所有的 Customer 对象。接着调用 findOne() 来通过ID获取一个单独的 Customer 对象。最后,它调用 findByLastName() 方法找到了所有lastName 为 “Bauer”的Customer对象。

注意:默认情况下,Spring Boot会启用JPA repository支持,并扫描package(和他的下级package)来确认 @SpringBootApplication 的位置。如果你在一些不可见的package中配置有JPA repository 接口的定义,你可以用 @EnableJpaRepositories 注解,和他的类型安全的参数: basePackageClasses=MyRepository.class 来指出这个package。

构建一个可执行的JAR包

如果你正在使用gradle,你可以使用 ./gradlew bootRun 命令来运行应用程序。

你可以构建一个包含所有必要的依赖,类和资源的一个可执行的JAR文件。这样使传输,版本管理和部署服务在整个开发生命周期在不同的环境,等等,变得更容易

./gradlew build 

然后你可以这样运行JAR包:

java -jar build/libs/gs-accessing-data-jpa-0.1.0.jar 

如果你正在使用Maven,你可以通过 mvn spring-boot:run 来运行应用,或者你也可以通过 mvn clean package 来构建JAR包,然后输入下面的命令来运行:

java -jar target/gs-accessing-data-jpa-0.1.0.jar 

注意:上述过程将创建一个可运行的JAR。你也可以选择 构建一个经典的WAR包 来代替。

你将会看到这样的输出:

== Customers found with findAll(): Customer[id=1, firstName='Jack', lastName='Bauer'] Customer[id=2, firstName='Chloe', lastName='O'Brian'] Customer[id=3, firstName='Kim', lastName='Bauer'] Customer[id=4, firstName='David', lastName='Palmer'] Customer[id=5, firstName='Michelle', lastName='Dessler']  == Customer found with findOne(1L): Customer[id=1, firstName='Jack', lastName='Bauer']  == Customer found with findByLastName('Bauer'): Customer[id=1, firstName='Jack', lastName='Bauer'] Customer[id=3, firstName='Kim', lastName='Bauer'] 

小结

恭喜,你已经写出了一个简单的使用Spring Data JPA来保存、取出对象的应用——关于repository的实现,一点代码也没有。

注意:如果你对暴露JPA在超媒体的RESTful前段下感兴趣,你可能会想阅读《 用REST访问JPA数据 》

原文  https://segmentfault.com/a/1190000005783495
正文到此结束
Loading...