聚合的实现三

DDD 学习笔记 | 极客时间 | 手把手教你落地 DDD

🏆 原文:17|聚合的实现(下):怎样用事务保护聚合?

从数据库中查询出聚合根、其下所有关联对象

 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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package chapter17.unjuanable.adapter.driven.persistence.orgmng;
// imports...

@Repository
public class EmpRepositoryJdbc implements EmpRepository {
   //声明 JdbcTemplate 和各个 SimpleJdbcInsert ...
   // 构造器、其他方法 ...

    @Override
    public Optional<Emp> findById(Long tenantId, Long id) {
        Optional<RebuiltEmp> empMaybe = retrieveEmp(tenantId, id);
        if (empMaybe.isPresent()) {
            RebuiltEmp emp = empMaybe.get();
            retrieveSkills(emp);
            retrieveExperiences(emp);
            retrievePosts(emp);
            return Optional.of(emp);
        } else {
            return Optional.empty();
        }
    }

    private Optional<RebuiltEmp> retrieveEmp(Long tenantId, Long id) {
        String sql = " select org_id, num, id_num, name "
                + " , gender_code, dob, status_code "
                + " from emp "
                + " where id = ? and tenant_id = ? ";

        RebuiltEmp emp = jdbc.queryForObject(sql,
                (rs, rowNum) -> {
                    RebuiltEmp newEmp = new RebuiltEmp(tenantId
                            , id
                            , rs.getTimestamp("create_at").toLocalDateTime()
                            , rs.getLong("created_by"));

                    newEmp.resetOrgId(rs.getLong("org_id"))
                          .resetNum(rs.getString("num"))
                          .resetIdNum(rs.getString("id_num"))
                          .resetName(rs.getString("name"))
                          .resetGender(Gender.ofCode(
                                    rs.getString("gender_code")))
                          .resetDob(rs.getDate("dob").toLocalDate())
                          .resetStatus(EmpStatus.ofCode(
                                      rs.getString("status_code")));
                    return newEmp;
                },
                id, tenantId);
                
        return Optional.ofNullable(emp);
    }

    private void retrieveSkills(RebuiltEmp emp) {
        String sql = " select id, tenant_id, skill_type_id, level, duration "
                + " from skill "
                + " where tenant_id = ? and emp_id = ? ";

        List<Map<String, Object>> skills = jdbc.queryForList(
                                sql, emp.getTenantId(), emp.getId());

        skills.forEach(skill -> emp.reAddSkill(
                    (Long) skill.get("id")
                    , (Long) skill.get("skill_type_id")
                    , SkillLevel.ofCode((String) skill.get("level_code"))
                    , (Integer) skill.get("duration")
                    , (Long) skill.get("created_by")
        });

    }

    private void retrieveExperiences(RebuiltEmp emp) {
        //与retrieveSkill 类似 ...
    }

    private void retrievePosts(RebuiltEmp emp) {
        //与retrieveSkill 类似 ...
    }
}

save() 通过 changingStatus 判断是新增还是更新

16 课文末代码

 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
package chapter16.unjuanable.common.framework.domain;
import static chapter16.unjuanable.common.framework.domain.ChangingStatus.*;

public abstract class AuditableEntity {
    protected ChangingStatus changingStatus = NEW;
    // 其他属性、构造器 ...

    public ChangingStatus getChangingStatus() {
        return changingStatus;
    }

    public void toUpdate() {
        this.changingStatus = UPDATED;
    }

    public void toDelete() {
        this.changingStatus = DELETED;
    }

    public void toUnChang() {
        this.changingStatus = UNCHANGED;
    }
    
    // 其他方法 ...
}

save()

  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
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package chapter17.unjuanable.adapter.driven.persistence.orgmng;
// imports ...

@Repository
public class EmpRepositoryJdbc implements EmpRepository {

    final JdbcTemplate jdbc;
    final SimpleJdbcInsert empInsert;
    final SimpleJdbcInsert skillInsert;
    final SimpleJdbcInsert WorkExperienceInsert;
    final SimpleJdbcInsert empPostInsert;

