연관관계가 있는 Repository를 Dao에서 조합해서 엔티티를 다루는 방식이다.
예컨대, 식물 엔티티
는 장소 엔티티
, 가드너(회원) 엔티티
와 연관관계를 맺고 있으므로 PlantDao
가 PlaceRepository
, GardenerRepository
, PlantRepository
를 가지고 있는 것이다.
하나밖에 없다.
save, update 시 엔티티 조합 로직을 분리하고 싶었다.
@Override
public int getCountByChemical_ChemicalId(Long chemicalId) {
return wateringRepository.countByChemical_ChemicalId(chemicalId);
}
읽기, 삭제 메소드는 이유 없이 레이어만 하나 타게 된다.
@Service
@RequiredArgsConstructor
public class ChemicalCommandServiceImpl implements ChemicalCommandService{
private final ChemicalRepository chemicalRepository;
private final GardenerRepository gardenerRepository;
@Override
@Transactional
public <T> T update(Long gardenerId, ChemicalDto chemicalRequest, ServiceCallBack<T> callBack) {
Chemical chemical = chemicalRepository.findById(chemicalRequest.getId()).orElseThrow(NoSuchElementException::new);
chemical.update(chemicalRequest.getName(), chemicalRequest.getType(), chemicalRequest.getPeriod());
return callBack.execute(chemical);
}
@Override
@Transactional
public <T> T save(Long gardenerId, ChemicalDto chemicalRequest, ServiceCallBack<T> callBack) {
Gardener gardener = gardenerRepository.getReferenceById(gardenerId);
Chemical chemical = chemicalRepository.save(chemicalRequest.toEntity(gardener));
// 서비스에서 제공하는 콜백을 호출하고 결과를 반환
return callBack.execute(chemical);
}
}
공통 로직을 CommandService로 분리하되, 리턴용 DTO는 콜백함수를 통해 만드는 코드로 리팩토링했다.
덕분에 Dao 레이어는 아예 삭제했다.
각 Repository가 CrudRepository
나 JpaRepository
대신 Repository
를 extends해 실사용하는 메소드만 가지도록한다.
결국 Command/Query 서비스가 분리된 셈인데,
그러면 Controller, Service, Repository 모두 읽기 전용과 쓰기 전용으로 분리해야 하는 것 아닌가?
만들면 만들수록 어렵다