JPA 진입..!

가언·2024년 7월 25일

spring

목록 보기
7/8
post-thumbnail

들어가기 앞서....

음...제가 한번 JPA 경험을 해봤는데요..
정말 매콤하더라구요 😂
단단히 마음의 준비 하시구요! 천천히 JPA에 스며들어봅시당..!

먼저 JDBC부터!

✔️ JDBC의 특징

  • JDBC는 사실 api!
  • JDBC를 한겹 더 싸는 것이 myBatis이고,
  • default: 하이버 네이트 사용
  • sql을 통해서 직접 객체를 mapping하는 역할

JPA는 해결사!✨

앞 포스팅에서 JPA가 필요한 이유는 말씀드렸쬬?!
그럼 JPA가 얼마나 중요한지 체감하신걸로 알고! 넘어가겠습니당
먼저 maven repository에 들어가서 jpa을 검색해볼까요~?

maven repository에서 찾은 JPA repository에 jdbc가 포함되어 있는거 보이시나용?!
JPA는 사실 JDBC를 포함하고 있는데요
JDBC만으로 sql를 통해서 직접 객체를 mapping하는 것도 쉽지 않았다고 합니다...
그래서 JDBC를 포함하고 있는 JPA가 이 중대한 문제의 해결사‼️라는 말이죠.


(cf. ORM: 객체와 관계를 mapping하는 것)
위 그림과 같이 JPA(+JDBC)가 자바와 mysql사이에서 데이터를 요청하고, 제공하며 mapping시켜주고 있네요.

코드 적용1

이론으로 배웠으니 이제 코드에 적용해봅시당

Q. MySQL과 JPA를 깔고 싶은데 어떻게 해야할까요?
▶︎ 간단합니당 인텔리제이의 build.gradle파일에 DB설치 명령하면 되게쬬?!
코드

implementation 'mysql:mysql-connector-java:8.0.31' //mysql을 사용할거야!
implementation 'org.springframework.boot:spring-boot-starter-data-jpa:3.3.2' //jpa를 사용할거야!

위에서 언급했다시피 jpa안에 jdbc가 포함되어 있기 때문에 jdbc코드는 추가하지 않아도 됩니다.
또 버전을 추가로 적지않아도, 안정화된 최신 버전을 자동으로 다운해줍니다!

Spring Data JPA는 또 뭐야?

  • JPA와 Spring Data JPA와 같을까 다를까용?
  • JPA와 같기도 하고 다르기도하다...!

    스프링이 기존 JPA+스프링 추가 기능을 덧댄 것이 Spring Data JPA이기 때문이죠!

즉 , spring이 우리가 JPA를 더 편하게 쓸 수 있게 도와주는 것!
"Spring Data JPA"는 더욱 추상화한 인터페이스이다!
로 정리할 수 있겠네용


JDBC에서 일하는 친구

  • DataSource: "JDBC주요 일꾼"으로 무슨역할을 할까?
    • DB와 소통 역할
    • 데이터를 주고받을 터널을 뚫을 주는 객체
  • jdbc 구현체: Hikari

코드 적용2 - 데이터 소스

application.propertiesn <프로젝트 속성> 코드 추가

1) DB 연결(JDBC를 사용하려면, 'DabaSource 객체'속성)

	spring.datasource.driver-class-name=마리아db
	spring.datasource.url=내 컴퓨터에 있는 디비
	spring.datasource.username=dbwjspdla
	spring.datasource.password=비밀번호

spring datasource 공식문서

2) 포트 넘버 바꾸기
3) 프로젝트 이름 바꾸기
4) 로그 파일 경로

주의할 점 + 막간지식

  • yml: 코드의 중복을 해결하는 파일형식 (트리구조)
  • xml: <> 파일 형식
  • 데이터베이스도 일종의 웹서버처럼 데이터 베이스 서버역할을 하기 때문에 port번호가 필요한 것
  • jpa는 기본 속성이 없어서 필요한 것만 추가해야 함

DB API들의 구현체 내 주요 객체

  • JDBC <복습>
    • 구현체: Hikari(패키지)
    • 주요 객체: DataSource
  • JPA
    • 구현체: hibernate(패키지)
    • 주요 객체: EntityManager: persistant 운동장에서 열심히 일하는 일꾼
    • EntityManager는 어디에 구현되어있을까? 직접 찾아봅시다!! ⬇️
  • Spring Data JPA
    - 구현체:
    - 주요 객체:

    여기서 생긴 궁금증❓

    dataSource와 EntityManager를 우리는 등록한적이 없는데 어떻게 등록되어있는 걸까yo?!?!
    @AutoConfiguration애노테이션을 통해 스프링이 자동으로 미리 등록해준다고 합니다!!
    스프링 짱!🫡




