JPA

Walter Mitty·2023년 2월 8일
0

ORM (Object Relational Mapping) 개념

  • OOP 객체와 RDBMS Entity 를 매핑하려는 기술 개념이다.
    • 여기서 객체란 java면 java 객체, python이면 python 객체를 말한다.
    • 이 기술을 구현해놓은게 Hibernate framework 이다.
      • sql 한줄도 없이 알아서 매핑해준다.

        Hibernate는 EJB의 entitybean에서 시작되었다.
        entity와의 객체의 매핑, 그리고 깐깐하기 때문에 안쓰기시작.
        monolithic?한 서비스에서 작은 서비스로 바뀌면서 매핑이 복잡하지 않아져서 Hibernate를 쓰기 시작했다. 테이블을 5개 이상 join에서 2개 정도가 되니까 간단해짐 => Hinernate로 갈아탐

  • Java에서 쓰려고하니 불편해서 아예 내장시켜놓음
    • 이게 Spring용 JPA(JavaPersistenceAPI)
    • EJB entitybean -> Hibernate Framework -> Spring용 JavaPersistenceAPI(자바ORM기술에 대한 표준명세=Hibernate는 JPA의 구현체!)

참고, DB의 한행의 정보와 java 객체를 매핑할 때는 mybatis를 썼었다 + 그 때 sql구문을 활용했었음

JPA

  • java언어로 지원하는 ORM 기술에 대한 추상화된 표준 명세이다.

장점

  • DB 설계와 JAVA 설계를 한번에 처리할 수 있다.
    테이블이 변경되면 SQL 변경되고, DAO나 서비스, 화면까지 변경해야한다.
    반면 JPA를 이용하면 테이블 생성 부터 변경되는 DB 설계까지 JPA가 알아서 해준다.

단점

  • 객체지향 설계원칙(SOLID)가 반영되어있어야한다.
  • 기존의 SQL을 재사용 불가 및 SQL 튜닝등의 작업에 제약이 생길 수 있다.

엔티티: 인스턴스 혹은 레토드라고 불린다.
엔티티와

Entity 와 Entity 객체

  • Entity
    • DB 테이블의 행 하나를 의미한다.
    • 인스턴스 또는 레코드라고 불린다.
  • Entity 객체
    • Entity와 Java 객체로 영속성을 유지하는 객체
  • Entity 매니저
    • 엔티티객체들의 LifeCycle을 관리하는 역할을 한다
    • Entity들을 관리하는 Persistence Context라는 곳에 넣어두고 관리한다

  • 엔티티 매니저별로 Persistence Context를 갖는다
  • Entity Manager는 Entity Manager Factory가 만드는데 Create 했다가 Close, 또 Create , Close 하며 사용한다

  • 객체를 보관하려면, persist(), commit(), rollback(), close()등 복잡한 관리코드가 필요하다.
  • 엔티티 객체 만들어짐(New) -> 엔티티 매니저에의해 관리되기 위해 persist() 호출 -> 관리들어감(Managed: 관리되는 상태) -> 객체와 영속성을 유지하기위해 DB에서 자료를 검색해옴 -> 항상 똑같게 유지되기 위해 DB 테이블에 같은 행이 있나 찾아봄 -> 없으면 insert(), 바뀌면 update() ...
    -> remove()를 호출하면 Managed 상태에서 벗어난다(더이상 객체가 DB 테이블의 행과 영속성 유지 안함) -> delete sql 구문 호출됨 -> clear()나 close()는 entity manager가 닫혀 버린다 -> 안에 있던 객체들 다 밖으로 나와버림(detached) -> Datached에서 Managed로 다시 갈 수 있다(merge()로!)
    commit(), flush() 를 호출하면 managed된 것들이 다 ..음?

Hibernate부터 공부!

  • Hibernate lifecycle 공부 후 JPA lifecycle 공부해보기
  • 상태가 크게
    1) Transient State
    2)


Hibernate의 호출에 따라 상태가 달라진다.
1. 객체가 만들어짐
2. Transient State 로감
3. 메서드 호출에 따라서 Persistent State로 이동 (객체가 Hibernate Container로 들어가서 관리들어감 = 영속성 유지를 위해 행 추가)
4. 메서드 호출에 따라 Detached State(여기로 잠깐 나갔다가 merge()되어 다시 Hibernate Container로 들어옴) or Removed State로 가고
5. Garbage는 메모리 삭제..


