这一节跟上一节用户微服务的注册方式是类似的,这一节主要会有个jpa一对多单向关联保存和查询的知识点,其他的操作也都很相似,相当于在复习一遍了
订单微服务主要是用户订单数据的保存以及订单明细的保存,包括订单金额,订单状态等等
目录
1、创建订单数据库和表结构
这里需要注意的是,创建表名最好加前缀,由于order是order by的关键字,也是mysql的保留关键字,如果直接用order命名查询不是很方便,还需要用单引号包裹,表名和表字段最好都用前缀来区分会好一点。
create schema cloud_order collate utf8mb4_0900_ai_ci; create table c_order ( id char(32) not null, order_no varchar(50) not null comment '订单号', order_status char default '0' not null comment '0 创建 1 完成 2 删除', finish_date datetime null comment '完成日期', delete_date datetime null comment '删除日期', create_date datetime not null, create_by char(32) not null, update_date datetime not null, update_by char(32) not null, amount double not null, constraint order_id_uindex unique (id) ) comment '订单'; alter table c_order add primary key (id); create table c_order_detail ( id char(32) not null, order_id char(32) null comment '订单id', good_id char(32) not null comment '商品ID', good_name varchar(50) not null comment '商品名称', price double not null comment '商品价格', quantity int not null comment '商品数量', amount double null comment '总金额', create_date datetime not null, create_by char(32) not null, update_date datetime not null, update_by char(32) null, constraint order_detail_id_uindex unique (id), constraint c_order_detail_c_order_id_fk foreign key (order_id) references c_order (id) on update cascade on delete cascade ) comment '订单明细'; alter table c_order_detail add primary key (id);
2、新建cloud-order订单微服务子模块
新建方法同上节类似,这里不再赘述
3、pom.xml文件中添加需要依赖的jar包
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>spring-cloud-study</artifactId> <groupId>com.apgblogs</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.apgblogs</groupId> <artifactId>cloud-order</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- 数据库连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.5</version> </dependency> <!--服务客户端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> </project>
4、创建配置文件
application.yml
这个文件需要修改的是应用名,改为cloud-order,这个名字将显示在服务注册中心页面中
log4j.properties
这个文件也是修改下日志文件名,这里日志文件名并没有指定一个好的路径,这个在后面会专门集成日志服务处理,所以不用担心
5、创建controller,entity,repository,service等包和相应的类
包的创建方式和上一节是一样的,这里就不说了
下图是包结构
COrderEntity
订单实体类,采用一对多的方式关联订单明细
这里需要注意的是采用的单向一对多关联,所以在订单明细表中是有个外键order_id进行关联的,这个字段在数据库中不要设置成不能为空,不然jpa保存时会报错提示order_id不能为空。
@OneToMany(targetEntity = COrderDetailEntity.class,cascade = CascadeType.ALL)
一对多关联,targetEntity表示子类也就是多数据的那一方,可以不用写,默认就是注解下面的订单明细类,后面 CascadeType 级联操作,这里选择所有操作
@JoinColumn(name="order_id")
关联的外键字段,也就是订单明细表中order_id,这个字段不能设置为不为空,不然无法正常保存,jpa应该是先保存两个表的数据,然后根据关联关系在单独修改子明细的order_id列
package com.apgblogs.cloudorder.entity; import org.hibernate.annotations.GenericGenerator; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import javax.persistence.*; import java.sql.Timestamp; import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; /** * @author xiaomianyang * @description * @date 2019-07-03 11:26 */ @Entity @Table(name = "c_order", schema = "cloud_order", catalog = "") @EntityListeners(AuditingEntityListener.class) public class COrderEntity { private String id; private String orderNo; private String orderStatus="0"; private Timestamp finishDate; private Timestamp deleteDate; private Timestamp createDate; private String createBy="sys"; private Timestamp updateDate; private String updateBy="sys"; private double amount; private List<COrderDetailEntity> cOrderDetailEntityList; @Id @Column(name = "id", nullable = false, length = 32) @GenericGenerator(name = "jpa-uuid", strategy = "uuid") @GeneratedValue(generator = "jpa-uuid") public String getId() { return id; } public void setId(String id) { this.id = id; } @Basic @Column(name = "order_no", nullable = false, length = 50) public String getOrderNo() { return orderNo; } public void setOrderNo(String orderNo) { this.orderNo = orderNo; } @Basic @Column(name = "order_status", nullable = false, length = 1) public String getOrderStatus() { return orderStatus; } public void setOrderStatus(String orderStatus) { this.orderStatus = orderStatus; } @Basic @Column(name = "finish_date", nullable = false) public Timestamp getFinishDate() { return finishDate; } public void setFinishDate(Timestamp finishDate) { this.finishDate = finishDate; } @Basic @Column(name = "delete_date", nullable = true) public Timestamp getDeleteDate() { return deleteDate; } public void setDeleteDate(Timestamp deleteDate) { this.deleteDate = deleteDate; } @Basic @Column(name = "create_date", nullable = false) @CreatedDate public Timestamp getCreateDate() { return createDate; } public void setCreateDate(Timestamp createDate) { this.createDate = createDate; } @Basic @Column(name = "create_by", nullable = false, length = 32) public String getCreateBy() { return createBy; } public void setCreateBy(String createBy) { this.createBy = createBy; } @Basic @Column(name = "update_date", nullable = false) @LastModifiedDate public Timestamp getUpdateDate() { return updateDate; } public void setUpdateDate(Timestamp updateDate) { this.updateDate = updateDate; } @Basic @Column(name = "update_by", nullable = false, length = 32) public String getUpdateBy() { return updateBy; } public void setUpdateBy(String updateBy) { this.updateBy = updateBy; } @Basic @Column(name = "amount", nullable = false, precision = 0) public double getAmount() { return amount; } public void setAmount(double amount) { this.amount = amount; } @OneToMany(targetEntity = COrderDetailEntity.class,cascade = CascadeType.ALL) @JoinColumn(name="order_id") public List<COrderDetailEntity> getcOrderDetailEntityList() { return cOrderDetailEntityList; } public void setcOrderDetailEntityList(List<COrderDetailEntity> cOrderDetailEntityList) { this.cOrderDetailEntityList = cOrderDetailEntityList; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; COrderEntity that = (COrderEntity) o; return Double.compare(that.amount, amount) == 0 && Objects.equals(id, that.id) && Objects.equals(orderNo, that.orderNo) && Objects.equals(orderStatus, that.orderStatus) && Objects.equals(finishDate, that.finishDate) && Objects.equals(deleteDate, that.deleteDate) && Objects.equals(createDate, that.createDate) && Objects.equals(createBy, that.createBy) && Objects.equals(updateDate, that.updateDate) && Objects.equals(updateBy, that.updateBy); } @Override public int hashCode() { return Objects.hash(id, orderNo, orderStatus, finishDate, deleteDate, createDate, createBy, updateDate, updateBy, amount); } }
COrderDetailEntity
订单明细类
package com.apgblogs.cloudorder.entity; import org.hibernate.annotations.GenericGenerator; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import javax.persistence.*; import java.sql.Timestamp; import java.util.Objects; /** * @author xiaomianyang * @description * @date 2019-07-03 11:26 */ @Entity @Table(name = "c_order_detail", schema = "cloud_order", catalog = "") @EntityListeners(AuditingEntityListener.class) public class COrderDetailEntity { private String id; private String orderId; private String goodId; private String goodName; private double price; private int quantity; private Double amount; private Timestamp createDate; private String createBy="sys"; private Timestamp updateDate; private String updateBy="sys"; @Id @Column(name = "id", nullable = false, length = 32) @GenericGenerator(name = "jpa-uuid", strategy = "uuid") @GeneratedValue(generator = "jpa-uuid") public String getId() { return id; } public void setId(String id) { this.id = id; } @Basic @Column(name = "order_id", length = 32) public String getOrderId() { return orderId; } public void setOrderId(String orderId) { this.orderId = orderId; } @Basic @Column(name = "good_id", nullable = false, length = 32) public String getGoodId() { return goodId; } public void setGoodId(String goodId) { this.goodId = goodId; } @Basic @Column(name = "good_name", nullable = false, length = 50) public String getGoodName() { return goodName; } public void setGoodName(String goodName) { this.goodName = goodName; } @Basic @Column(name = "price", nullable = false, precision = 0) public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } @Basic @Column(name = "quantity", nullable = false) public int getQuantity() { return quantity; } public void setQuantity(int quantity) { this.quantity = quantity; } @Basic @Column(name = "amount", nullable = true, precision = 0) public Double getAmount() { return amount; } public void setAmount(Double amount) { this.amount = amount; } @Basic @Column(name = "create_date", nullable = false) @CreatedDate public Timestamp getCreateDate() { return createDate; } public void setCreateDate(Timestamp createDate) { this.createDate = createDate; } @Basic @Column(name = "create_by", nullable = false, length = 32) public String getCreateBy() { return createBy; } public void setCreateBy(String createBy) { this.createBy = createBy; } @Basic @Column(name = "update_date", nullable = false) @LastModifiedDate public Timestamp getUpdateDate() { return updateDate; } public void setUpdateDate(Timestamp updateDate) { this.updateDate = updateDate; } @Basic @Column(name = "update_by", nullable = true, length = 32) public String getUpdateBy() { return updateBy; } public void setUpdateBy(String updateBy) { this.updateBy = updateBy; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; COrderDetailEntity that = (COrderDetailEntity) o; return Double.compare(that.price, price) == 0 && quantity == that.quantity && Objects.equals(id, that.id) && Objects.equals(orderId, that.orderId) && Objects.equals(goodId, that.goodId) && Objects.equals(goodName, that.goodName) && Objects.equals(amount, that.amount) && Objects.equals(createDate, that.createDate) && Objects.equals(createBy, that.createBy) && Objects.equals(updateDate, that.updateDate) && Objects.equals(updateBy, that.updateBy); } @Override public int hashCode() { return Objects.hash(id, orderId, goodId, goodName, price, quantity, amount, createDate, createBy, updateDate, updateBy); } }
OrderRepository,OrderDetailRepository
这两个类都很简单和上节差不多,这里也就不说了
OrderServiceImpl
订单业务类,创建两个保存订单和查询单个订单的逻辑方法
package com.apgblogs.cloudorder.service; import com.apgblogs.cloudorder.entity.COrderEntity; import com.apgblogs.cloudorder.repository.OrderRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * @author xiaomianyang * @description * @date 2019-07-03 11:38 */ @Service public class OrderServiceImpl { @Autowired private OrderRepository orderRepository; /** * @description 通过订单Id获取订单 * @author xiaomianyang * @date 2019-07-03 12:32 * @param [id] * @return com.apgblogs.cloudorder.entity.COrderEntity */ public COrderEntity getOrder(String id){ if(!orderRepository.existsById(id)){ return null; } return orderRepository.findById(id).get(); } /** * @description 保存订单 * @author xiaomianyang * @date 2019-07-03 12:33 * @param [orderEntity] * @return com.apgblogs.cloudorder.entity.COrderEntity */ public COrderEntity saveOrder(COrderEntity COrderEntity){ COrderEntity.setOrderNo(String.valueOf(System.currentTimeMillis())); return orderRepository.save(COrderEntity); } }
OrderDetailServiceImpl
订单明细实现类,这个是空的,暂时没有用到
package com.apgblogs.cloudorder.service; import org.springframework.stereotype.Service; /** * @author xiaomianyang * @description * @date 2019-07-03 11:38 */ @Service public class OrderDetailServiceImpl { }
6、创建订单启动类
OrderApplication
订单启动类
package com.apgblogs.cloudorder; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; /** * @author xiaomianyang * @description * @date 2019-07-03 11:18 */ @SpringBootApplication @EnableDiscoveryClient @EnableJpaAuditing public class OrderApplication { public static void main(String[] args) { SpringApplication.run(OrderApplication.class,args); } }
7、启动项目
启动服务注册中心和用户以及订单微服务
查看服务中心是否已经出现了这两个微服务
出现那就说明注册成功了
8、访问并测试订单微服务关联保存和关联查询
用postman访问订单保存接口
关联保存成功,可以到数据库查看是否写入成功了
测试关联查询,用刚刚保存成功生成Id查询
可以看到查询成功了,那说明我们的接口写的没问题
9、文章源码地址
至此订单微服务就已经构建好了,下一节继续创建商品微服务