java 如果属性设置为true,服务将只记录将要执行的CRUD操作,如何分隔业务逻辑

bbmckpt7  于 2023-02-28  发布在  Java
关注(0)|答案(2)|浏览(101)

我有一个需求,我需要创建一个服务,其中包含一些业务逻辑,这些业务逻辑将确定哪些资源应该删除,哪些应该在数据库中创建。资源的内容从JSON中读取,JSON是在项目根中静态定义的。下面是一个示例:

{
  "subjects" : [
    {
      "name" : "New-subject",
      "description" : "Math subject",
      "price" : "100"
    },
    {
      "name" : "New-subject-2",
      "description" : "Chemistry subject",
      "price" : "120"
    },
    {
      "name" : "Already-Existing-Subject",
      "description" : "Physics subject",
      "price" : "120"
    }
  ]
}

名称被视为唯一标识符,在阅读JSON并将其Map到内部模型之后,我需要确定应该创建哪些资源,并相应地创建它们,以及应该删除哪些资源,即没有在JSON资源中定义,但存在于数据库中。
现在需求有了一个子任务,其中包含:如果启用了选项readOnlyAndLog,则服务应仅遍历JSON资源,确定应执行哪些操作,并记录这些操作,而无需在数据库中执行任何创建/删除操作。
因此,启用此选项后,输出应如下所示:

New-subject will be created 
New-subject2 will be created
Already-Existing-Subject is already defined in the DB
Subject3 will be deleted
Subject4 will be deleted
.....

我现在的问题是,如何重用同一个服务,但这两个不同的场景取决于是否启用readOnlyAndLog?在服务上进行这种分离的最佳实践是什么?

tmb3ates

tmb3ates1#

根据属性值使用bean初始化。
可以使用方法void handleSubject(Subject subj)创建接口SubjectHandler
然后定义这个接口两个实现:ReadOnlySubjectHandlerDatabaseSubjectHandler,前者实现了检查主题和日志的逻辑,后者在数据库中放置了检查主题和执行CRUD操作的逻辑。
然后,您可以使用Spring注解@ConditionalOnProperty(name = "readOnlyAndLog", havingValue = "true/false")并将其放在接口的实现上。
下次启动应用程序时,Spring将只创建SubjectHandler的一个示例,具体取决于readOnlyAndLog的值。

jhdbpxl9

jhdbpxl92#

我试图复制你的项目,这里是一个可能的解决方案。
首先,定义实体Subject,名称为唯一标识符:

public class Subject {
    @Id private String name;
    @Column private String description;
    @Column private BigDecimal price;

    @Override
    public boolean equals(Object o) {
        if (o == this)
            return true;
        if (!(o instanceof Subject)) {
            return false;
        }
        Subject subject = (Subject) o;
        return Objects.equals(name, subject.name);
    }
}

application.properties中定义app.read-only-and-log

app.read-only-and-log=false

并使用@Value将该值绑定到SubjectServImpl

@Value("${app.read-only-and-log}")
private Boolean readOnlyAndLog;

SubjectServImpl中编写业务逻辑:

public void update(List<Subject> incoming) {
    List<Subject> existing = subjectRepo.findAll();

    // cross check incoming and existing
    for (Subject i : incoming) {
      if (existing.remove(i)) {
        if (readOnlyAndLog)
          log.info(i.getName() + " is already defined in the DB");
      } else {
        if (readOnlyAndLog)
          log.info(i.getName() + " will be created");
        else
          subjectRepo.save(i);
      }
    }

    if (readOnlyAndLog)
      existing.forEach(e -> log.info(e.getName() + " will be deleted"));
    else
      subjectRepo.deleteAll(existing);
}

您可以尝试从SubjectController调用subjectServ.update(subjects),而在application.properties中更改app.read-only-and-log的值将切换服务的行为。

**关于业务逻辑的一个附带说明:**当项目变得更大时,在每次调用更新时循环遍历SubjectRepo中的所有现有行可能不是理想的做法。

希望我能帮上一点忙。

相关问题