我在访问我的实体中的服务时遇到问题。我知道,除了我的代码不起作用之外,也不推荐它。所以,我想知道如果我遇到这样的问题,最佳做法是什么?这是我的类(class)。
Controller 类:
@Controller
@RequestMapping("step")
public class TenderController {
@Autowired
StepService stepService;
@GetMapping("")
public ModelAndView index(ModelAndView mView,
@ModelAttribute(name = "result_code") String result_code,
@ModelAttribute(name = "result_message") String result_message) {
mView.addObject("stepList", stepService.getAllSteps());
mView.setViewName("pages/step/index");
return mView;
}
}
在我的 View html 上,我迭代了步骤列表
<tr th:each="s:${stepList}"
th:classappend="${s?.isStepNow()?'bg-success':''}">
<!-- some td -->
</tr>
问题是,由于某种原因,我必须使用 if else 条件来获取当前日期以在 isStepNow() 方法中使用。一个来自操作系统。另一份来自数据库。所以,我想到了创建一个服务类的想法
以下是服务类:
public interface TimeServices {
Date getNow();
}
和实现类:
@Service
public class TimeServicesImpl implements TimeServices {
@Value("${app.mode}")
String appMode;
@Autowired
DateDBRepository dateDBRepository;
@Override
public Date getNow() {
if(appMode.equalsIgnoreCase("GET_FROM_DB")){
Optional<DateDB> dateDBOptional = dateDBRepository.findById(1L);
if(dateDBOptional.isPresent()){
return dateDBOptional.get().getDate();
}else{
throw new IdNotExistsException();
}
}else{
return new Date();
}
}
}
问题出在我的实体中:
@Entity
@Table(name = "step")
public class Step{
@Autowired
@Transient
TimeServices timeServices; //BAD PRACTICE AND DOESN'T WORK
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Date start;
private Date end;
public Boolean isStepNow(){
Date now = timeServices.getNow(); //THE PROBLEM
if(now.compareTo(start)>0 && end.compareTo(now)>0) {
return true;
}else{
return false;
}
}
}
当然不行,因为timeService始终为null。有人可以建议我解决这个问题吗?
我知道我可以将 isStepNow() 编辑为 isStepNow(Date date)。然后,我可以通过 Controller 访问该服务。所以我可以在我的 View 中调用 isStepNow(date) 。但是,我认为编写源代码效率不高,因为我必须从某些 Controller 访问服务,而不是只在实体中编写一次。
最佳答案
我已经看过很多这样的讨论了。 使用DDD的人往往会这样解决:
- 将 @Entity 注解的类重命名为 StepEntity 或 ORMStep 类似的名称,并仅保留在该类中执行 ORM 所需的字段。
- 创建您使用 ORMStep 和依赖服务创建的不同(域)类 Step,并将域逻辑方法放入该类中。
- 让 StepService 接口(interface)(最好称之为 StepRepository)返回 Step 类,而不是 ORMStep。
- 通过注入(inject) DAO(Spring Data 也将其称为 Repository)和依赖服务来实现 StepRepository,并将它们组合起来读取 ORMStep 并转换为 Step 类。
这看起来需要付出很大的努力,并且您可能还需要将 Step 实例转换回 ORMStep 类才能进行更新,但从长远来看,这是一个非常干净的解决方案。您可以独立于 ORM 类发展 Step 类,或者切换 ORM,而无需更改 Controller 等。
它也是 TDD 友好的,因为所有业务逻辑都在域对象中,而不是在 ORM 对象中,因此您可以更轻松地对它们进行单元测试。
如果您使用的类有很多字段,MapStruct 和/或 Lombok Builders 可以使您的代码保持简洁。
关于java - 当我认为我可以从 Spring 中的实体访问服务时,如何更好的解决方案来替换我的代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60949240/