3.1.3 定义 schema 并预加载数据
除了 Ingredient 表之外,还需要一些保存订单和设计信息的表。图 3.1 说明了需要的表以及这些表之间的关系。
图 3.1 Taco Cloud Schema
图 3.1中的表有以下用途:
- Taco_Order - 保存着重要的订单细节
- Taco - 保存着关于 taco 设计的重要信息
- Ingredient_Ref - 包含 Taco 表中每一行的一个或多行数据,将 Taco 映射到该 Taco 的 Ingredient
- Ingredient - 保存着原料信息
在我们的应用程序中,Taco 不能存在于 Taco_Order 的上下文之外。因此,Taco_Order 和 Taco 聚合关系,其中 Taco_Order 是聚合根。另一方面,Ingredient 对象是其自身聚合的唯一成员,并且 Taco 通过 Ingredient_Ref 引用。
注意:聚合和聚合根是领域驱动设计的核心概念,是一种设计方法,它提倡软件代码应与业务域匹配。虽然在 Taco Cloud 领域对象中,我们只简单应用领域驱动设计(DDD),但 DDD 不只是聚合和聚合根。更多信息请阅读 Eric Evans 的开创性作品《领域驱动设计: 软件核心复杂性应对之道》。
下一个程序清单显示了创建表的 SQL 语句。
程序清单 3.9 定义 Taco Cloud 模式
create table if not exists Taco_Order (
id identity,
delivery_Name varchar(50) not null,
delivery_Street varchar(50) not null,
delivery_City varchar(50) not null,
delivery_State varchar(2) not null,
delivery_Zip varchar(10) not null,
cc_number varchar(16) not null,
cc_expiration varchar(5) not null,
cc_cvv varchar(3) not null,
placed_at timestamp not null
);
create table if not exists Taco (
id identity,
name varchar(50) not null,
taco_order bigint not null,
taco_order_key bigint not null,
created_at timestamp not null
);
create table if not exists Ingredient_Ref (
ingredient varchar(4) not null,
taco bigint not null,
taco_key bigint not null
);
create table if not exists Ingredient (
id varchar(4) not null,
name varchar(25) not null,
type varchar(10) not null
);
alter table Taco
add foreign key (taco_order) references Taco_Order(id);
alter table Ingredient_Ref
add foreign key (ingredient) references Ingredient(id);
最大的问题是把这个 Schema 定义放在哪里。事实上,Spring Boot 已经有答案。
如果有一个名为 schema.sql 的文件。在应用程序的类路径根目录下执行 sql,然后在应用程序启动时对数据库执行该文件中的 SQL。因此,应该将程序清单 3.8 的内容写入一个名为 schema.sql 的文件中,然后放在项目的 src/main/resources 文件夹下。
还需要用一些 Ingredient 数据来预加载数据库。幸运的是,Spring Boot 还将执行一个名为 data.sql 的文件,这个文件位于根路径下。因此,可以使用 src/main/resources/data.sql 中的下面程序清单中的 insert 语句来加载包含 Ingredient 数据的数据库。
程序清单 3.10 预加载数据库
delete from Ingredient_Ref;
delete from Taco;
delete from Taco_Order;
delete from Ingredient;
insert into Ingredient (id, name, type)
values ('FLTO', 'Flour Tortilla', 'WRAP');
insert into Ingredient (id, name, type)
values ('COTO', 'Corn Tortilla', 'WRAP');
insert into Ingredient (id, name, type)
values ('GRBF', 'Ground Beef', 'PROTEIN');
insert into Ingredient (id, name, type)
values ('CARN', 'Carnitas', 'PROTEIN');
insert into Ingredient (id, name, type)
values ('TMTO', 'Diced Tomatoes', 'VEGGIES');
insert into Ingredient (id, name, type)
values ('LETC', 'Lettuce', 'VEGGIES');
insert into Ingredient (id, name, type)
values ('CHED', 'Cheddar', 'CHEESE');
insert into Ingredient (id, name, type)
values ('JACK', 'Monterrey Jack', 'CHEESE');
insert into Ingredient (id, name, type)
values ('SLSA', 'Salsa', 'SAUCE');
insert into Ingredient (id, name, type)
values ('SRCR', 'Sour Cream', 'SAUCE');
即使只开发了配料数据的 repository,也可以启动 Taco Cloud 应用程序并访问设计页面,查看 JdbcIngredientRepository 的运行情况。大胆的试试吧。后续可以继续编写用于持久化 Taco、TacoOrder 的 repository。