Java 将数据库条目连接到Springbean

Java 将数据库条目连接到Springbean,java,spring,spring-bean,Java,Spring,Spring Bean,标题可能有点误导,但我正试图找到将数据库条目连接到Springbeans的最佳解决方案。我希望下面的例子能澄清问题 首先,我有一个任务实体 @Entity @Table( name = "tasks") class Task { } 我还有一个TaskExecutor接口,它只有一个方法executetask public interface TaskExecutor { void executeTask(Task t); } 现在,我有3个TaskExecutor接口的实现 @Ser

标题可能有点误导,但我正试图找到将数据库条目连接到Springbeans的最佳解决方案。我希望下面的例子能澄清问题

首先,我有一个
任务
实体

@Entity
@Table( name = "tasks")
class Task {

}
我还有一个
TaskExecutor
接口,它只有一个方法executetask

public interface TaskExecutor {
  void executeTask(Task t);
}
现在,我有3个
TaskExecutor
接口的实现

@Service("taskExecutorOne")
class TaskExecutorOne implements TaskExecutor {  
}
@Service("taskExecutorTwo")
class TaskExecutorTwo implements TaskExecutor{
 }    
@Service("taskExecutorThree")
class TaskExecutorThree implements TaskExecutor{
} 
现在,每个任务都应该由这三个任务执行者之一执行。 我遇到的问题是,确定在任务数据库条目和可用executor服务之间创建连接的最佳解决方案

1。一种方法是创建一个带有三个值的
ExecutorType
enum:

 enum ExecutorType {
    EXECUTOR_ONE,
    EXECUTOR_TWO,
    EXECUTOR_THREE
    };
我们可以在tasks表中添加一列,该列将包含特定任务的枚举值。这样,当我们需要为任务找到执行者时,我们可以这样做:

@Service
class TaskRegisterService {
  @Autowired
  @Qualifier("taskExecutorOne")
  private TaskExecutor taskExecutorOne;

  @Autowired
  @Qualifier("taskExecutorOne")
  private TaskExecutor taskExecutorOne;

  @Autowired
  @Qualifier("taskExecutorOne")
  TaskExecutor taskExecutorOne;

  public TaskExecutor getExecutorForTask(Task t) {
    if(t.executorType == ExecutorType.EXECUTOR_ONE)
      return taskExecutorOne;
    else if(t.executorType == ExecutorType.EXECUTOR_TWO)
      return taskExecutorTwo;
    else if(t.executorType == ExecutorType.EXECUTOR_THREE)
      return taskExecutorThree;
  }
}
@Service
class TaskRegisterService {

  @Autowired 
  private ApplicationContext applicationContex;

  public TaskExecutor getExecutorForTask(Task t) {
    return (TaskExecutor) applicationContex.getBean(t.getBeanName());
  }
}
@Service("taskExecutor")
public class TaskExecutorRouter implements TaskExecutor {
    private final Map<String, TaskExecutor> taskExecutorMap;

    @Autowired
    public TaskExecutorRouter(@Qualifier("taskExecutorOne") TaskExecutor taskExecutorOne,
                              @Qualifier("taskExecutorTwo") TaskExecutor taskExecutorTwo,
                              @Qualifier("taskExecutorThree") TaskExecutor taskExecutorThree) {
        this.taskExecutorMap = new HashMap<>();
        taskExecutorMap.put("taskExecutorOne", taskExecutorOne);
        taskExecutorMap.put("taskExecutorTwo", taskExecutorTwo);
        taskExecutorMap.put("taskExecutorThree", taskExecutorThree);
    }

    @Override
    public void executeTask(Task task) {
        taskExecutorMap.get(task.getExecutorType()).executeTask(task);
    }
}
我不喜欢这个解决方案,因为创建新服务需要在enum中添加一个新条目,并在
getExecutorForTask
方法中添加一个新的
if
部分

2.另一种方法是将bean名称存储在
tasks
表中。在这种情况下,
getExecutorForTask
将如下所示:

@Service
class TaskRegisterService {
  @Autowired
  @Qualifier("taskExecutorOne")
  private TaskExecutor taskExecutorOne;

  @Autowired
  @Qualifier("taskExecutorOne")
  private TaskExecutor taskExecutorOne;

  @Autowired
  @Qualifier("taskExecutorOne")
  TaskExecutor taskExecutorOne;

  public TaskExecutor getExecutorForTask(Task t) {
    if(t.executorType == ExecutorType.EXECUTOR_ONE)
      return taskExecutorOne;
    else if(t.executorType == ExecutorType.EXECUTOR_TWO)
      return taskExecutorTwo;
    else if(t.executorType == ExecutorType.EXECUTOR_THREE)
      return taskExecutorThree;
  }
}
@Service
class TaskRegisterService {

  @Autowired 
  private ApplicationContext applicationContex;

  public TaskExecutor getExecutorForTask(Task t) {
    return (TaskExecutor) applicationContex.getBean(t.getBeanName());
  }
}
@Service("taskExecutor")
public class TaskExecutorRouter implements TaskExecutor {
    private final Map<String, TaskExecutor> taskExecutorMap;

