티스토리 뷰

Spring

JPA

장진혁 2023. 3. 4. 03:10
데이터베이스를 직접 다룰 때의 문제점이 있다고 한다.

 

  1. 번거롭다.
  2. SQL 의존적이라 변경에 취약
  3. 객체지향 모델과 관계형 데이터베이스의 패러다임 불일치가 발생

출처 : https://knoc-story.tistory.com/m/90

  객체  릴레이션
밀도 문제 다양한 크기의 객체를 만들 수 있음, 커스텀한 타입 만들기 쉬움 테이블, 기본 데이터 타입
서브타입 문제 상속, 다형성 구현 쉬움 상속 없음, 다형적인 관계 표현 불가
식별성 문제 레퍼런스 동일성, 인스턴스 동일성 오직 pk
관계 문제 서로간의 객체 참조를 통해 표현, 다대다 가능, 방향이 있다 다대다 x, 다대다를 맺어주는 테이블로 처리, 외래키가 있어서 바로 조회 가능(방향 없음)
데이터 네비게이션 문제 마음대로 레퍼런스타고 이동 가능 그러한 방식이 비효율적(매번 join, 그리고 다 가저오면 성능문제)
  1. 밀도 문제는 딱히 설명이 필요 없겠죠. 데이터베이스의 데이터가 더 정형화되어있고 까다롭습니다.
  2. 관계형 데이터 베이스에는 상속의 개념이 없습니다. 하지만 우리가 이미 배웠던 것처럼 상속은 객체의 역할과 구현을 분리해주기 위해 객체 지향 프로그래밍에서 가장 핵심적인 기능 중 하나입니다.
  3. 관계 문제와 데이터 네비게이션 문제는 설명이 조금 더 필요 할 것 같습니다.
		// DB 연결
        Connection connection = DriverManager.getConnection("jdbc:h2:mem:db", "sa", "");

        // DB Query 작성
        PreparedStatement ps = connection.prepareStatement("select max(id) as id from product");
        ResultSet rs = ps.executeQuery();
        if (rs.next()) {
            // product id 설정 = product 테이블의 마지막 id + 1
            product.setId(rs.getLong("id") + 1);
        } else {
            throw new SQLException("product 테이블의 마지막 id 값을 찾아오지 못했습니다.");
        }

        ps = connection.prepareStatement("insert into product(id, title, image, link, lprice, myprice) values(?, ?, ?, ?, ?, ?)");
        ps.setLong(1, product.getId());
        ps.setString(2, product.getTitle());
        ps.setString(3, product.getImage());
        ps.setString(4, product.getLink());
        ps.setInt(5, product.getLprice());
        ps.setInt(6, product.getMyprice());

        // DB Query 실행
        ps.executeUpdate();

        // DB 연결 해제
        ps.close();
        connection.close();

        // 응답 보내기
        return new ProductResponseDto(product);

 

패러다임 불일치에서 기인한 문제들과,
반복적이고 번거로운 어플리케이션 단에서의 쿼리 작업을 줄여주기 위해서
ORM(객체 관계 매핑)기술들이 등장

 

JPA: Java Persistence API 자바 ORM 기술에 대한 표준 명세

아래와 같은 일들을 해줍니다.

  1. 쿼리를 자동으로 만들어 줍니다.
  2. 그리고 어플리케이션 계층에서 sql 의존성을 줄여서 번거로운 작업이 매우매우 단축됩니다.
  3. 패러다임의 불일치를 해결해줍니다. 이와 관련된 내용으로는 매우 다양한 예시가 있지만, 지금 모두 이야기하게는 너무 많은 것 같습니다.
  4. 특정한 상황을 제외하고는,성능도 챙겼습니다. 최적화를 위한 노력이 있었습니다..
  5. 방언도 지원해줍니다. h2 Databse를 붙여도, mySql, oracle 뭘 붙여도 코드의 변경은 없습니다, 관계형 db이자 표준을 준수한 sql을 지원한다면, jpa가 방언들도 알아서 처리해줍니다.

JPA 연관관계

  • 회원 1명은 주문 N개를 할 수 있다.
    • 회원 : 주문 = 1 : N 관계
  • 음식 1개는 주문 N개에 포함될 수 있다.
    • 음식 : 주문 = 1 : N 관계
  • 결론적으로
    • 회원 : 음식 = N : N 관계

 

JPA 연관관계 설정방법

 

문제점: 회원 중복

@Getter
@Entity
@NoArgsConstructor
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(nullable = false) // 널이 아니여야
    private String memberName;

    // 회원 하나는 여러개의 주문을 넣을 수 있다.
    @OneToMany(mappedBy = "member", fetch = FetchType.EAGER) // 연관 관계 주인은 mamber
    private List<Orders> orders = new ArrayList<>(); // 여러가지 오더여서 리스트 형식이다.

    public Member(String memberName) {
        this.memberName = memberName;
    }
}

문제점: 음식 중복

@Getter
@Entity
@NoArgsConstructor
public class Food {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(nullable = false)
    private String foodName;
    @Column(nullable = false)
    private int price;

    // 음식하나에 오더가 여러개일 수 있다.
    @OneToMany(mappedBy = "food", fetch = FetchType.EAGER) // 연관 관계 주인은 food
    private List<Orders> orders = new ArrayList<>(); // 여러가지 오더여서 리스트 형식이다.

    public Food(String foodName, int price) {
        this.foodName = foodName;
        this.price = price;
    }
}

주문'을 위한 테이블이 필요 → Order 테이블 추가

@Getter
@Entity
@NoArgsConstructor
public class Orders {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // food와 member의 id를 받아와야한다.
    // 같은 음식을 많이 시킬수 있다 하나의 음식으로 부터
    @ManyToOne
    @JoinColumn(name = "food_id") // food의 아이디로 조인하겠다.
    private Food food; // 연관관계 주인은 food이다.

    // 주문을 여러번 넣을 수 있다 하나의 회원으로 부터
    @ManyToOne
    @JoinColumn(name = "member_id") // 멤버의 아이디로 조인하겠다.
    private Member member;// 연관관계이 주인은 mamber

    public Orders(Food food, Member member) {
        this.food = food;
        this.member = member;
    }
}

'Spring' 카테고리의 다른 글

HTTP, MVC 패턴  (1) 2023.03.05
@Valid 어노테이션으로 Parameter 검증하기 ft.정규식  (0) 2023.03.05
트랜젝션(Transaction)  (0) 2023.03.02
IoC 와 DI  (0) 2023.03.01
Spring MVC 패턴 CRUD API 만들기  (0) 2023.02.28
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함