1.service 간단 설명
service는 서비스이다.

맞다. 당연히 x소리인데...
또 자세히 설명을 하면 '아예 틀린 말은 아니구나' 할 것이다.
service에서는 백엔드에서 동작하는 로직들을 함수로 정리한다.
보통 controller에서 service의 함수들을 호출하는데,
이 service가 repository와 연결이 되어 있다.
즉, controller에게 백엔드 기능을 수행할 수 있는 함수를 제공하고,(물론 그 함수는 직접 코딩해야 한다.)
repository와 연결까지 시켜주는 '서비스'를 제공하는 것이다.
2.service 코드
service를 두 부분으로 나눴다.
memberservice.java는 회원가입/로그인/비밀번호 찾기 등을 할 때의 기능을 모았고,
RoadDamageService.java는 도로 파손물에 대한 정보를 업데이트하는 것에 대한 service를 모았다.
memberservice.java
package com.example.finalproject.finalproject.service;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.example.finalproject.finalproject.dto.memberDTO;
import com.example.finalproject.finalproject.entity.MemberEntity;
import com.example.finalproject.finalproject.repository.memberRepository;
@Service
@Component
public class memberservice {
/*
* dto와 entity의 관계
* service의 코드들을 잘 보기 전에, dto,entity의 관계를 잘 볼 필요가 있다.
* 1.entity는 실제 디비와 매핑되는 핵심 클래스이다.
* 테이블이 가지지 않는 컬럼을 필드로 가져서는 안된다
* entity는 데이터베이스 영속성을 목적으로 사용되기 때문에 request,response값을 전달하는 클래스로 쓰지 말것.
*
* 2.dto는 레이어간 데이터 교환이 이뤄질 수 있도록 하는 객체이다.
* 디비에서 데이터를 얻어, service나 controller등으로 보낼 때 사용한다.
*
* 3.entity를 직접 반환할 경우에는 엔터티의 이름이 변경될 경우, 추가 작업이 필요할 수 있다.
* 또한, 보안 문제도 있고, 필요한 데이터만 전송하기 어렵다.
*
*
* 4.컨트롤러에서는 dto의 형태로 데이터를 받아 서비스에 전달한다.
* 5.서비스에서는 컨트롤러에서 받은 DTO를 Entity로 변환하고, 필요한 작업을 수행한 뒤에 Repository에 Entity를
* 전달한다.
*
*/
// service 객체에 쓰일 repository를 정의한다.
// repository에 jpa가 있기 때문에 꼭 정의를 해야 한다.
@Autowired
private final memberRepository memberRepository;
// memberRepository가 null인 상태에서 save 메서드를 호출하려 하면 오류가 난다. 그래서 이 코드를 추가.
@Autowired
public memberservice(memberRepository memberRepository) {
this.memberRepository = memberRepository;
}
// 받아온 데이터들을 저장하는 메소드이다.
public void save(memberDTO memberDTO) {
// repository의 save 메서드 호출.(entity를 넘겨야 한다.)
// 1.dto를 entity로 변환한다.(dto 클래스에 구현)
try {
MemberEntity memberEntity = MemberEntity.toMemberEntity(memberDTO);
memberRepository.save(memberEntity); // 이렇게 레포지토리로 데이터를 save시킨다.
}
// 2.save 메서드를 호출한다.(jpa에서 호출한다.)
// 3.이 쿼리를 통해 데이터베이스 내에서 쿼리를 만들어 주는 것이다.
catch (Exception e) {
e.printStackTrace();
}
}
public memberDTO login(memberDTO memberDTO) {
// 로그인을 수행할 때 수행되는 함수이다.
// 1.회원이 입력한 아이디로 db에서 조회를 한다.
// Optional은 memberentity를 한번 더 감싸는 개념이다.
Optional<MemberEntity> findById = memberRepository.findByMemberId(memberDTO.getMemberId());
// 조회 결과가 있다면
if (findById.isPresent()) {
// 일단 이 구문을 통해 데이터를 벗겨낸다.
MemberEntity memberEntity = findById.get();
// 2.db에서 조회한 비밀번호(entity)가 사용자가 입력한 비밀번호(dto)가 일치하는지 판단한다.
if (memberEntity.getPassword().equals(memberDTO.getPassword())) {
// 비밀번호 일치
// entity를 dto로 변환한 후 리턴해야 한다.(번거롭다.)
// 결국, 로그인을 성공했을 때만 dto에 뭘 담아서 주는 것이다.
memberDTO dto = memberDTO.toMemberDTO(memberEntity);
return dto;
} else {
// 비밀번호 불일치(로그인 실패)
return null;
}
} else {
// 3.없다면
return null;
}
}
// 회원 조회를 위한 함수이다.
public List<memberDTO> findAll() {
List<MemberEntity> memberEntityList = memberRepository.findAll();
// entity list를 dto list로 변환해야 한다.
List<memberDTO> memberDTOList = new ArrayList<>();
// 하나하나 꺼낸다.
for (MemberEntity memberEntity : memberEntityList) {
memberDTOList.add(memberDTO.toMemberDTO(memberEntity));
}
return memberDTOList;
}
public String emailCheck(String memberEmail) {
// repository 함수를 통해 사용자가 입력한 이메일 값으로 조회를 한다. 이렇게 조회하는 것은 JPA의 repository를 통해
// 조회할 수 있다.
Optional<MemberEntity> byMemberEmail = memberRepository.findByEmail(memberEmail);
if (byMemberEmail.isPresent()) {
// 이메일 값이 이미 있으면(회원이 중복되어 있으면)사용할 수 없다.
return null;
}
else {
// 조회 결과가 없으면 사용할 수 있다.
return "ok";
}
}
public String idCheck(String memberId) {
// repository 함수를 통해 사용자가 입력한 아이디 값으로 조회를 한다.
Optional<MemberEntity> byMemberId = memberRepository.findByMemberId(memberId);
if (byMemberId.isPresent()) {
// 아이디 값이 이미 있으면(회원이 중복되어 있으면)사용할 수 없다.
return null;
}
else {
// 조회 결과가 없으면 사용할 수 있다.
return "ok";
}
}
public MemberEntity getPasswordByEmail(String memberEmail) {
Optional<MemberEntity> byMemberEmail = memberRepository.findByEmail(memberEmail);
return byMemberEmail.orElse(null);
}
// Transactional 어노테이션은 여러 줄의 코드를 하나의 작업으로 처리해준다.
// 하나의 작업으로 처리해주면, 부분적으로 오류가 난 것을 같이 처리할 수 있다는 장점이 있다.
@Transactional
public boolean changePassword(String email, String newPassword) {
Optional<MemberEntity> userOptional = memberRepository.findByEmail(email);
if (userOptional.isPresent()) {
MemberEntity user = userOptional.get();
user.setPassword(newPassword);
memberRepository.save(user);
return true;
}
return false;
}
// 이메일로 아이디 찾기
public Optional<MemberEntity> findIdByEmail(String email) {
return memberRepository.findByEmail(email);
}
// 아이디로 비밀번호 찾기
public Optional<MemberEntity> findPasswordById(String memberId) {
return memberRepository.findByMemberId(memberId);
}
}
RoadDamageService.java
package com.example.finalproject.finalproject.service;
import java.util.List;
import java.util.stream.Collectors;
import javax.persistence.EntityNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.finalproject.finalproject.dto.RoadDamageDto;
import com.example.finalproject.finalproject.entity.RoadDamageEntity;
import com.example.finalproject.finalproject.repository.RoadDamageRepository;
@Service
public class RoadDamageService {
// 디비의 정보를 하나 하나 받는 service 파일이다.
// 이 파일을 통해 정보를 하나하나 받아오면, 이를js을 통해 웹 페이지에 팝업창을 띄운다.
@Autowired
private RoadDamageRepository roadDamageRepository;
public List<RoadDamageDto> getAllRoadDamages() {
List<RoadDamageEntity> roadDamages = roadDamageRepository.findAll();
return roadDamages.stream()
.map(this::convertToDTO)
.collect(Collectors.toList());
}
// 데이터들을 디비에서 가져오는 쿼리문(모든 table 포함.)
private RoadDamageDto convertToDTO(RoadDamageEntity roadDamage) {
if (roadDamage == null) {
throw new IllegalArgumentException("RoadDamage 객체가 null입니다.");
}
// 데이터들을 디비에서 가져온다.
RoadDamageDto dto = new RoadDamageDto();
dto.setId(roadDamage.getId());
dto.setPhotoInfo(roadDamage.getPhotoInfo());
dto.setLat(roadDamage.getLat());
dto.setLng(roadDamage.getLng());
dto.setCategoryId(roadDamage.getCategoryId());
dto.setCreationTime(roadDamage.getCreationTime());
dto.setCompletionTime(roadDamage.getCompletionTime());
dto.setMemberId(roadDamage.getMemberId());
dto.setMaintenance(roadDamage.getMaintenance());
return dto;
}
public void updateRoadDamage(Integer id, RoadDamageDto updateDto) {
RoadDamageEntity roadDamageEntity = roadDamageRepository.findById(id)
.orElseThrow(() -> new EntityNotFoundException("도로 위험물을 찾을 수 없습니다."));
// 업데이트할 필드들을 DTO에서 가져와 엔터티에 적용
roadDamageEntity.setMemberId(updateDto.getMemberId());
roadDamageEntity.setCompletionTime(updateDto.getCompletionTime()); // 현재 시간으로 업데이트
roadDamageEntity.setMaintenance(updateDto.getMaintenance());
// 디비에 새로 저장
roadDamageRepository.save(roadDamageEntity);
}
}
3.repository 간단 설명
entity에 의해 생성된 db에 접근하는 메서드들을 사용하기 위한 인터페이스이다.
엔터티를 선언했다면, 여기에 어떤 값을 넣거나, 넣어진 값을 조회하는 등의
CRUD(Create, Read, Update, Delete)를 해야 쓸모가 있는데, 이것을 어찌할지 정의해주는 계층이다.
가장 중요한 것은, jpaRepository를 상속받음으로서 기본적인 동작이 가능하다는 것이다.
public interface memberRepository extends JpaRepository<MemberEntity, Long>
이 구조를 잊지 말자. <>안의 변수들은 실제 엔터티에 따라 달라진다.
4.repository 코드
memberRepository.java와 RoadDamageRepository.java가 있다.
전자는 회원의 정보에 관한 entity에 대한 것이고,
후자는 도로 파손물에 관한 entity에 대한 것이다.
memberRepository.java
package com.example.finalproject.finalproject.repository;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.finalproject.finalproject.entity.MemberEntity;
public interface memberRepository extends JpaRepository<MemberEntity, Long> {
// jparepository를 상속받는다.
// 첫번째 인자는 엔터티이고, 두번째 인자는 primary key의 자료형이다.
// 인터페이스로 repository를 정의하기 때문에, 추상 클래스를 정의할 수 있다.
// 이메일로 찾기
Optional<MemberEntity> findByEmail(String email);
// member_id로 찾기.
Optional<MemberEntity> findByMemberId(String memberId);
}
RoadDamageRepository.java
package com.example.finalproject.finalproject.repository;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.example.finalproject.finalproject.entity.RoadDamageEntity;
@Repository
public interface RoadDamageRepository extends JpaRepository<RoadDamageEntity, Integer> {
// 기본적인 CRUD 메서드는 JpaRepository에서 자동으로 제공됩니다.
// id로 찾기.
Optional<RoadDamageEntity> findById(Integer id);
}