让我们从可以构造的最简单的东西开始。实际上,为了使其尽可能简单,我们甚至可以省略 REST 的概念。(稍后,我们将添加 REST 以了解两者之间的区别。)
我们的示例为管理公司员工的简单工资服务建模。简而言之,我们需要将员工对象存储在 H2 内存数据库中,并通过 JPA 访问它们。这将被 Spring MVC 层包装以进行远程访问。
nonrest/src/main/java/payroll/Employee.java
package payroll;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Data
@Entity
class Employee {
private @Id @GeneratedValue Long id;
private String name;
private String role;
Employee() {}
Employee(String name, String role) {
this.name = name;
this.role = role;
}
}
尽管很小,但该 Java 类包含许多内容:
@Data
是 Lombok 注解,用于基于字段插件所有 getter、setter、equals
、hash
和toString
方法;@Entity
是一个 JPA 注解,可以使该对象准备好存储在基于 JPA 的数据存储区中;id
、name
,和role
是域对象的属性,第一个被标记了更多的 JPA 注解以指示它是主键,并由 JPA 提供程序自动填充;- 当我们需要创建新实例但还没有 ID 时,就会创建一个自定义构造函数。
有了这个领域对象定义,我们现在可以转向 Spring Data JPA 来处理繁琐的数据库交互。Spring Data 存储库是具有支持针对后端数据存储读取、更新、删除和创建记录的方法的接口。在适当的情况下,某些存储库还支持数据分页和排序。Spring Data 根据在接口中的方法命名中找到的约定来综合实现。
除了 JPA,还有多种存储库实现。我们可以使用 Spring Data MongoDB、Spring Data GemFire、Spring Data Cassandra 等。在该教程中,我们将一直使用 JPA。
nonrest/src/main/java/payroll/EmployeeRepository.java
package payroll;
import org.springframework.data.jpa.repository.JpaRepository;
interface EmployeeRepository extends JpaRepository<Employee, Long> {
}
该接口扩展了 Spring Data JPA 的 JpaRepository
,将域类型指定为 Employee
并将 ID 类型指定为 Long
。该接口尽管表面上是空的,但只要它支持,它就会将其打包:
- 创建新实例;
- 更新现有的;
- 删除中;
- 查找(一个、全部、通过简单或复杂的属性)
Spring Data 的存储库解决方案可以避开数据存储的详细信息,而可以使用特定于域的术语来解决大多数问题。
信不信由你,这足以启动一个应用!Spring Boot 应用至少是一个 public static void main
入口点和 @SpringBootApplication
注解。这告诉 Spring Boot 尽可能地提供帮助。
nonrest/src/main/java/payroll/PayrollApplication.java
package payroll;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class PayrollApplication {
public static void main(String... args) {
SpringApplication.run(PayrollApplication.class, args);
}
}
@SpringBootApplication
是一个元注解,可引入组件扫描、自动配置,和属性支持。在该教程中,我们不会深入探讨 Spring Boot 的细节,但从本质上讲,它将启动 servlet 容器并提供我们的服务。
不过,没有数据的应用并不是很有趣,所以让我们预加载它。其后的类将在 Spring 之前自动加载:
nonrest/src/main/java/payroll/LoadDatabase.java
package payroll;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@Slf4j
class LoadDatabase {
@Bean
CommandLineRunner initDatabase(EmployeeRepository repository) {
return args -> {
log.info("Preloading " + repository.save(new Employee("Bilbo Baggins", "burglar")));
log.info("Preloading " + repository.save(new Employee("Frodo Baggins", "thief")));
};
}
}
加载后会发生什么?
- 一旦应用上下文被家在,Spring Boot 将运行所有
CommandLineRunner
的 bean; - 该运行器将请求我们刚刚创建的
EmployeeRepository
副本; - 使用它,它将创建两个实体并将其存储;
@Slf4j
是 Lombok 注解,用于自动创建基于 Slf4j 的LoggerFactory
作为log
,从而使我们可以记录这些新创建的 “员工”。
右键单击并运行 PayRollApplication
,这是我们得到的:
控制台输出的片段,显示数据的预加载
...
2018-08-09 11:36:26.169 INFO 74611 --- [main] payroll.LoadDatabase : Preloading Employee(id=1, name=Bilbo Baggins, role=burglar)
2018-08-09 11:36:26.174 INFO 74611 --- [main] payroll.LoadDatabase : Preloading Employee(id=2, name=Frodo Baggins, role=thief)
...
这不是完整的日志,而只是预加载数据的关键部分。(的确,请查看整个控制台。这很辉煌。)