SpringBoot+JPA實現DDD(六)


潤色一下

記錄sql語句及sql的執行時間

<properties>
    <p6spy.version>3.9.0</p6spy.version>
</properties>
<dependency>
    <groupId>p6spy</groupId>
    <artifactId>p6spy</artifactId>
    <version>${p6spy.version}</version>
</dependency>

src/main/resources下新建spy.properties配置文件:

driverlist=com.mysql.cj.jdbc.Driver
logfile=spy.log
dateformat=yyyy-MM-dd HH:mm:ss.SS
logMessageFormat=com.p6spy.engine.spy.appender.CustomLineFormat
customLogMessageFormat=- %(currentTime) | took %(executionTime)ms | connection %(connectionId) \nEXPLAIN %(sql);\n
filter=true
exclude=select 1 from dual

application.properties修改成:

#spring.datasource.url=jdbc:mysql://localhost:3306/product_center?\ useSSL=false&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8
spring.datasource.url=jdbc:p6spy:mysql://localhost:3306/product_center?\ useSSL=false&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=<your username>
spring.datasource.password=<your password>
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.driver-class-name=com.p6spy.engine.spy.P6SpyDriver

增加全局異常處理

@ControllerAdvice
@ResponseBody
public class GlobalDefaultExceptionHandler {
    private static final String UNKNOWN_ERROR_CODE = "unknown-error";
    private static final String SYSTEM_ERROR_INFO = "系統異常,請聯系管理員";
    private static final String ILLEGAL_PARAM_CODE = "illegal-param";

    @ExceptionHandler(value = IllegalArgumentException.class)
    public ApiResult illegalParamExceptionHandler(IllegalArgumentException e) throws Exception {
        // log todo
        return ApiResult.error(ILLEGAL_PARAM_CODE, e.getMessage());
    }

    @ExceptionHandler(value = BusinessException.class)
    public ApiResult businessExceptionHandler(BusinessException e) throws Exception {
        // log todo
        return ApiResult.error(e.getCode(), e.getMessage());
    }

    @ExceptionHandler(value = Exception.class)
    public ApiResult defaultErrorHandler(Exception e) throws Exception {
        // log todo
        e.printStackTrace();
        return ApiResult.error(UNKNOWN_ERROR_CODE, SYSTEM_ERROR_INFO);
    }
}

數據庫添加自定義的審計字段

domain.common.model:

@MappedSuperclass
@Data
public abstract class AuditEntity implements Serializable {
    @Column(name = "is_delete", columnDefinition = "TINYINT(1) DEFAULT 0")
    protected Boolean isDelete;
    @Column(name = "created_by", length = 11, nullable = false)
    protected Integer createdBy;
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "created_at", columnDefinition = "DATETIME NULL DEFAULT CURRENT_TIMESTAMP")
    protected Date createdAt;
    @Column(name = "updated_by", length = 11, nullable = false)
    protected Integer updatedBy;
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "updated_at", columnDefinition = "DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
    protected Date updatedAt;

    @PrePersist
    protected void onCreate() {
        updatedAt = createdAt = new Date();
        isDelete = false;
    }

    @PreUpdate
    protected void onUpdate() {
        updatedAt = new Date();
    }
}
public class Product extends AuditEntity implements Serializable {
      ...
}

確定需求->構建模型->實現模型->調整模型->實現模型...,走完這個過程,相信你對DDD的玩法已經有了一定的了解,而且我相信你大概能領略到DDD代碼的優美之處。好的代碼應該是高內聚低耦合的,DDD的代碼就是要讓高內聚低耦合落地。

高內聚體現在業務代碼都集中在領域對象里了(聚合根,實體,值對象,域服務)。業務規則在代碼里都有非常清楚的對應關系。代碼真正體現了面向對象的思想。
低耦合體現在聚合根不直接引用其它聚合根。 低耦合還有一個很關鍵的點是領域事件。 這個跟DDD事件驅動的架構風格分不開。

說起DDD的架構風格,最常用的就是CQRS(讀寫分離)和事件驅動。
事件驅動又分 event storming和event sourcing(個人理解,不對請指正),event sourcing看起來比較極端,似乎應用場景針對性太強,也就是說比較少見。

如果你的業務很復雜,事件比較多,可以使用event storming。商品中心相對比較簡單,用讀寫分離就差不多了。本人水平有限,本系列文章旨在拋磚引玉,希望大家能留言討論。

demo下載地址: productcenter6.zip


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM