springCloud微服务之订单微服务注册

这一节跟上一节用户微服务的注册方式是类似的,这一节主要会有个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

这个文件也是修改下日志文件名,这里日志文件名并没有指定一个好的路径,这个在后面会专门集成日志服务处理,所以不用担心
log4j配置文件

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访问订单保存接口

关联保存成功,可以到数据库查看是否写入成功了
postman post

测试关联查询,用刚刚保存成功生成Id查询

可以看到查询成功了,那说明我们的接口写的没问题
postman get

9、文章源码地址

码云:https://gitee.com/apgblogs/springCloudStudy/tree/order/

至此订单微服务就已经构建好了,下一节继续创建商品微服务

发表评论