Entity method

참고 자료

  • persist(Object entity): 새로운 엔티티를 영속성 컨텍스트에 추가+저장
  • merge(T entity): 분리된 엔티티의 상태를 현재 영속성 컨텍스트와 병합
  • remove(Object entity): 영속성 컨텍스트에서 엔티티를 제거
  • flush(): 영속성 컨텍스트의 변경 사항을 데이터베이스에 즉시 반영
  • clear(): 영속성 컨텍스트를 비운다.
  • close(): EntityManager를 닫는다.

JPA가 어떻게 영속화를 해줄까?

  • Entity: 나 영속화되고 싶은 객체/영속화가 된 객체

    • @Entity 어노테이션을 클래스 위에 달아두면,
    • EntityContext(영속화가 될/된 객체 공간)에 들어가고 싶어!라는 말!
  • EntityManager:

    • persist(): EntityContext에 Entity를 모아둠 + 테이블에 저장
      그렇다면... Entitycontext에 없는 객체를 테이블에 저장할 수 있을까❓NO!
      EntityContext에 추가되어야 테이블에 저장됨!!!
  • EntityContext:

  • ORM
    JPA의 최고 일꾼 EntityManager가 ORM을 해줌 어떻게? 영속성을 지키고자 하는 객체를 entityContext에 넣어놓고, entityManager가
    entityContext를 보고 오? 너 영속화 되길 원하는 구나 ! 내가 해줄게 해서 ORM을 실시!

    🔮정리

    자바와 DB사이(정확히는 자바 끄트머리)에 엔터티 컨텍스트가 있고, 둘 사이를 데이터가 왔다 갔다하려면, 엔터티 컨텍스트에 꼭 들렸다 와야한다.
    이를 담당하는 것이 EntityManager!

코드에 적용을 해봅시다!

@Component
public class RoomRepository {
    EntityManager entityManager;
    public RoomRepository(EntityManager entityManager) {
        this.entityManager = entityManager;
    }
    Map<Integer, Room> roomTable=new HashMap<>();
    int idx=0;
    public void saveRoom(Room room) {
        entityManager.persist(room);
    }
}
@Entity
public class Room {
    int id;
    private String type;
    int price;

    public String getType(){
        return type;
    }
}

⛔️ 오류가 발생함.. 무슨 오류일까?

위 사진을 보니.. @Id가 필요하다구 왜..?!?!

이유: DB에 들어가면 id가 생기겠지만, EntityContext내에서는 id가 없음-> @id: 룸들을 식별하기 위한 식별자
EntityManager가 EntityContext안을 보는데 똑같은 애들room들을 식별하기 위해 붙여주는 것
Id를 만들어서 식별해줘야겠다!

해결: @Id를 통해 식별자로 쓰면 돼!

다시 코드 적용

@Entity
public class Room {
	@Id //추가
    int id;
    private String type;
    int price;

    public String getType(){
        return type;
    }
}

⛔️ 다시 실행했더니 아래와 같이 transaction 오류가 뜨네

또 뭐가 문제야!!

  • transaction: 로직 단위 여러개-> service에서 처리

해결: @Transactional로 처리

코드에 다시 또 적용해보자!

RoomService
@Transactional
    public void saveRoom(Room room) {
        roomRepository.saveRoom(room);
    }

오 드디어 !!200 Ok가 떴지만, id가 자동으로 만들어지네 나는 id를 따로 생성한적이 없는데 어떻게 자동으로 만들어지는 걸까?!?🤔
-> entitymanager가 식별할 수 없어서,
entity context에 들어와야 저장 가능한데 id가 없음 그럼 아이디가 어떻게 만들지? db한테 가서 아직 저장하지 말고 잠깐만 해봐봐 id만들어볼게 rollback도 가능해!
id 만들었어 1가지고 와서 entity로 만드는 것
transaction을 왜 만들까? 잘못하면 db에서 만든 id를 rollback해야할 수 있음
db야 내가 관리하기 전이긴 한데 너가 id좀 만들어줬으면 좋겠어 저장은 하지말고 저장해보더니 1이던데? 이제 entity식별 가능하네 다시 db에 저장완료!

post=> getter가 있어야 함
나머지 =>setter가 있어야함?

드디어 끝! 😝

profile
@gari_guri

1개의 댓글

comment-user-thumbnail
2024년 7월 28일

굿굿 감동 포스팅이네료

답글 달기