프로젝트의 구조를 만들 때 엔티티 중점 vs 기능 중점을 기준으로 구조를 만들 수 있다.
엔티티 중점
기능 중점
나는 이 중 기능을 중점으로 나누었다
필요한 패키지
1. controller
2. dto
3. entity
4. repository
5. service
6. exception
엔티티의 개수만큼 만드는게 아니라 사용될 url을 기준으로 나눈다.
/home
, /user
, /user/info
가 있다면 HomeController, UserController 두 개가 필요하다고 볼 수 있다.
@Controller
어노테이션이 필요하다@RequestMapping(value = "/user")
를 클래스에 사용해주면,@RequestMapping
을 써주고 내부 메소드에 @GetMapping(/info)
등을 사용해 특정하면 된다.RequiredArgsConstructor
를 필요로 한다.테이블별로 나누어 만들 수 있다. Entity 패키지 안에 사용될 그룹별로 나누고, 그 안에 Class를 넣어둔다.
@Entity
와 생성자
를 위한 어노테이션이 필요하다@Getter
어노테이션을 넣는다@NoArgsConstructor(access = AccessLevel.PROTECTED)
, @NonNull
, @Column(length = 100)
를 사용하였다ERD에서의 type과 객체의 자료형이 약간씩 다르다
varchar -> String
tinyint(1) -> Boolean (기본값 설정 필요 ex. faulse)
bigint -> Long
date -> LocalDateTime
ERD의 start_date는 엔티티에서 카멜케이스로 startDate로 표시한다.
이때 DB에서 똑바로 표현되기 위해 @Column(name = "start_date")를 해줄 필요 없다. JPA에서 자동으로 스네이크케이스로 변환해준다!
@Service
어노테이션 필요@RequiredArgsConstructor
넣어줌JpaRepository<Entity 클래스, PK 타입>
을 상속하면 기본적인 CRUD 메소드가 자동으로 생성된다.JpaRepository를 상속받는 것을 통해 Class를 만들어 save
, findAll
등을 직접 만들지 않아도 사용할 수 있게 된다.
생각해봐야 하는 부분) 프로젝트에서는 JpaRepository에서 했지만 강의와 아래의 링크에서는 @Repository를 추천한다?
Spring - JpaRepository가 아닌 Repository를 사용해야 하는 이유!
Ex)
public interface MemberRepository extends JpaRepository<Member, Long>{
}
Test)
@SpringBootTest //SpringConext를 로딩하여 Test에 활용하겠다.
class UserRepoitoryTest {
@Autowired
private UserRepoitory userRepoitory;
@Test
void crud(){ // create, read, update, delete
userRepoitory.save(new User()); //User 생성하고 저장.
System.out.println(" >>> " + userRepoitory.findAll());
}
}
JpaRepository
// 조건x 테이블 전체값 가져오기, Test 쓰이지만 실제서비스에선 성능때문에 잘 사용하지 않음.
@Override
List<T> findAll();
// sort값을 즉 정렬 값 추가된 조회
@Override
List<T> findAll(Sort sort);
// Id값을 List로 받아서 In 구문으로 조회하여 여러가지 레코드를 조회
@Override
List<T> findAllById(Iterable<ID> ids);
// entity를 리터럴로 받아서 모두 저장
@Override
<S extends T> List<S> saveAll(Iterable<S> entities);
// 현재 JPA컨텍스트에 가지고 있는 DB값을 DB에 반영하도록 하는 메서드
void flush();
// 위와 비슷 저장하고바로반영
<S extends T> S saveAndFlush(S entity);
<S extends T> List<S> saveAllAndFlush(Iterable<S> entities);
// Entity를 리터러블(리스트상위인터페이스) 형식으로 받아서 한꺼번에 지운다.
default void deleteInBatch(Iterable<T> entities){deleteAllInBatch(entities);}
// 조건없이 해당 엔티티 즉 테이블을 통제로 지운다. 실제로 안씀.FindAll이랑 비슷
void deleteAllInBatch(Iterable<T> entities);
// 해당 ID값을 받아서 값을 조회한다.
T getOne(ID id);
T getById(ID id);
// 예시를 이용한 findAll도 제공한다.
<S extends T> List<S> findAll(Example<S> example);
// 예시 + 정렬 값을 이용한 findAll도 사용 가능하다.
<S extends T> List<S> findAll(Example<S> example, Sort sort);
PagingAndSortingRepository
//Pageable을 사용해 쉽게 페이징 하도록 하는 메서드.
Page<T> findAll(Pageable pageable);
CrudRepository
// 우리가 사용하는 대부분이 여기 있다.
// 엔티티에 대한 저장
<S extends T> S save(S entity);
// 리스트타입을 한번에 저장
<S extends T> Iterable<S> saveAll(Iterable<S> entities);
// Optional 타입으로 랩핑해서 Id값으로 객체를 찾는 것 findOne과 조금 다름.
Optional<T> findById(ID id);
// 해당객체의 존재 여부확인
boolean existsById(ID id);
Iterable<T> findAll();
Iterable<T> findAllById(Iterable<ID> ids);
// 전체 엔티티의 개수 확인. 페이징할때 유용
long count();
// id값을 엔티티를 인자로 받아서 삭제.
void deleteById(ID id);
void delete(T entity);
void deleteAllById(Iterable<? extends ID> ids);
void deleteAll(Iterable<? extends T> entities);
void deleteAll();
참고
[Spring Boot] 게시판 구현 1 - Entity 및 Repository 만들기
JPA Repository Interface 상세 1
@RequestMapping