JPA 알아보기

떡ol·2023년 4월 11일
0
post-thumbnail

1. JPA란

JPA는 자바 진영에서 ORM(Object-Relational Mapping) 기술 표준으로 사용되는 인터페이스의 모음이다. 그 말은 즉, 실제적으로 구현된것이 아니라 구현된 클래스와 매핑을 해주기 위해 사용되는 프레임워크이다. JPA를 구현한 대표적인 오픈소스로는 Hibernate가 있다.

2. 장단점

장점

  • SQL문이 아닌 Method를 통해 DB를 조작할 수 있어, 개발자는 객체 모델을 이용하여 비즈니스 로직을 구성하는데만 집중할 수 있음.
    (내부적으로는 쿼리를 생성하여 DB를 조작함. 하지만 개발자가 이를 신경 쓰지 않아도됨)
  • Query와 같이 필요한 선언문, 할당 등의 부수적인 코드가 줄어들어, 각종 객체에 대한 코드를 별도로 작성하여 코드의 가독성을 높임
  • 객체지향적인 코드 작성이 가능하다. 오직 객체지향적 접근만 고려하면 되기때문에 생산성 증가
    매핑하는 정보가 Class로 명시 되었기 때문에 ERD를 보는 의존도를 낮출 수 있고 유지보수 및 리팩토링에 유리 예를들어 기존 방식에서 MySQL 데이터베이스를 사용하다가 PostgreSQL로 변환한다고 가정해보면, 새로 쿼리를 짜야하는 경우가 생김. 이런 경우에 ORM을 사용한다면 쿼리를 수정할 필요가 없음

단점

  • 프로젝트의 규모가 크고 복잡하여 설계가 잘못된 경우, 속도 저하 및 일관성을 무너뜨리는 문제점이 생길 수 있음
  • 복잡하고 무거운 Query는 속도를 위해 별도의 튜닝이 필요하기 때문에 결국 SQL문을 써야할 수도 있음
  • 학습비용이 비쌈

정리
JPA는 반복적인 CRUD SQL을 처리해준다. JPA는 매핑된 관계를 이용해서 SQL을 생성하고 실행하는데, 개발자는 어떤 SQL이 실행될지 생각만하면 되고, 예측도 쉽게 할 수 있다. 추가적으로 JPA는 네이티브 SQL이란 기능을 제공해주는데 관계 매핑이 어렵거나 성능에 대한 이슈가 우려되는 경우 SQL을 직접 작성하여 사용할 수 있다.

3. JPA 초기 셋팅

Depedency 추가

	implementation 'org.hibernate:hibernate-entitymanager'
	runtimeOnly 'com.h2database:h2:2.1.214' // 메인이되는 db넣으시면 됩니다.

resource/META-INF/persistence.xml
해당경로에 파일을 만들어 작성합니다.

<persistence version="2.2"
           xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
  <persistence-unit name="hello">
    	<!--예제를위해 class테그로 임포트하였습니다. boot는 알아서 됩니다.-->
      <class>com.jpaexample.Member</class>
      <class>com.jpaexample.Team</class>
      <properties>
          <!-- 필수 속성 : jdbc할때처럼 하면 됩니다.-->
          <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
          <property name="javax.persistence.jdbc.user" value="sa"/>
          <property name="javax.persistence.jdbc.password" value=""/>
          <property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/test"/>
          <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>

          <!-- 옵션 : hibernate에 옵션입니다. 아래 3개는 console에 보이게 합니다.-->
          <property name="hibernate.show_sql" value="true"/>
          <property name="hibernate.format_sql" value="true"/>
          <property name="hibernate.use_sql_comments" value="true"/>
          <!--<property name="hibernate.jdbc.batch_size" value="10"/>-->
          <!--<property name="hibernate.hbm2ddl.auto" value="create" />-->
      </properties>
  </persistence-unit>
</persistence>

또는 사용하시는 프레임워크가 Spring boot라면, application.properties(yml)에도 등록 가능합니다.

spring.datasource.url=jdbc:h2:tcp://localhost/~/test
spring.datasource.username=sa
spring.datasource.password=

spring.jpa.hibernate.ddl-auto=create
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true

4. CRUD 테스트해보기

  • 만약 테스트 용도로 이용하신다면 해당 주석을 풀어주시면 자동으로 TABLE이 생성됩니다. create말고도 다양한 기능이 있습니다.
    <property name="hibernate.hbm2ddl.auto" value="create" />

사용할 객체를 생성해야합니다.
@Entity가 핵심입니다 객체에 이 Annotation을 선언해야 JPA 객체가 되는겁니다.

@Getter
@Setter
@Entity
public class Member {

  public Member() {
  }
  @Id // RDBMS의 PK선언입니다.
  @GeneratedValue(strategy = GenerationType.AUTO) // MYSQL AUTO_INCREMENT, ORACLE SEQ와 같은 기능입니다.
  private Long id;
  @Column(name = "USER_NAME") // DB의 COLUMN값이 다르면 직접 선언 가능합니다.
  private String name;
}

위에 내용에서 @GeneratedValue(strategy = GenerationType.AUTO)만 봐도 JPA의 장점이 눈에 들어옵니다. 이 Annotation을 선언한것만으로도 내 DB의 종류(ORACLE, MySQL)와 상관없이 알아서 쿼리문을 생성하고 매핑해 줍니다.


JPA를 사용하기위해서는 Faxtory, Manager, Transaction을 만들어 사용해야합니다.
EntityManagerFactory의 "hello"는 persistense.xml에 persistence-unit value입니다.

      EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
      EntityManager em = emf.createEntityManager();
      EntityTransaction tx = em.getTransaction();
      tx.begin();

      try {
			
          Member member = new Member();
          member.setId(1L);
          member.setName("HelloA");

          //insert 등록
          em.persist(member);

          //select 찾기
          Member findMember = em.find(Member.class, 1L);
          System.out.println(findMember.getId());
          System.out.println(findMember.getName());

          //셀렉트문 여러개로 불러오기
          List<Member> resultList = em.createQuery("select m from Member as m", Member.class) //결국 SQL문을 써야할때가 있습니다.
                  .setFirstResult(0)
                  .setMaxResults(10)
                  .getResultList();
          resultList.forEach(member -> System.out.println(member.getName()));

          //delete 삭제
          Member findMember = em.find(Member.class, 1L);
          em.remove(findMember);

          //update 업데이트 setName만 해도 진행된다.
          Member findMember = em.find(Member.class, 1L);
          findMember.setName("HelloB");

          tx.commit(); // 커밋을해야 db에 들어가집니다.
      } catch (Exception e){
          tx.rollback(); // 에러나면 롤백해야됩니다.
      }finally {
          em.close();
      }
      emf.close(); // 당연히 닫아야겠죠?

4.결론

이 처럼 개발자는 더이상 복잡한 sql문을 작성하느라 시간을 낭비할 필요가 없게 됩니다.
다음에는 영속성과 객체지향 단, 양방향 등 연관관계를 알아보겠습니다.



참고자료들___
(참고) JPA란

profile
하이

0개의 댓글