Spring 입문 230224 #4 연관관계/Timestamped/에너테이션

김춘복·2023년 2월 25일
0

Spring 공부

목록 보기
4/14
post-custom-banner

DB의 연관관계

  • 자바는 객체와 참조. DB는 FK로 각자의 연관관계 방식이 있는데, 두 방식의 차이를 해결하기 위해 JPA는 Java 어플리케이션 상에서, DB의 연관관계를 표현해주기위한 장치가 있다.

  • DB의 연관관계는 비즈니스 요구사항에 맞춰 이루어진다.
    JPA가 제공하는 연관관계는 이러한 DB의 연관관계를 표현하기 위함이다.

JPA 연관관계

  • JPA는 Entity 클래스 필드 위에 연관관계 @(어노테이션)을 설정해주면 된다.

  • 연관관계 종류

Spring Data JPA

: JPA를 편하게 쓰기 위해 스프링에서 JPA를 Wrapping.
스프링 개발자들이 JPA를 쓸 때 필수적으로 생성해야하나 예상가능하고 반복적인 코드
-> Spring Data JPA가 대신 작성.
Repository 인터페이스만 작성하면 필요한 구현은 스프링이 알아서한다.

  • Spring Data JPA 기본 제공기능
    예시) public class Product extends Timestamped에서
    public interface ProductRepository extends JpaRepository<Product, Long> 생성
// 1. 상품 생성
Product product = new Product(...);
productRepository.save(product);

// 2. 상품 전체 조회
List<Product> products = productRepository.findAll();

// 3. 상품 전체 개수 조회
long count = productRepository.count();

// 4. 상품 삭제
productRepository.delete(product);

.save() : 하나의 객체만 저장할 때 사용.
.saveAll() : 리스트형식처럼 되어있는걸 한번에 저장할 때 사용
.findAll : 전제 조회
.count() : 전체 '개수' 조회
.delete() : 삭제

  • ID이외의 필드에 대한 추가기능은 인터페이스만 선언해주면 구현은 Spring Data JPA가 대신
public interface ProductRepository extends JpaRepository<Product, Long> {
    // (1) 회원 ID 로 등록된 상품들 조회
    List<Product> findAllByUserId(Long userId);

    // (2) 상품명이 title 인 관심상품 1개 조회
		Product findByTitle(String title);

		// (3) 상품명에 word 가 포함된 모든 상품들 조회
		List<Product> findAllByTitleContaining(String word);

		// (4) 최저가가 fromPrice ~ toPrice 인 모든 상품들을 조회
    List<Product> findAllByLpriceBetween(int fromPrice, int toPrice);
}

위처럼 조건에 따라서 사용할 수 있는 메서드들은 이미 다 구현이 되어있다.
Spring Data JPA 추가기능 구현방법

  • Repository 인터페이스에서
    Optional<Member> findByMemberName(Strinf memberName) 이런 식으로 만들면
    다른 자바 파일에서 memberRepository.findByMemberName() 처럼 만든 메서드를 쓸 수 있다.

실습 메모

실습주소

  • 클래스에 붙여주는 에너테이션
    @Entity : 클래스를 Entity로 선언
    @Getter : 값을 가져올때 쓰는 게터 추가
    @NoArgsConstructor : 기본생성자 만들어줌

  • 클래스 안에 넣어두는 애너테이션
    @Id : 해당 엔티티의 주요 키(Primary Key, PK)가 될 값을 지정해주는 것.
    Id만 사용할 시 기본키를 직접할당해야하는데 아래를 쓰면 안해도 된다.
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    : @GeneratedValue는 기본키를 자동으로 생성해주는 어노테이션.
    IDENTITY 전략은 기본 키 생성을 데이터베이스에 위임하는 것.

  • 컬럼에 위에 붙이는 애너테이션(해당 컬럼위에)
    @Column(nullable = false) : 컬럼안에 들어가는 값들은 null이 안된다. 값이 꼭 있어야
    @ManyToOne : 같은 entity 관계 설정도 컬럼에
    @JoinColumn(name = "food_id") : food테이블의 id를 가져와서 쓴다? 사용법알아보기
    @OneToMany(mappedBy = "food") : 연관관계의 주인을 food로 지정.
    위의 name = food_id의 주인을 mappedBy=여기서 알려줌
  • 필드(컬럼,열)값은 private Long id; 처럼 클래스의 변수로 선언 id는 long으로!

  • join으로 orders 테이블에서 멤버랑 푸드테이블을 땡겨왔으면
    멤버와 푸드에도 받아주는부분 넣어야 한다. 위의 mappedBy=

  • food에서 orders를 받는 컬럼을 만드는데 @OneToMany로 받는다.
    음식 1개에 order 여러개가 될 수 있기 때문에?
    컬럼은 ArrayList<Orders>로 설계

  • Repository는 인터페이스로 생성하고 extends JpaRepository<Food, Long>
    JpaRepository를 상속하면서 제네릭스는 어떤 테이블과 연결할지 명시해야한다.
    Long은 Id를 Long으로 지정했기때문에 그렇다.
    JpaRepository<연결하려는테이블, Id타입>

  • 상속으로 생성 수정시간 관리하기 Timestamped
    Post클래스가 Timestamped(생성 수정시각 필드로)를 상속하는 것만으로도
    DB에 추가가 될때 자동으로 시각이 기록된다.

Entity를 만들 때 Timestamped 객체를 만들고

@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class) 
public class Timestamped {

    @CreatedDate
    @Column(updatable = false)
    private LocalDateTime createdAt;

    @LastModifiedDate
    @Column
    private LocalDateTime modifiedAt;
}

public class Post extends Timestamped 처럼 테이블에 상속받으면
상속받은 Entity 객체는 항상 Timestamped의 칼럼을 가진다.
매번 등록해야하는 번거로움을 덜 수 있다.

profile
Backend Dev / Data Engineer
post-custom-banner

0개의 댓글