    @Autowired
    public TaskExecutorRouter(@Qualifier("taskExecutorOne") TaskExecutor taskExecutorOne,
                              @Qualifier("taskExecutorTwo") TaskExecutor taskExecutorTwo,
                              @Qualifier("taskExecutorThree") TaskExecutor taskExecutorThree) {
        this.taskExecutorMap = new HashMap<>();
        taskExecutorMap.put("taskExecutorOne", taskExecutorOne);
        taskExecutorMap.put("taskExecutorTwo", taskExecutorTwo);
        taskExecutorMap.put("taskExecutorThree", taskExecutorThree);
    }

    @Override
    public void executeTask(Task task) {
        taskExecutorMap.get(task.getExecutorType()).executeTask(task);
    }
}
这样,我就可以添加新的执行器,而无需在
getExecutorForTask
方法中添加任何额外的代码,但我必须在数据库中存储bean名称

有没有更好的方法来解决我刚才描述的问题?如果不是,我描述的方法中哪一种看起来更好?
我的目标是能够轻松地添加新的执行器,同时修改尽可能少的代码。

我建议最后一个选项,基于枚举将bean名称添加到数据库是确定需要使用哪个执行器的有效方法。它使您的代码更加动态和模块化,并且看起来更加干净(if-else语句更少),因此我绝对鼓励您使用最后一个选项


如果您还有任何问题可以问,那么我将详细说明:)

您可以创建TaskExecutor装饰器来选择实现。大概是这样的:

@Service
class TaskRegisterService {
  @Autowired
  @Qualifier("taskExecutorOne")
  private TaskExecutor taskExecutorOne;

  @Autowired
  @Qualifier("taskExecutorOne")
  private TaskExecutor taskExecutorOne;

  @Autowired
  @Qualifier("taskExecutorOne")
  TaskExecutor taskExecutorOne;

  public TaskExecutor getExecutorForTask(Task t) {
    if(t.executorType == ExecutorType.EXECUTOR_ONE)
      return taskExecutorOne;
    else if(t.executorType == ExecutorType.EXECUTOR_TWO)
      return taskExecutorTwo;
    else if(t.executorType == ExecutorType.EXECUTOR_THREE)
      return taskExecutorThree;
  }
}
@Service
class TaskRegisterService {

  @Autowired 
  private ApplicationContext applicationContex;

  public TaskExecutor getExecutorForTask(Task t) {
    return (TaskExecutor) applicationContex.getBean(t.getBeanName());
  }
}
@Service("taskExecutor")
public class TaskExecutorRouter implements TaskExecutor {
    private final Map<String, TaskExecutor> taskExecutorMap;

    @Autowired
    public TaskExecutorRouter(@Qualifier("taskExecutorOne") TaskExecutor taskExecutorOne,
                              @Qualifier("taskExecutorTwo") TaskExecutor taskExecutorTwo,
                              @Qualifier("taskExecutorThree") TaskExecutor taskExecutorThree) {
        this.taskExecutorMap = new HashMap<>();
        taskExecutorMap.put("taskExecutorOne", taskExecutorOne);
        taskExecutorMap.put("taskExecutorTwo", taskExecutorTwo);
        taskExecutorMap.put("taskExecutorThree", taskExecutorThree);
    }

    @Override
    public void executeTask(Task task) {
        taskExecutorMap.get(task.getExecutorType()).executeTask(task);
    }
}
@服务(“任务执行者”)
公共类TaskExecutorRouter实现TaskExecutor{
私人最终地图;
@自动连线
公用TaskExecutorRouter(@Qualifier(“taskExecutorOne”)TaskExecutor taskExecutorOne,
@限定符(“taskExecutorTwo”)taskExecutorTwo,
@限定符(“TaskExecutor三”)TaskExecutor TaskExecutor三){
this.taskExecutorMap=新HashMap();
taskExecutorMap.put(“taskExecutorOne”,taskExecutorOne);
taskExecutorMap.put(“taskExecutorTwo”,taskExecutorTwo);
taskExecutorMap.put(“taskExecutorThree”,taskExecutorThree);
}
@凌驾
public void executeTask(任务){
taskExecuteMap.get(task.getExecuteType()).executeTask(task);
}
}

然后您可以只将此实现作为TaskExecutor注入。

我不确定我是否正确解释了它,但在我的第二个选项中将没有枚举。我对枚举的问题是,添加新服务需要向枚举中添加新条目,如果我决定创建上述代码库,这可能是不可能的。@Dvorog,在这种情况下,它仍然是最好的选择:)我只是假设您会使用枚举,但事实并非如此mandatory@Dvorog,这个问题的回答令您满意吗?:)我同意你的回答,但我想知道,如果有人已经有过这类问题的经验,是否会有一个更具洞察力的解决方案。我想我正在等待一个更详细的解释,或者一种能让我以更好的方式解决问题的方法,因为在数据库中存储bean名称似乎不是一件好事。我很感谢你的回答,如果我没有得到更好的答案,我可能会选择这个解决方案,但我觉得这不应该是目前公认的答案(如果你是这么问的话)。@Dvorog,我想知道如果我的回答没有完全回答这个问题,我是否可以帮助你进一步解决这个问题:)你能否详细说明任务执行者之间的不同方式以及他们(可能)需要做什么?有几个例子对于提出一个好的解决方案非常有用:)谢谢你的回答,但是这个解决方案与我描述的(选项1)没有什么不同。这一个需要跟踪寄存器中的所有可用服务,因此它与创建枚举相同。