    @Autowired
    public EmpRepositoryJdbc(JdbcTemplate jdbc) {
        this.jdbc = jdbc;
        this.empInsert = new SimpleJdbcInsert(jdbc)
                .withTableName("emp")
                .usingGeneratedKeyColumns("id");
        //初始化其他 SimpleJdbcInsert ...
    }

    @Override
    public void save(Emp emp) {
        saveEmp(emp);
        emp.getSkills().forEach(s -> saveSkill(emp, s));
        emp.getExperiences().forEach(e -> saveWorkExperience(emp, e));
        emp.getEmpPosts().forEach(p -> saveEmpPost(emp, p));
    }

    private void saveEmp(Emp emp) {
        switch (emp.getChangingStatus()) {
            case NEW:
                insertEmpRecord(emp);
                break;
            case UPDATED:
                updateEmpRecord(emp);
                break;
        }
    }

    private void insertEmpRecord(Emp emp) {
        Map<String, Object> parms = Map.of(
                "tenant_id", emp.getTenantId()
                , "org_id", emp.getOrgId()
                , "num", emp.getNum()
                , "id_num", emp.getIdNum()
                , "name", emp.getName()
                , "gender", emp.getGender().code()
                , "dob", emp.getDob()
                , "status", emp.getStatus().code()
                , "created_at", emp.getCreatedAt()
                , "created_by", emp.getCreatedBy()
        );

        Number createdId = empInsert.executeAndReturnKey(parms);

        forceSet(emp, "id", createdId.longValue());
    }

    private void updateEmpRecord(Emp emp) {
        String sql = "update emp " +
                " set org_id = ?" +
                ", num = ?" +
                ", id_num =? " +
                ", name = ?" +
                ", gender =?" +
                ", dob = ?" +
                ", status =?" +
                ", last_updated_at =?" +
                ", last_updated_by =? " +
                " where tenant_id = ? and id = ? ";
        this.jdbc.update(sql
                , emp.getOrgId()
                , emp.getNum()
                , emp.getIdNum()
                , emp.getName()
                , emp.getGender().code()
                , emp.getDob()
                , emp.getStatus()
                , emp.getLastUpdatedAt()
                , emp.getLastUpdatedBy()
                , emp.getTenantId()
                , emp.getId());
    }

    private void saveSkill(Emp emp, Skill skill) {
        switch (skill.getChangingStatus()) {
            case NEW:
                insertSkillRecord(skill, emp.getId());
                break;
            case UPDATED:
                updateSkillRecord(skill);
                break;
            case DELETED:
                deleteSkillRecord(skill);
                break;

        }
    }

    private void insertSkillRecord(Skill skill, Long empId) {
        Map<String, Object> parms = Map.of(
            "emp_id", empId,
            "tenant_id", skill.getTenantId(),
            "skill_type_id", skill.getSkillTypeId(),
            "level_code", skill.getLevel().code(),
            "duration", skill.getDuration(),
            "created_at", skill.getCreatedAt(),
            "created_by", skill.getCreatedBy()
            );

        Number createdId = skillInsert.executeAndReturnKey(parms);

        forceSet(skill, "id", createdId.longValue());
    }

    private void updateSkillRecord(Skill skill) {
        String sql = "update skill " 
                    + " set level_code = ?" 
                    + ", duration = ?" 
                    + ", last_updated_at = ?" 
                    + ", last_updated_by = ?" 
                    + " where tenant_id = ? and id = ? ";
        this.jdbc.update(sql
                , skill.getSkillTypeId()
                , skill.getDuration()
                , skill.getLastUpdatedAt()
                , skill.getLastUpdatedBy()
                , skill.getTenantId()
                , skill.getId());
    }


    private void deleteSkillRecord(Skill skill) {
        this.jdbc.update("delete from skll where tenant_id = ? "
                       + " and id = ?"
                , skill.getTenantId()
                , skill.getId());
    }

    private void saveWorkExperience(Emp emp, WorkExperience e) {
        // 与 saveSkill( ) 类似...
    }

    private void saveEmpPostRecord(Emp emp, EmpPost p) {
        // 与 saveSkill( ) 类似...
    }

}
comments powered by Disqus