Spring Data JPA
对象与关系的范式不匹配
Hibernate
- ⼀款开源的对象关系映射(Object / Relational Mapping)框架
- 将开发者从 95% 的常 ⻅数据持久化 ⼯作中解放出来
- 屏蔽了底层数据库的各种细节
- 2006 年,Hibernate 3.2 成为 JPA 实现
Reference
Java Persistence API
JPA1.0 是作为 JSR 220 的一部分正式发布。
- 简化数据持久化代码的开发工作
- 为 Java 社区屏蔽不同持久化 API 的差异(屏蔽了 Hibernate、JDO、EJB 之间的差异)
- 相当于在 O/R Mapping 框架之前做了一层抽象。
Spring Data
在保留底层存储特性的同时,提供相对 ⼀致的、基于 Spring 的编程模型。Spring Family List :
- Spring Data Commons
- Spring Data JDBC
- Spring Data JPA
- Spring Data Redis
- ……
如何引入 Spring Data JPA
1<dependency>
2 <groupId>org.springframework.boot</groupId>
3 <artifactId>spring-boot-starter-data-jpa</artifactId>
4 </dependency>
常用 JPA 注解
实体
- @Entity:声明此类为一个实体。
- @MappedSuperclass:在多个实体类的父类上面标注。
- @Table(name):实体与表关联。如果没有写 @Table 注解,会自动将该类的名字作为表名。
主键
@Id
- @GeneratedValue(strategy, generator):用于指定主键的生成策略、和对应的生成器。
- @SequenceGenerator(name, sequenceName):指定序列。
映射
- @Column(name, nullable, length, insertable, updatable)
- @JoinTable(name):关联查询时,表与表是多对多的关系时,指定多对多关联表中间表的参数。
- @JoinColumn(name):关联查询时,表与表是一对一、一对多、多对一以及多对多的关系时,声明表关联的外键字段作为连接表的条件。必须配合关联表的注解一起使用
关系
- @OneToOne:关联表注解,表示对应的实体和本类是一对一的关系
- @OneToMany:关联表注解,表示对应的实体和本类是一对多的关系
- @ManyToOne:关联表注解,表示对应的实体和本类是多对一的关系
- @ManyToMany:关联表注解,表示对应的实体和本类是多对多的关系
- @OrderBy:
BucksProject
项目目标
引入依赖
1<?xml version="1.0" encoding="UTF-8"?>
2<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4 <modelVersion>4.0.0</modelVersion>
5 <parent>
6 <groupId>org.springframework.boot</groupId>
7 <artifactId>spring-boot-starter-parent</artifactId>
8 <version>2.1.2.RELEASE</version>
9 <relativePath/> <!-- lookup parent from repository -->
10 </parent>
11 <groupId>geektime.spring.springbucks</groupId>
12 <artifactId>jpa-demo</artifactId>
13 <version>0.0.1-SNAPSHOT</version>
14 <name>jpa-demo</name>
15 <description>Demo project for Spring Boot</description>
16
17 <properties>
18 <java.version>1.8</java.version>
19 </properties>
20
21 <dependencies>
22 <dependency>
23 <groupId>org.springframework.boot</groupId>
24 <artifactId>spring-boot-starter-data-jpa</artifactId>
25 </dependency>
26
27 <dependency>
28 <groupId>org.joda</groupId>
29 <artifactId>joda-money</artifactId>
30 <version>1.0.1</version>
31 </dependency>
32 <dependency>
33 <groupId>org.jadira.usertype</groupId>
34 <artifactId>usertype.core</artifactId>
35 <version>6.0.1.GA</version>
36 </dependency>
37
38 <dependency>
39 <groupId>com.h2database</groupId>
40 <artifactId>h2</artifactId>
41 <scope>runtime</scope>
42 </dependency>
43 <dependency>
44 <groupId>org.projectlombok</groupId>
45 <artifactId>lombok</artifactId>
46 <optional>true</optional>
47 </dependency>
48 <dependency>
49 <groupId>org.springframework.boot</groupId>
50 <artifactId>spring-boot-starter-test</artifactId>
51 <scope>test</scope>
52 </dependency>
53 </dependencies>
54
55 <build>
56 <plugins>
57 <plugin>
58 <groupId>org.springframework.boot</groupId>
59 <artifactId>spring-boot-maven-plugin</artifactId>
60 </plugin>
61 </plugins>
62 </build>
63</project>
application.properties
1# 定义DDL 每次运行都会创建表结构、每次结束都会删除
2spring.jpa.hibernate.ddl-auto=create-drop
3# 打印sql
4spring.jpa.properties.hibernate.show_sql=true
5# 对sql进行格式化
6spring.jpa.properties.hibernate.format_sql=true
实体定义
BaseEntity
1package geektime.spring.springbucks.jpademo.model;
2
3import lombok.AllArgsConstructor;
4import lombok.Data;
5import lombok.NoArgsConstructor;
6import org.hibernate.annotations.CreationTimestamp;
7import org.hibernate.annotations.UpdateTimestamp;
8
9import javax.persistence.Column;
10import javax.persistence.GeneratedValue;
11import javax.persistence.Id;
12import javax.persistence.MappedSuperclass;
13import java.io.Serializable;
14import java.util.Date;
15
16@MappedSuperclass
17@Data
18@NoArgsConstructor
19@AllArgsConstructor
20public class BaseEntity implements Serializable {
21 @Id
22 @GeneratedValue
23 private Long id;
24 @Column(updatable = false)
25 @CreationTimestamp
26 private Date createTime;
27 @UpdateTimestamp
28 private Date updateTime;
29}
Coffee
1package geektime.spring.springbucks.jpademo.model;
2
3import lombok.AllArgsConstructor;
4import lombok.Builder;
5import lombok.Data;
6import lombok.NoArgsConstructor;
7import lombok.ToString;
8import org.hibernate.annotations.Type;
9import org.joda.money.Money;
10
11import javax.persistence.Entity;
12import javax.persistence.Table;
13import java.io.Serializable;
14
15@Entity
16@Table(name = "T_MENU")
17@Builder
18@Data
19@ToString(callSuper = true)
20@NoArgsConstructor
21@AllArgsConstructor
22public class Coffee extends BaseEntity implements Serializable {
23 private String name;
24 @Type(type = "org.jadira.usertype.moneyandcurrency.joda.PersistentMoneyAmount",
25 parameters = {@org.hibernate.annotations.Parameter(name = "currencyCode", value = "CNY")})
26 private Money price;
27}
CoffeeOrder
1package geektime.spring.springbucks.jpademo.model;
2
3import lombok.AllArgsConstructor;
4import lombok.Builder;
5import lombok.Data;
6import lombok.NoArgsConstructor;
7import lombok.ToString;
8
9import javax.persistence.Column;
10import javax.persistence.Entity;
11import javax.persistence.Enumerated;
12import javax.persistence.JoinTable;
13import javax.persistence.ManyToMany;
14import javax.persistence.OrderBy;
15import javax.persistence.Table;
16import java.io.Serializable;
17import java.util.List;
18
19@Entity
20@Table(name = "T_ORDER")
21@Data
22@ToString(callSuper = true)
23@NoArgsConstructor
24@AllArgsConstructor
25@Builder
26public class CoffeeOrder extends BaseEntity implements Serializable {
27 private String customer;
28 @ManyToMany
29 @JoinTable(name = "T_ORDER_COFFEE")
30 @OrderBy("id")
31 private List<Coffee> items;
32 @Enumerated
33 @Column(nullable = false)
34 private OrderState state;
35}
OrderState 枚举类(描述订单的状态)
1package geektime.spring.springbucks.jpademo.model;
2
3public enum OrderState {
4 INIT, PAID, BREWING, BREWED, TAKEN, CANCELLED
5}
控制台输出
1# 如果有,删除
2Hibernate:
3
4 drop table t_menu if exists
5Hibernate:
6
7 drop table t_order if exists
8Hibernate:
9
10 drop table t_order_coffee if exists
11Hibernate:
12
13 drop sequence if exists hibernate_sequence
14Hibernate: create sequence hibernate_sequence start with 1 increment by 1
15
16# 创建表结构
17Hibernate:
18
19 create table t_menu (
20 id bigint not null,
21 create_time timestamp,
22 name varchar(255),
23 price decimal(19,2),
24 update_time timestamp,
25 primary key (id)
26 )
27Hibernate:
28
29 create table t_order (
30 id bigint not null,
31 create_time timestamp,
32 customer varchar(255),
33 state integer not null,
34 update_time timestamp,
35 primary key (id)
36 )
37Hibernate:
38
39 create table t_order_coffee (
40 coffee_order_id bigint not null,
41 items_id bigint not null
42 )
43Hibernate:
44
45 alter table t_order_coffee
46 add constraint FKj2swxd3y69u2tfvalju7sr07q
47 foreign key (items_id)
48 references t_menu
49Hibernate:
50
51 alter table t_order_coffee
52 add constraint FK33ucji9dx64fyog6g17blpx9v
53 foreign key (coffee_order_id)
54 references t_order
55
56# 删除
57Hibernate:
58
59 drop table t_menu if exists
60Hibernate:
61
62 drop table t_order if exists
63Hibernate:
64
65 drop table t_order_coffee if exists
66Hibernate:
67
68 drop sequence if exists hibernate_sequence
通过 Spring Data JPA 操作数据库
启动类添加 @EnableJpaRepositories
Repository<T, ID> 接口
- CrudRepository<T, ID>
- PagingAndSortingRepository<T, ID>
- JpaRepository<T, ID>
定义查询
根据方法名定义查询
- find…By… / read…By… / query…By… / get…By…
- count…By…
- …OrderBy…[Asc / Desc]
- And / Or / IgnoreCase
- Top / First / Distinct
分页查询
- PagingAndSortingRepository<T, ID>
- Pageable / Sort
- Slice
/ Page
定义 Repository
BaseRepository
1package geektime.spring.springbucks.jpademo.repository;
2
3import org.springframework.data.repository.NoRepositoryBean;
4import org.springframework.data.repository.PagingAndSortingRepository;
5
6import java.util.List;
7
8@NoRepositoryBean
9public interface BaseRepository<T, Long> extends PagingAndSortingRepository<T, Long> {
10 /**
11 * 对更新时间进行升序排序,并且查询出前三名
12 * @return
13 */
14 List<T> findTop3ByOrderByUpdateTimeDescIdAsc();
15}
CoffeeRepository
1package geektime.spring.springbucks.jpademo.repository;
2
3import geektime.spring.springbucks.jpademo.model.Coffee;
4
5public interface CoffeeRepository extends BaseRepository<Coffee, Long> {
6}
CoffeeOrderRepository
1package geektime.spring.springbucks.jpademo.repository;
2
3import geektime.spring.springbucks.jpademo.model.CoffeeOrder;
4
5import java.util.List;
6
7public interface CoffeeOrderRepository extends BaseRepository<CoffeeOrder, Long> {
8 List<CoffeeOrder> findByCustomerOrderById(String customer);
9 List<CoffeeOrder> findByItems_Name(String name);
10}
启动类
1package geektime.spring.springbucks.jpademo;
2
3import geektime.spring.springbucks.jpademo.model.Coffee;
4import geektime.spring.springbucks.jpademo.model.CoffeeOrder;
5import geektime.spring.springbucks.jpademo.model.OrderState;
6import geektime.spring.springbucks.jpademo.repository.CoffeeOrderRepository;
7import geektime.spring.springbucks.jpademo.repository.CoffeeRepository;
8import lombok.extern.slf4j.Slf4j;
9import org.joda.money.CurrencyUnit;
10import org.joda.money.Money;
11import org.springframework.beans.factory.annotation.Autowired;
12import org.springframework.boot.ApplicationArguments;
13import org.springframework.boot.ApplicationRunner;
14import org.springframework.boot.SpringApplication;
15import org.springframework.boot.autoconfigure.SpringBootApplication;
16import org.springframework.data.domain.Sort;
17import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
18import org.springframework.transaction.annotation.EnableTransactionManagement;
19
20import javax.transaction.Transactional;
21import java.util.Arrays;
22import java.util.Collections;
23import java.util.List;
24import java.util.stream.Collectors;
25
26@SpringBootApplication
27@EnableJpaRepositories
28@EnableTransactionManagement
29@Slf4j
30public class JpaDemoApplication implements ApplicationRunner {
31 @Autowired
32 private CoffeeRepository coffeeRepository;
33 @Autowired
34 private CoffeeOrderRepository orderRepository;
35
36 public static void main(String[] args) {
37 SpringApplication.run(JpaDemoApplication.class, args);
38 }
39
40 @Override
41 @Transactional
42 public void run(ApplicationArguments args) throws Exception {
43 initOrders();
44 findOrders();
45 }
46
47 /**
48 * 增
49 */
50 private void initOrders() {
51 //保存咖啡:Coffee表添加拿铁
52 Coffee latte = Coffee.builder().name("latte")
53 .price(Money.of(CurrencyUnit.of("CNY"), 30.0))
54 .build();
55 coffeeRepository.save(latte);
56 log.info("Coffee: {}", latte);
57
58 //保存咖啡:Coffee表添加特浓
59 Coffee espresso = Coffee.builder().name("espresso")
60 .price(Money.of(CurrencyUnit.of("CNY"), 20.0))
61 .build();
62 coffeeRepository.save(espresso);
63 log.info("Coffee: {}", espresso);
64
65 //Li Lei 第一个订单(特浓)
66 CoffeeOrder order = CoffeeOrder.builder()
67 .customer("Li Lei")
68 .items(Collections.singletonList(espresso))//不可变List
69 .state(OrderState.INIT) //状态为INIT
70 .build();
71 orderRepository.save(order);
72 log.info("Order: {}", order);
73
74 //Li Lei 第二个订单(特浓、拿铁)
75 order = CoffeeOrder.builder()
76 .customer("Li Lei")
77 .items(Arrays.asList(espresso, latte))
78 .state(OrderState.INIT)
79 .build();
80 orderRepository.save(order);
81 log.info("Order: {}", order);
82 }
83
84 /**
85 * 查询
86 */
87 private void findOrders() {
88
89 //查询咖啡:根据咖啡的ID降序
90 coffeeRepository
91 .findAll(Sort.by(Sort.Direction.DESC, "id"))
92 .forEach(c -> log.info("Loading {}", c));
93
94 //查询订单:对订单的更新时间进行升序排序,并且查询出前三名
95 List<CoffeeOrder> list = orderRepository.findTop3ByOrderByUpdateTimeDescIdAsc();
96 log.info("findTop3ByOrderByUpdateTimeDescIdAsc: {}", getJoinedOrderId(list));
97
98 //查询订单: 查询顾客为Li Lei的所有订单:(输出其订单号每个订单的ID,及其包含的咖啡)
99 list = orderRepository.findByCustomerOrderById("Li Lei");
100 log.info("findByCustomerOrderById: {}", getJoinedOrderId(list));
101 // 不开启事务会因为没Session而报LazyInitializationException
102 list.forEach(o -> {
103 log.info("Order {}", o.getId());
104 o.getItems().forEach(i -> log.info(" Item {}", i));
105 });
106
107 //查询订单:查询订单中包含 拿铁的 所有订单(Items_Name 相当于查询items属性所包含集合中每个元素的name属性)
108 list = orderRepository.findByItems_Name("latte");
109 log.info("findByItems_Name: {}", getJoinedOrderId(list));
110 }
111
112 //过滤器list中的id,并且添加分隔符循环遍历
113 private String getJoinedOrderId(List<CoffeeOrder> list) {
114 return list.stream().map(o -> o.getId().toString())
115 .collect(Collectors.joining(","));
116 }
117}
控制台输出
1//第一订单:orderRepository.save(order);
2 Order: CoffeeOrder(super=BaseEntity(id=3, createTime=null, updateTime=null), customer=Li Lei, items=[Coffee(super=BaseEntity(id=2, createTime=null, updateTime=null), name=espresso, price=CNY 20.00)], state=INIT)
3
4//第一订单:orderRepository.save(order);
5Order: CoffeeOrder(super=BaseEntity(id=4, createTime=null, updateTime=null), customer=Li Lei, items=[Coffee(super=BaseEntity(id=2, createTime=null, updateTime=null), name=espresso, price=CNY 20.00), Coffee(super=BaseEntity(id=1, createTime=null, updateTime=null), name=latte, price=CNY 30.00)], state=INIT)
6
7//查询咖啡:根据咖啡的ID降序
8Loading Coffee(super=BaseEntity(id=2, createTime=Thu Jan 09 17:38:01 CST 2020, updateTime=Thu Jan 09 17:38:01 CST 2020), name=espresso, price=CNY 20.00)
9Loading Coffee(super=BaseEntity(id=1, createTime=Thu Jan 09 17:38:01 CST 2020, updateTime=Thu Jan 09 17:38:01 CST 2020), name=latte, price=CNY 30.00)
10
11//查询订单:对订单的更新时间进行升序排序,并且查询出前三名
12findTop3ByOrderByUpdateTimeDescIdAsc: 3,4
13
14//查询订单: 查询顾客为Li Lei的所有订单:(输出其订单号每个订单的ID,及其包含的咖啡)
15findByCustomerOrderById: 3,4
16Order 3
17 Item Coffee(super=BaseEntity(id=2, createTime=Thu Jan 09 17:38:01 CST 2020, updateTime=Thu Jan 09 17:38:01 CST 2020), name=espresso, price=CNY 20.00)
18Order 4
19 Item Coffee(super=BaseEntity(id=2, createTime=Thu Jan 09 17:38:01 CST 2020, updateTime=Thu Jan 09 17:38:01 CST 2020), name=espresso, price=CNY 20.00)
20 Item Coffee(super=BaseEntity(id=1, createTime=Thu Jan 09 17:38:01 CST 2020, updateTime=Thu Jan 09 17:38:01 CST 2020), name=latte, price=CNY 30.00)
21
22//查询订单:查询订单中包含 拿铁的 所有订单(Items_Name 相当于查询items属性所包含集合中每个元素的name属性)
23findByItems_Name: 4
JpaRepository 接口的方法
1@NoRepositoryBean
2public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
3
4 List<T> findAll();
5
6 List<T> findAll(Sort sort);
7
8 List<T> findAllById(Iterable<ID> ids);
9
10 <S extends T> List<S> saveAll(Iterable<S> entities);
11
12 void flush();
13
14 <S extends T> S saveAndFlush(S entity);
15
16 void deleteInBatch(Iterable<T> entities);
17
18 void deleteAllInBatch();
19
20 T getOne(ID id);
21 @Override
22 <S extends T> List<S> findAll(Example<S> example);
23
24 @Override
25 <S extends T> List<S> findAll(Example<S> example, Sort sort);
26}
QueryByExampleExecutor
1public interface QueryByExampleExecutor<T> {
2
3 <S extends T> Optional<S> findOne(Example<S> example);
4
5 <S extends T> Iterable<S> findAll(Example<S> example);
6
7 <S extends T> Iterable<S> findAll(Example<S> example, Sort sort);
8
9 <S extends T> Page<S> findAll(Example<S> example, Pageable pageable);
10
11 <S extends T> long count(Example<S> example);
12
13 <S extends T> boolean exists(Example<S> example);
14}
CoffeeRepository
1package geektime.spring.springbucks.repository;
2
3import geektime.spring.springbucks.model.Coffee;
4import org.springframework.data.jpa.repository.JpaRepository;
5
6public interface CoffeeRepository extends JpaRepository<Coffee, Long> {
7}
CoffeeOrderRepository
1package geektime.spring.springbucks.repository;
2
3import geektime.spring.springbucks.model.CoffeeOrder;
4import org.springframework.data.jpa.repository.JpaRepository;
5
6import java.util.List;
7
8public interface CoffeeOrderRepository extends JpaRepository<CoffeeOrder, Long> {
9 /**
10 * 查询指定用户名的所有订单并根据 id 排序
11 * @param customer
12 * @return
13 */
14 List<CoffeeOrder> findByCustomerOrderById(String customer);
15}
CoffeeService
1package geektime.spring.springbucks.service;
2
3import geektime.spring.springbucks.model.Coffee;
4import geektime.spring.springbucks.model.CoffeeOrder;
5import geektime.spring.springbucks.model.OrderState;
6import geektime.spring.springbucks.repository.CoffeeOrderRepository;
7import lombok.extern.slf4j.Slf4j;
8import org.springframework.beans.factory.annotation.Autowired;
9import org.springframework.stereotype.Service;
10
11import javax.transaction.Transactional;
12import java.util.ArrayList;
13import java.util.Arrays;
14
15@Slf4j
16@Service
17@Transactional
18public class CoffeeOrderService {
19 @Autowired
20 private CoffeeOrderRepository orderRepository;
21
22 public CoffeeOrder createOrder(String customer, Coffee...coffee) {
23 CoffeeOrder order = CoffeeOrder.builder()
24 .customer(customer)
25 .items(new ArrayList<>(Arrays.asList(coffee)))
26 .state(OrderState.INIT)
27 .build();
28 CoffeeOrder saved = orderRepository.save(order);
29 log.info("New Order: {}", saved);
30 return saved;
31 }
32
33 public boolean updateState(CoffeeOrder order, OrderState state) {
34 if (state.compareTo(order.getState()) <= 0) { //检测状态,传入的状态不能比现有订单状态码小
35 log.warn("Wrong State order: {}, {}", state, order.getState());
36 return false;
37 }
38 order.setState(state);
39 orderRepository.save(order);
40 log.info("Updated Order: {}", order);
41 return true;
42 }
43}
CoffeeOrderService
1package geektime.spring.springbucks.service;
2
3import geektime.spring.springbucks.model.Coffee;
4import geektime.spring.springbucks.model.CoffeeOrder;
5import geektime.spring.springbucks.model.OrderState;
6import geektime.spring.springbucks.repository.CoffeeOrderRepository;
7import lombok.extern.slf4j.Slf4j;
8import org.springframework.beans.factory.annotation.Autowired;
9import org.springframework.stereotype.Service;
10
11import javax.transaction.Transactional;
12import java.util.ArrayList;
13import java.util.Arrays;
14import java.util.List;
15
16@Slf4j
17@Service
18@Transactional
19public class CoffeeOrderService {
20 @Autowired
21 private CoffeeOrderRepository orderRepository;
22
23 public CoffeeOrder createOrder(String customer, Coffee...coffee) {
24 CoffeeOrder order = CoffeeOrder.builder()
25 .customer(customer)
26 .items(new ArrayList<>(Arrays.asList(coffee)))
27 .state(OrderState.INIT)
28 .build();
29 CoffeeOrder saved = orderRepository.save(order);
30 log.info("New Order: {}", saved);
31 return saved;
32 }
33
34 public boolean updateState(CoffeeOrder order, OrderState state) {
35 if (state.compareTo(order.getState()) <= 0) { //检测状态,传入的状态不能比现有订单状态码小
36 log.warn("Wrong State order: {}, {}", state, order.getState());
37 return false;
38 }
39 order.setState(state);
40 orderRepository.save(order);
41 log.info("Updated Order: {}", order);
42 return true;
43 }
44
45 public List<CoffeeOrder> findByCustomerOrderById(String customer){
46 return orderRepository.findByCustomerOrderById(customer);
47 }
48}
启动类
1package geektime.spring.springbucks;
2
3import geektime.spring.springbucks.model.Coffee;
4import geektime.spring.springbucks.model.CoffeeOrder;
5import geektime.spring.springbucks.model.OrderState;
6import geektime.spring.springbucks.repository.CoffeeRepository;
7import geektime.spring.springbucks.service.CoffeeOrderService;
8import geektime.spring.springbucks.service.CoffeeService;
9import lombok.extern.slf4j.Slf4j;
10import org.springframework.beans.factory.annotation.Autowired;
11import org.springframework.boot.ApplicationArguments;
12import org.springframework.boot.ApplicationRunner;
13import org.springframework.boot.SpringApplication;
14import org.springframework.boot.autoconfigure.SpringBootApplication;
15import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
16import org.springframework.transaction.annotation.EnableTransactionManagement;
17
18import javax.swing.text.html.Option;
19import java.security.spec.ECParameterSpec;
20import java.util.List;
21import java.util.Optional;
22import java.util.stream.Collectors;
23
24@Slf4j
25@EnableTransactionManagement
26@SpringBootApplication
27@EnableJpaRepositories
28public class SpringBucksApplication implements ApplicationRunner {
29 @Autowired
30 private CoffeeRepository coffeeRepository;
31 @Autowired
32 private CoffeeService coffeeService;
33 @Autowired
34 private CoffeeOrderService orderService;
35
36 public static void main(String[] args) {
37 SpringApplication.run(SpringBucksApplication.class, args);
38 }
39
40 @Override
41 public void run(ApplicationArguments args) throws Exception {
42 //直接使用coffeeRepository
43 log.info("All Coffee: {}", coffeeRepository.findAll());
44 //All Coffee: [Coffee(super=BaseEntity(id=1, createTime=2020-01-12 16:03:36.35, updateTime=2020-01-12 16:03:36.35), name=espresso, price=CNY 20.00), Coffee(super=BaseEntity(id=2, createTime=2020-01-12 16:03:36.352, updateTime=2020-01-12 16:03:36.352), name=latte, price=CNY 25.00), Coffee(super=BaseEntity(id=3, createTime=2020-01-12 16:03:36.352, updateTime=2020-01-12 16:03:36.352), name=capuccino, price=CNY 25.00), Coffee(super=BaseEntity(id=4, createTime=2020-01-12 16:03:36.352, updateTime=2020-01-12 16:03:36.352), name=mocha, price=CNY 30.00), Coffee(super=BaseEntity(id=5, createTime=2020-01-12 16:03:36.352, updateTime=2020-01-12 16:03:36.352), name=macchiato, price=CNY 30.00)]
45
46 //findOneCoffee
47 Optional<Coffee> latte = coffeeService.findOneCoffee("Latte");
48 Optional<Coffee> espresso = coffeeService.findOneCoffee("espresso");
49 if (latte.isPresent() && espresso.isPresent()) {
50 CoffeeOrder order = orderService.createOrder("Li Lei", latte.get(), espresso.get());
51 log.info("Update INIT to PAID: {}", orderService.updateState(order, OrderState.PAID));
52 //Update INIT to PAID: true
53 log.info("Update PAID to INIT: {}", orderService.updateState(order, OrderState.INIT));
54 //Update PAID to INIT: false 无法从 PAID 转到 INIT
55 }
56
57 //orderService
58 List<CoffeeOrder> list = orderService.findByCustomerOrderById("Li Lei");
59 log.info("findByCustomerOrderById: {}", getJoinedOrderId(list));
60 //findByCustomerOrderById: 1
61
62
63 }
64 //过滤器list中的id,并且添加分隔符循环遍历
65 private String getJoinedOrderId(List<CoffeeOrder> list) {
66 return list.stream().map(o -> o.getId().toString())
67 .collect(Collectors.joining(","));
68 }
69}