随笔 - 15, 文章 - 0, 评论 - 15, 阅读 - 38998

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

SpringBoot+JPA实现DDD(六)

Posted on   ahau10  阅读(1782)  评论(0编辑  收藏  举报

润色一下

记录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

编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
点击右上角即可分享
微信分享提示