Springboot JPA

  • JPA를 쓰기 편하게 만들어놓은 모듈
    • 위에서 언급한 persist(), find(), remove() 등 여러 메서드들을 담긴 인터페이스를 상속한 인터페이스를 만들면 사용가능하다
    • Proxy 개념의 이해
      • proxy: 대리자라는 뜻. proxy 패턴 기반으로 구현한 하위 클래스를...

Proxy Pattern

대리자 패턴

  • 객체지향 모델링 패턴 중 하나이다
    • 객체지향 모델링 중엔 AOP 도 있고 JPA도 있음
      CrudRespository<Entity 타입, id >의 메서드들
    • 두번째 인자인 id가 식별자의 자료형이되고 그거 key로 삼아서 entity타입을 객체로 관리하게 된다
  • save()
  • findById()
    • ⬆️(extends)
      ProductRepository 우리는 이것만 만들면 된다. Hibernate
      • ⬆️(extends) ---- ⬆️(extends) ↗️(extends)
        ProxyRepository ----MainPepository
        save(){} ------

왜 ProxyRepository를 쓸까???
EclipseLink

  • persist() {}
  • find() {}
  • merge() {}
    메서드 이름은 같아도 Hibernate와 EclipseLink의 메서드는 구현부가 다를수도 있다.
    그래서 이때는 EclipseLink에 적절한 Repository를 만들텐데, 그래도 앞에 ProxyRepo는 같게 유지해야한다.(바뀌지 않는다) 실제 구현체는 안쪽게 가려놓는다 -> 실제 구현체는 원하는 프레임워크로 구현하면된다.

스프링용 JPA를 만들려면 interface만 설계해놓으면 된다
main,proxy repo 만들고 main은 가려놓는다.


mybatis와 JPA의 차이점

  • O/R Mapper의 형태가 xml이나 interface여야 했다.


(보라색은 우리가 만들 필요없고 자동으로 만들어지는것!)

  • 이제 Mapper.xml이 필요없어짐
  • service에서 save()나 어떤 메서드를 호출하면 그때부터 동작 시작~
  • 대신 (Main)Repository가 필요하고, JPA(Hibernate/EclipseList)가 managed냐, detached냐에 따라서 작동 한다.

Springboot JPA 프로젝트 만들기


  • HicariCP도 있고
  • Spring ORM
  • Hibernate
    등등이 있는걸 확인할 수 있다.
  • oracle 용 jdbc (o jdbc) 라이브러리, DriverSpy 추가


CrudRepository를 상속받은 Repository 인터페이스 생성

  • CrudRepository에는 아래와 같은 메서드들이 기본으로 내장되어있다.
    • save
    • findById(ID id);
      • id 객체를 찾는다 = persistence를 유지하고있는 행
      • select문와 같은 효과
    • findAll
    • deleteById
    • delete(T entity)
      • hibernate Context에서 내보내는 역할
        • 영속성 유지를 위해 DB에서도 해당 행 지움 = delete 문과 같은 효과
A a = new A();
a.setA_1("one");
a.setA_2(1);
repository.save(a,1) //INSERT INTO A VALUES("one",1);

repository.findById("one");
이걸 호출할 때는 문자열(String) 타입으로 인자를 전달해줘야한다.
= PK 타입을 넣어줘야하는거...???아니면 무조건 String??
= SELECT * FROM A WHERE a_1 = 'one';


VO를 쪼개자

  1. DTO (메서드의 매개변수나 return으로 쓰임을 알림)
  2. Entity 클래스 (VO임을 알림)
    자동 매핑을 해주는 ObjectMapper 라이브러리 사용.

--

  • 소스코드 변경되면 자동구동이 된다.




#application.properties파일에 JPA설정
spring.jpa.database=oracle

# 시작시 테이블 삭제후 생성 : create
# 종료시 테이블 삭제 : create-drop
#테이블을 새로 생성 : create
#spring.jpa.hibernate.ddl-auto=create 
spring.jpa.hibernate.ddl-auto=update



#DB전용SQL문법 사용가능 : ROWNUM, DECODE(), 테이블생성시 SUBQUERY사용방법이 DB마다 다를 수 있다.
#spring.jpa.generate-ddl=true
spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect

spring.jpa.show-sql=true

#SQL을 자동줄바꿈해서 보여줌
spring.jpa.properties.hibernate.format_sql=true

#log
logging.level.org.hibernate=info

  • PK 제약 조건 붙음

dev tools 설치 이후 바뀌고 update하면 자동 구동된다.

0개의 댓글