• Miss 置顶
    2020-01-02
    偶是编辑,这篇加餐比较长~作者会抽周末的时间把音频讲解为大家补上。感谢等待!
    
     4
  • CN....
    2020-01-06
    老师好,浏览代码有两点疑惑
    1,我们通常会认为加了事务注解就尽量避免除数据库外的其他调用,但是代码中在领域服务中的方法中发送mq,而且是在有事务注解的方法中,这里是基于什么考虑
    2,消费mq的逻辑应该属于那一层
    谢谢

    作者回复: 1、这个主要是考虑业务数据,事件数据持久化和发送消息队列同时能够成功,避免出现数据不一致的情况。当然也可以只在业务数据和事件数据持久化增加事务,如果消息队列发送不成功,还可以从事件表中获取数据再次发送。
    2、消息订阅方一般在应用层监听和接受事件数据。

     1
     3
  • 阿玛铭
    2020-01-02
    欧老师的回马枪猝不及防

    作者回复: 😄,舍不得跟大家告别。

    
     2
  • zj
    2020-01-07
    有个问题我还是想问问欧老师,在工作中我遇到这样的一个场景,KA商品推广实体,很多场景都可以用领域服务实现,但是有个场景是查询KA商品推广列表,列表上还要有每个KA商品的推广效果数据(点击量,曝光量,交易额,商详页UV),这个推广效果数据放在领域服务中去查询总感觉不合适,老师有什么好的建议

    作者回复: 基于聚合根的查询不太适合进行复杂的查询。
    对于复杂的查询你可以通过应用服务,在仓储实现中直接用SQL查询也是可以的。

     1
     1
  • 切糕
    2020-01-06
    老师,有个问题请教下:
    应用层负责领域服务的组织和编排,我看示例代码的事务控制在领域服务层,多个领域服务如何确保事务的一致性。
    示例:
    public void createLeaveInfo(Leave leave){
            //get approval leader max level by rule
            int leaderMaxLevel = approvalRuleDomainService.getLeaderMaxLevel(leave.getApplicant().getPersonType(), leave.getType().toString(), leave.getDuration());
            //find next approver
            Person approver = personDomainService.findFirstApprover(leave.getApplicant().getPersonId(), leaderMaxLevel);
            leaveDomainService.createLeave(leave, leaderMaxLevel, Approver.fromPerson(approver));
        }
    展开

    作者回复: 这个领域服务的事务控制主要是保证写业务表和事件表以及发布到消息队列,这三步能够保持数据一致。聚合之间或微服务之间可以在应用服务采用事务机制。

    
     1
  • 陈四丰
    2020-01-05
    感谢欧老师的加餐,受益匪浅。

    实际操作中,我产生了一个疑问。是不是每个微服务都要有自己单独的数据库?比如本节案例:“请假”和“考勤”是两个微服务,那么就应该有两个独立的数据库去对应。(database: leave和checking)?

    多谢指教!!!
    展开

    作者回复: 如果按照领域建模的方式来设计微服务的话,我们可以很容易的对对象进行聚合以及实体归类,所以也很容易的实现数据之间的解耦,没有特殊考虑的话,建议一个微服务一个数据库。

     2
     1
  • 盲僧
    2020-01-03
    太棒了,这个案例太精彩

    作者回复: 😄

    
     1
  • zj
    2020-01-02
    这篇文章刚下班,还没来得及看,等会下班到家再一饱眼福。
    
     1
  • 嘉嘉☕
    2020-02-10
    老师, 请问下,
    对于每一层, 也是需要面向接口编程的吧 ?

    作者回复: 是的,逐层封装。

    
    
  • 微光
    2020-02-05
    棒,值得学习->实践->再学习
    
    
  • 微光
    2020-02-05
    有个疑问,如果是微服务之间调用,为了减少重复编码和统一性,是不是应该把DTO和FeginClient打成jar包发布到仓库,让调用方引用啊?
    
    
  • 静静聆听
    2020-01-28
    老师,Leave是个实体类,怎么能用@Autowired注入Bean的
    
    
  • 若水
    2020-01-22
    老师您好,这样 设计一个组合属性字段,以 Json 串的方式存储在 PO,会存在如下两个问题。①、数据修改,对应记录值不会修改。 ②、这样设计一个大字段存储,引发数据库查询的效率问题。 这两个问题您是怎么看待呢

    作者回复: 一般对于有查询和统计要求的值对象,不建议做成json串存储。其实如果这部分数据在处理后,加载到数据平台,也不影响查询使用。这类值对象的修改需要对应的前端操作,所以其它地方修改并不会修改值对象的值,这也是一种正常的需求,它记录业务发生那一刻的数据快照,不会因为外部数据修改而导致无法记录业务产生那一刻的真实数据。

    
    
  • focus
    2020-01-16
    如果是内部事件,与外部服务无关,还需要定义listener,publish发布的是内部事件;这样可以用事件总线,借助guava中的EventBus来实现是吗

    作者回复: 是的。这种主要是处理微服务内部不同聚合之间的领域事件。主要是因为在处理新增和修改数据的时候,一个操作是对一个聚合整理的数据进行操作的。这样可以避免聚合之间的数据不一致的情况。

    
    
  • 切糕
    2020-01-15
    老师,您好!我们这边有个比较怪异的场景,想请教下老师:
    背景介绍:我们主要是做分期账单的业务,整体分为两部分,一部分是订单、一部分是账单。订单中包含渠道、收款人、付款人信息,而这些信息因渠道侧不同字段会有很大差异。后面的账单基本是根据订单生成的,初始账单的“渠道、收款人、付款人”信息是一致的,但后续账单可能会变更收款人信息。
    目前状况:我们把订单、账单分成两个聚合,这个时候“渠道、收款人、付款人”通过抽象ID维护在订单聚合,但是账单这边也需要“渠道、收款人、付款人”实体,这个时候复用好像又不太对,因为这个实体在订单聚合内,账单聚合操作依赖订单聚合中的实体,感觉很怪。
    个人见解:
    1.订单的生命周期主要是为了生成账单,一但账单生成订单的生命周期结束,所以订单中的“渠道、收款人、付款人”以值对象JSON存储下来,而不同渠道的字段不一样,在和不同渠道业务交互的规则中去处理。
    2.账单聚合中维护“渠道、收款人、付款人”实体对象,因存在变更收款人操作等操作,所以收款人比较适合做实体,而渠道和付款人信息应该是和收款人属于同一级别,所以都认为是实体。

    对这一块还是比较疑惑,希望老师能给些建议。


    展开

    作者回复: 我建议你再设计两个聚合:渠道和人员(暂且叫人员吧,你可以根据你的业务场景来命名)聚合。人员聚合主要提供人员的新增和修改,而这个人员数据可以被订单或账单聚合以值对象的方式来引用,在值对象引用时你可以根据业务类型将人员设置为收款人或者付款人。这样人员信息可以在人员聚合集中维护,它可以同时被多个其它的聚合以值对象的形式整体引用。

    
    
  • Geek_74f563
    2020-01-13
    老师可以把数据库表结构的脚本上传上去吗? 哈哈

    作者回复: JPA可以自动创建的。

    
    
  • uangguan
    2020-01-13
    老师,LeaveRepositoryInterface接口的save方法,为什么传入的是LeavePO而不是Leave?在LeaveDomainService层里直接调用LeaveRepositoryInterface.save(Leave leave)保存领域实体不是更合理吗?这样在LeaveDomainService层就不需要知道LeavePO的存在了。

    作者回复: 你这个想法挺好的。基础层的对象是可以为所有层提供服务的,把PO拿出来主要还是希望将DO和PO的转换统一放在工厂服务中。如果用leave的DO对象做完save的参数,在save仓储实现内,一样还是需要转换的。

    
    
  • 宋承展
    2020-01-11
    老师好,请教一下在查询列表这种交易中,一般我们会返回翻页通信区给前端,这个翻页通信区,一般放在哪一层的。。。我看在领域服务层里,都是只是返回了实体的list,对于这种翻页通信区,没说明,能否指导一下?谢谢

    作者回复: 复杂的查询可以不走领域层,你可以定义一个查询应用服务,按照传统三层架构分页查询方式就可以了。

    
    
  • SpEcIAL_ID
    2020-01-10
    赞赞赞,很多共鸣,👍🏻👍🏻👍🏻👍🏻

    作者回复: 过来人😀。

    
    
  • Geek_aa8017
    2020-01-09
    老师,你之前的章节说接口层到应用层参数的转换是dto转do的,但现在看代码怎么是dto直接转实体传给应用层的

    作者回复: 实体是DO的一种呀。

    
    
我们在线,来聊聊吧