使用 Java 持久化 API
Java

> 
> 我们通过为自行车商店构建示例应用程序来学习如何使用 JPA。
> 
> 
> 


![](/data/attachment/album/201912/27/000705dymv92hnba2a2322.jpg)


对应用开发者来说，<ruby> Java 持久化 API <rt>  Java Persistence API </rt></ruby>（JPA）是一项重要的 java 功能，需要透彻理解。它为 Java 开发人员定义了如何将对象的方法调用转换为访问、持久化及管理存储在 NoSQL 和关系型数据库中的数据的方案。


本文通过构建自行车借贷服务的教程示例来详细研究 JPA。此示例会使用 Spring Boot 框架、MongoDB 数据库（[已经不开源](https://www.techrepublic.com/article/mongodb-ceo-tells-hard-truths-about-commercial-open-source/)）和 Maven 包管理来构建一个大型应用程序，并且构建一个创建、读取、更新和删除（CRUD）层。这儿我选择 NetBeans 11 作为我的 IDE。


此教程仅从开源的角度来介绍 Java 持久化 API 的工作原理，不涉及其作为工具的使用说明。这全是关于编写应用程序模式的学习，但对于理解具体的软件实现也很益处。可以从我的 [GitHub 仓库](https://github.com/StephonBrown/SpringMongoJava)来获取相关代码。


### Java: 不仅仅是“豆子”


Java 是一门面向对象的编程语言，自 1996 年发布第一版 Java 开发工具（JDK）起，已经变化了很多很多。要了解其各种发展及其虚拟机本身就是一堂历史课。简而言之，和 Linux 内核很相似，自发布以来，该语言已经向多个方向分支发展。有对社区免费的标准版本、有针对企业的企业版本及由多家供应商提供的开源替代品。主要版本每六个月发布一次，其功能往往差异很大，所以确认选用版本前得先做些研究。


总而言之，Java 的历史很悠久。本教程重点介绍 Java 11 的开源实现 [JDK 11](https://openjdk.java.net/projects/jdk/11/)。因其是仍然有效的长期支持版本之一。


* **Spring Boot** 是由 Pivotal 公司开发的大型 Spring 框架的一个模块。Spring 是 Java 开发中一个非常流行的框架。它支持各种框架和配置，也为 WEB 应用程序及安全提供了保障。Spring Boot 为快速构建各种类型的 Java 项目提供了基本的配置。本教程使用 Spring Boot 来快速编写控制台应用程序并针对数据库编写测试用例。
* **Maven** 是由 Apache 开发的项目/包管理工具。Maven 通过 `POM.xml` 文件来管理包及其依赖项。如果你使用过 NPM 的话，可能会非常熟悉包管理器的功能。此外 Maven 也用来进行项目构建及生成功能报告。
* **Lombok** 是一个库，它通过在对象文件里面添加注解来自动创建 getters/setters 方法。像 C# 这些语言已经实现了此功能，Lombok 只是把此功能引入 Java 语言而已。
* **NetBeans** 是一款很流行的开源 IDE，专门用于 Java 开发。它的许多工具都随着 Java SE 和 EE 的版本更新而更新。


我们会用这组工具为一个虚构自行车商店创建一个简单的应用程序。会实现对 `Customer` 和 `Bike` 对象集合的的插入操作。


### 酿造完美


导航到 [Spring Initializr](https://start.spring.io/) 页面。该网站可以生成基于 Spring Boot 和其依赖项的基本项目。选择以下选项：


1. **项目：** Maven 工程
2. **语言：** Java
3. **Spring Boot：** 2.1.8（或最稳定版本）
4. **项目元数据：** 无论你使用什么名字，其命名约定都是像 `com.stephb` 这样的。
	* 你可以保留 Artifact 名字为 “Demo”。
5. **依赖项：** 添加：
	* Spring Data MongoDB
	* Lombok


点击 **下载**，然后用你的 IDE（例如 NetBeans） 打开此新项目。


#### 模型层概要


在项目里面，<ruby> 模型 <rt>  model </rt></ruby>代表从数据库里取出的信息的具体对象。我们关注两个对象：`Customer` 和 `Bike`。首先，在 `src` 目录创建 `dto` 目录；然后，创建两个名为 `Customer.java` 和 `Bike.java` 的 Java 类对象文件。其结构如下示：



```
package com.stephb.JavaMongo.dto;

import lombok.Getter;
import lombok.Setter;
import org.springframework.data.annotation.Id;

/**
 *
 * @author stephon
 */
@Getter @Setter
public class Customer {

        private @Id String id;
        private String emailAddress;
        private String firstName;
        private String lastName;
        private String address;
        
}
```

*Customer.Java*



```
package com.stephb.JavaMongo.dto;

import lombok.Getter;
import lombok.Setter;
import org.springframework.data.annotation.Id;

/**
 *
 * @author stephon
 */
@Getter @Setter
public class Bike {
        private @Id String id;
        private String modelNumber;
        private String color;
        private String description;

        @Override
        public String toString() {
                return "This bike model is " + this.modelNumber + " is the color " + this.color + " and is " + description;
        }
}
```

*Bike.java*


如你所见，对象中使用 Lombok 注解来为定义的<ruby> 属性 <rt>  properties </rt></ruby>/<ruby> 特性 <rt>  attributes </rt></ruby>生成 getters/setters 方法。如果你不想对该类的所有特性都生成 getters/setters 方法，可以在属性上专门定义这些注解。这两个类会变成容器，里面携带有数据，无论在何处想显示信息都可以使用。


#### 配置数据库


我使用 [Mongo Docker](https://hub.docker.com/_/mongo) 容器来进行此次测试。如果你的系统上已经安装了 MongoDB，则不必运行 Docker 实例。你也可以登录其官网，选择系统信息，然后按照安装说明来安装 MongoDB。


安装后，就可以使用命令行、GUI（例如 MongoDB Compass）或用于连接数据源的 IDE 驱动程序来与新的 MongoDB 服务器进行交互。到目前为止，可以开始定义数据层了，用来拉取、转换和持久化数据。需要设置数据库访问属性，请导航到程序中的 `applications.properties` 文件，然后添加如下内容：



```
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=BikeStore
```

#### 定义数据访问对象/数据访问层


<ruby> 数据访问层 <rt>  data access layer </rt></ruby>（DAL）中的<ruby> 数据访问对象 <rt>  data access objects </rt></ruby>（DAO）定义了与数据库中的数据的交互过程。令人惊叹的就是在使用 `spring-boot-starter` 后，查询数据库的大部分工作已经完成。


让我们从 `Customer` DAO 开始。在 `src` 下的新目录 `dao` 中创建一个接口文件，然后再创建一个名为 `CustomerRepository.java` 的 Java 类文件，其内容如下示：



```
package com.stephb.JavaMongo.dao;

import com.stephb.JavaMongo.dto.Customer;
import java.util.List;
import org.springframework.data.mongodb.repository.MongoRepository;

/**
 *
 * @author stephon
 */
public interface CustomerRepository extends MongoRepository<Customer, String>{
        @Override
        public List<Customer> findAll();
        public List<Customer> findByFirstName(String firstName);
        public List<Customer> findByLastName(String lastName);
}
```

这个类是一个接口，扩展或继承于 `MongoRepository` 类，而 `MongoRepository` 类依赖于 DTO （`Customer.java`）和一个字符串，它们用来实现自定义函数查询功能。因为你已继承自此类，所以你可以访问许多方法函数，这些函数允许持久化和查询对象，而无需实现或引用自己定义的方法函数。例如，在实例化 `CustomerRepository` 对象后，你就可以直接使用 `Save` 函数。如果你需要扩展更多的功能，也可以重写这些函数。我创建了一些自定义查询来搜索我的集合，这些集合对象是我自定义的元素。


`Bike` 对象也有一个存储源负责与数据库交互。与 `CustomerRepository` 的实现非常类似。其实现如下所示：



```
package com.stephb.JavaMongo.dao;

import com.stephb.JavaMongo.dto.Bike;
import java.util.List;
import org.springframework.data.mongodb.repository.MongoRepository;

/**
 *
 * @author stephon
 */
public interface BikeRepository extends MongoRepository<Bike,String>{
        public Bike findByModelNumber(String modelNumber);
        @Override
        public List<Bike> findAll();
        public List<Bike> findByColor(String color);
}
```

#### 运行程序


现在，你已经有了一种结构化数据的方式，可以对数据进行提取、转换和持久化，然后运行这个程序。


找到 `Application.java` 文件（有可能不是此名称，具体取决于你的应用程序名称，但都会包含有 “application” ）。在定义此类的地方，在后面加上 `implements CommandLineRunner`。这将允许你实现 `run` 方法来创建命令行应用程序。重写 `CommandLineRunner` 接口提供的 `run` 方法，并包含如下内容用来测试 `BikeRepository` ：



```
package com.stephb.JavaMongo;

import com.stephb.JavaMongo.dao.BikeRepository;
import com.stephb.JavaMongo.dao.CustomerRepository;
import com.stephb.JavaMongo.dto.Bike;
import java.util.Scanner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication
public class JavaMongoApplication implements CommandLineRunner {
                @Autowired
                private BikeRepository bikeRepo;
                private CustomerRepository custRepo;
                
    public static void main(String[] args) {
                        SpringApplication.run(JavaMongoApplication.class, args);
    }
        @Override
        public void run(String... args) throws Exception {
                Scanner scan = new Scanner(System.in);
                String response = "";
                boolean running = true;
                while(running){
                        System.out.println("What would you like to create? \n C: The Customer \n B: Bike? \n X:Close");
                        response = scan.nextLine();
                        if ("B".equals(response.toUpperCase())) {
                                String[] bikeInformation = new String[3];
                                System.out.println("Enter the information for the Bike");
                                System.out.println("Model Number");
                                bikeInformation[0] = scan.nextLine();
                                System.out.println("Color");
                                bikeInformation[1] = scan.nextLine();
                                System.out.println("Description");
                                bikeInformation[2] = scan.nextLine();

                                Bike bike = new Bike();
                                bike.setModelNumber(bikeInformation[0]);
                                bike.setColor(bikeInformation[1]);
                                bike.setDescription(bikeInformation[2]);

                                bike = bikeRepo.save(bike);
                                System.out.println(bike.toString());


                        } else if ("X".equals(response.toUpperCase())) {
                                System.out.println("Bye");
                                running = false;
                        } else {
                                System.out.println("Sorry nothing else works right now!");
                        }
                }
                
        }
}
```

其中的 `@Autowired` 注解会自动依赖注入 `BikeRepository` 和 `CustomerRepository` Bean。我们将使用这些类来从数据库持久化和采集数据。


已经好了。你已经创建了一个命令行应用程序。该应用程序连接到数据库，并且能够以最少的代码执行 CRUD 操作


### 结论


从诸如对象和类之类的编程语言概念转换为用于在数据库中存储、检索或更改数据的调用对于构建应用程序至关重要。Java 持久化 API（JPA）正是为 Java 开发人员解决这一难题的重要工具。你正在使用 Java 操纵哪些数据库呢？请在评论中分享。




---


via: <https://opensource.com/article/19/10/using-java-persistence-api>


作者：[Stephon Brown](https://opensource.com/users/stephb) 选题：[lujun9972](https://github.com/lujun9972) 译者：[runningwater](https://github.com/runningwater) 校对：[wxy](https://github.com/wxy)


本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


OK
The Java Persistence API (JPA) is an important Java functionality for application developers to understand. It translates exactly how Java developers turn method calls on objects into accessing, persisting, and managing data stored in NoSQL and relational databases.

This article examines the JPA in detail through a tutorial example of building a bicycle loaning service. This example will create a create, read, update, and delete (CRUD) layer for a larger application using the Spring Boot framework, the MongoDB database (which is [no longer open source](https://www.techrepublic.com/article/mongodb-ceo-tells-hard-truths-about-commercial-open-source/)), and the Maven package manager. I also use NetBeans 11 as my IDE of choice.

This tutorial focuses on the open source angle of the Java Persistence API, rather than the tools, to show how it works. This is all about learning the pattern of programming applications, but it's still smart to understand the software. You can access the full code in my [GitHub repository](https://github.com/StephonBrown/SpringMongoJava).

## Java: More than 'beans'


Java is an object-oriented language that has gone through many changes since the Java Development Kit (JDK) was released in 1996. Understanding the language's various pathways and its virtual machine is a history lesson in itself; in brief, the language has forked in many directions, similar to the Linux kernel, since its release. There are standard editions that are free to the community, enterprise editions for business, and an open source alternatives contributed to by multiple vendors. Major versions are released at six-month intervals; since there are often major differences in features, you may want to do some research before choosing a version.

All and all, Java is steeped in history. This tutorial focuses on [JDK 11](https://openjdk.java.net/projects/jdk/11/), which is the open source implementation of Java 11, because it is one of the long-term-support versions that is still active.

**Spring Boot:**Spring Boot is a module from the larger Spring framework developed by Pivotal. Spring is a very popular framework for working with Java. It allows for a variety of architectures and configurations. Spring also offers support for web applications and security. Spring Boot offers basic configurations for bootstrapping various types of Java projects quickly. This tutorial uses Spring Boot to quickly write a console application and test functionality against the database.**Maven:**Maven is a project/package manager developed by Apache. Maven allows for the management of packages and various dependencies within its POM.xml file. If you have used NPM, you may be familiar with how package managers function. Maven also manages build and reporting functionality.**Lombok:**Lombok is a library that allows the creation of object getters/setters through annotation within the object file. This is already present in languages like C#, and Lombok introduces this functionality into Java.**NetBeans:**NetBeans is a popular open source IDE that focuses specifically on Java development. Many of its tools provide an implementation for the latest Java SE and EE updates.

This group of tools will be used to create a simple application for a fictional bike store. It will implement functionality for inserting collections for "Customer" and "Bike" objects.

## Brewed to perfection

Navigate to the [Spring Initializr](https://start.spring.io/). This website enables you to generate basic project needs for Spring Boot and the dependencies you will need for the project. Select the following options:

**Project:**Maven Project**Language:**Java**Spring Boot:**2.1.8 (or the most stable release)**Project Metadata:**Whatever your naming conventions are (e.g.,**com.stephb**)- You can keep Artifact as "Demo"

**Dependencies:**Add:- Spring Data MongoDB
- Lombok


Click **Download** and open the new project in your chosen IDE (e.g., NetBeans).

### Model outline

The models represent information collected about specific objects in the program that will be persisted in your database. Focus on two objects: **Customer** and **Bike**. First, create a **dto** folder within the **src** folder. Then, create the two Java class objects named **Customer.java** and **Bike.java**. They will be structured in the program as follows:

**Customer. Java**

```
1 package com.stephb.JavaMongo.dto;
2
3 import lombok.Getter;
4 import lombok.Setter;
5 import org.springframework.data.annotation.Id;
6
7 /**
8 *
9 * @author stephon
10 */
11 @Getter @Setter
12 public class Customer {
13
14 private @Id String id;
15 private String emailAddress;
16 private String firstName;
17 private String lastName;
18 private String address;
19
20 }
```


**Bike.java**

```
1 package com.stephb.JavaMongo.dto;
2
3 import lombok.Getter;
4 import lombok.Setter;
5 import org.springframework.data.annotation.Id;
6
7 /**
8 *
9 * @author stephon
10 */
11 @Getter @Setter
12 public class Bike {
13 private @Id String id;
14 private String modelNumber;
15 private String color;
16 private String description;
17
18 @Override
19 public String toString() {
20 return "This bike model is " + this.modelNumber + " is the color " + this.color + " and is " + description;
21 }
22 }
```


As you can see, Lombok annotation is used within the object to generate the getters/setters for the properties/attributes. Properties can specifically receive the annotations if you do not want all of the attributes to have getters/setters within that class. These two classes will form the container carrying your data to wherever you want to display information.

### Set up a database

I used a [Mongo Docker](https://hub.docker.com/_/mongo) container for testing. If you have MongoDB installed on your system, you do not have to run an instance in Docker. You can install MongoDB from its website by selecting your system information and following the installation instructions.

After installing, you can interact with your new MongoDB server through the command line, a GUI such as MongoDB Compass, or IDE drivers for connecting to data sources. Now you can define your data layer to pull, transform, and persist your data. To set your database access properties, navigate to the **applications.properties** file in your application and provide the following:

```
1 spring.data.mongodb.host=localhost
2 spring.data.mongodb.port=27017
3 spring.data.mongodb.database=BikeStore
```


### Define the data access object/data access layer

The data access objects (DAO) in the data access layer (DAL) will define how you will interact with data in the database. The awesome thing about using a **spring-boot-starter** is that most of the work for querying the database is already done.

Start with the **Customer** DAO. Create an interface in a new **dao** folder within the **src** folder, then create another Java class name called **CustomerRepository.java**. The class should look like:

```
1 package com.stephb.JavaMongo.dao;
2
3 import com.stephb.JavaMongo.dto.Customer;
4 import java.util.List;
5 import org.springframework.data.mongodb.repository.MongoRepository;
6
7 /**
8 *
9 * @author stephon
10 */
11 public interface CustomerRepository extends MongoRepository<Customer, String>{
12 @Override
13 public List<Customer> findAll();
14 public List<Customer> findByFirstName(String firstName);
15 public List<Customer> findByLastName(String lastName);
16 }
```


This class is an interface that extends or inherits from the **MongoRepository** class with your DTO (**Customer.java**) and a string because they will be used for querying with your custom functions. Because you have inherited from this class, you have access to many functions that allow persistence and querying of your object without having to implement or reference your own functions. For example, after you instantiate the **CustomerRepository** object, you can use the **Save** function immediately. You can also override these functions if you need more extended functionality. I created a few custom queries to search my collection, given specific elements of my object.

The **Bike** object also has a repository for interacting with the database. Implement it very similarly to the **CustomerRepository**. It should look like:

```
1 package com.stephb.JavaMongo.dao;
2
3 import com.stephb.JavaMongo.dto.Bike;
4 import java.util.List;
5 import org.springframework.data.mongodb.repository.MongoRepository;
6
7 /**
8 *
9 * @author stephon
10 */
11 public interface BikeRepository extends MongoRepository<Bike,String>{
12 public Bike findByModelNumber(String modelNumber);
13 @Override
14 public List<Bike> findAll();
15 public List<Bike> findByColor(String color);
16 }
```


### Run your program

Now that you have a way to structure your data and a way to pull, transform, and persist it, run your program!

Navigate to your **Application.java** file (it may have a different name, depending on what you named your application, but it should include "application"). Where the class is defined, include an **implements CommandLineRunner** afterward. This will allow you to implement a **run** method to create a command-line application. Override the **run** method provided by the **CommandLineRunner** interface and include the following to test the **BikeRepository**:

```
1 package com.stephb.JavaMongo;
2
3 import com.stephb.JavaMongo.dao.BikeRepository;
4 import com.stephb.JavaMongo.dao.CustomerRepository;
5 import com.stephb.JavaMongo.dto.Bike;
6 import java.util.Scanner;
7 import org.springframework.beans.factory.annotation.Autowired;
8 import org.springframework.boot.CommandLineRunner;
9 import org.springframework.boot.SpringApplication;
10 import org.springframework.boot.autoconfigure.SpringBootApplication;
11
12
13 @SpringBootApplication
14 public class JavaMongoApplication implements CommandLineRunner {
15 @Autowired
16 private BikeRepository bikeRepo;
17 private CustomerRepository custRepo;
18
19 public static void main(String[] args) {
20 SpringApplication.run(JavaMongoApplication.class, args);
21 }
22 @Override
23 public void run(String... args) throws Exception {
24 Scanner scan = new Scanner(System.in);
25 String response = "";
26 boolean running = true;
27 while(running){
28 System.out.println("What would you like to create? \n C: The Customer \n B: Bike? \n X:Close");
29 response = scan.nextLine();
30 if ("B".equals(response.toUpperCase())) {
31 String[] bikeInformation = new String[3];
32 System.out.println("Enter the information for the Bike");
33 System.out.println("Model Number");
34 bikeInformation[0] = scan.nextLine();
35 System.out.println("Color");
36 bikeInformation[1] = scan.nextLine();
37 System.out.println("Description");
38 bikeInformation[2] = scan.nextLine();
39
40 Bike bike = new Bike();
41 bike.setModelNumber(bikeInformation[0]);
42 bike.setColor(bikeInformation[1]);
43 bike.setDescription(bikeInformation[2]);
44
45 bike = bikeRepo.save(bike);
46 System.out.println(bike.toString());
47
48
49 } else if ("X".equals(response.toUpperCase())) {
50 System.out.println("Bye");
51 running = false;
52 } else {
53 System.out.println("Sorry nothing else works right now!");
54 }
55 }
56
57 }
58 }
```


The **@Autowired** annotation allows automatic dependency injection of the **BikeRepository** and **CustomerRepository** beans. You will use these classes to persist and gather data from the database.

There you have it! You have created a command-line application that connects to a database and is able to perform CRUD operations with minimal code on your part.

## Conclusion

Translating from programming language concepts like objects and classes into calls to store, retrieve, or change data in a database is essential to building an application. The Java Persistence API (JPA) is an important tool in the Java developer's toolkit to solve that challenge. What databases are you exploring in Java? Please share in the comments.

## Comments are closed.