Как лучше заменить мой код, если я думаю, что я могу получить доступ к сервису из сущности в Spring? - PullRequest
0 голосов
/ 31 марта 2020

У меня проблема с доступом к сервису в моей организации. Я знаю, кроме того, что мой код не работает, он также не рекомендуется. Итак, я хочу знать, что является лучшей практикой, если у меня есть такая проблема? Вот мой класс.

Класс контроллера:

@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;
   }
}

На мой взгляд html, я повторяю stepList

<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 всегда нулевой. У кого-нибудь есть рекомендации для решения этой проблемы?

Я знаю, что могу отредактировать свой isStepNow () в isStepNow (Date date). Затем я могу получить доступ к услуге через контроллер. Так что я могу назвать isStepNow (дата) на мой взгляд. Но я думаю, что это неэффективно при написании исходного кода, потому что мне нужно получить доступ к сервису с некоторых контроллеров, а не писать его только один раз в сущности.

1 Ответ

1 голос
/ 31 марта 2020

Я много видел эту дискуссию. Люди, использующие DDD, как правило, решают его следующим образом:

  • Переименуйте свой аннотированный класс @ Entity в StepEntity или ORMStep во что-то похожее и оставьте только поля, необходимые для ORM в этом классе.
  • Создайте другой (доменный) класс Step, который вы создаете с помощью ORMStep и зависимых сервисов, и поместите в этот класс методы logi c вашего домена.
  • Позвольте интерфейсу StepService (лучше назвать его StepRepository ) возвращает класс Step, а не ORMStep.
  • Реализуйте StepRepository, внедрив как DAO (который Spring Data смущенно также вызывает Repository), так и зависимые службы, и объедините их для чтения ORMSteps и преобразования в классы Step.

Это похоже на большие усилия, и вам, вероятно, нужно преобразовать экземпляры Step обратно в классы ORMStep, чтобы выполнять обновления, но в долгосрочной перспективе это очень чистое решение. Вы можете развивать классы Step независимо от классов ORM или переключать ORM, не меняя контроллер и т. Д. c.

Это также дружественно к TDD, поскольку все бизнес-логики c находятся в доменные объекты, а не объекты ORM, так что вы можете гораздо проще их тестировать.

Если у используемых вами классов много полей, MapStruct и / или Lombok Builders могут поддерживать ваш код в чистоте.

...