目录

Life in Flow

知不知,尚矣;不知知,病矣。
不知不知,殆矣。

X

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

项目目标
bucks

项目中的对象实

引入依赖

 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}

作者:Soulboy