일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 애자일
- API
- 자바
- 그리디
- 데이터베이스
- Java
- 애자일기법
- framework
- 애자일프로그래밍
- 그리디알고리즘
- 코드
- ES
- 엘라스틱서치
- 개발
- database
- Spring
- 코딩테스트
- 프레임워크
- Baekjoon
- 개발자
- cleancode
- 읽기쉬운코드
- 스프링
- 코딩
- Elasticsearch
- 알고리즘
- 백준
- 클린코드
- JPA
- spring boot
- Today
- Total
튼튼발자 개발 성장기🏋️
JPA를 사용하기 위한 설정과 동작 원리 본문
JPA를 사용하는 궁극적인 목적은 데이터베이스 관점의 테이블과 객체지향적 객체 사이에서 개발자가 해야할 일을 최소화하고 객체지향적으로 자유롭게 개발하기 위해서다. 따라서, JPA를 사용하려면 가장 먼저 객체를 매핑해야한다.
- 객체 매핑
CREATE TABLE MEMBER (
ID VARCHAR(255) NOT NULL,
NAME VARCHAR(255),
AGE INTEGER,
PRIMARY KEY (ID)
)
위 테이블은 아래와 같이 객체 매핑을 할 수 있다.
@getter
@setter
@Entity
@Table(name="MEMBER")
public class Member {
@id
private String id;
@Column(nullable = true, length = 255, unique = false)
private String username;
private String age;
}
- @getter와 @setter 어노테이션은 lombok을 이용한 것이다. 해당 내용을 알고 싶다면 #18 : Lombok을 참고하자.
- @Entity 어노테이션은 해당 클래스가 엔티티라고 정의하는 역할을 한다. 엔티티라는 이야기는 곧 데이터베이스 테이블과 매핑이 되는 클래스를 이야기 한다.
- @Table 어노테이션으로 name Element를 전달함으로써 해당 클래스가 매핑될 테이블 명을 정의한다. 만약, 정의하지 않는다면 class명으로 table을 찾고 없으면 table create문을 날리기도 한다.(이 부분은 설정에 따라 안하게 할 수도 있다.)
- @id 어노테이션은 해당 컬럼이 기본키(primary key)라고 정의한 것이다.
- @Column 어노테이션으로 세 가지의 Element를 주었다.
- nullable : NULL값 허용인지?
- length : max length
- unique : unique key 정의
- (그 외의 Element는 아래 내용 참고)
그 외에도 많은 어노테이션과 Element들이 있다. 이 것들을 전부 외울 수 없으니 이 docs를 옆에 끼고 개발하자. 해당 docs는 java 7버전이며, 본인이 개발 환경에 맞는 docs를 보는 것을 권장한다.
위에서 살펴본 어노테이션은 javax.persistence.* package에 포함되어있다. JPA는 persistence.xml을 사용해서 설정 정보를 관리한다. spring MVC와 spring Boot간 차이가 있을 수 있으니 함께 알아보자.
- Spring Boot
application.properties 파일에 다음과 같이 설정한다.
spring.datasource.url=jdbc:mysql://127.0.0.1:9999/TEST?serverTimezone=UTC
spring.datasource.username=dotori
spring.datasource.password=dotori
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=none
spring.jpa.generate-ddl=false
spring.jpa.show-sql=true
spring.jpa.database=mysql
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
- spring.jpa.hibernate.dll-auto : create, create-drop, update, validate, none을 정의할 수 있다.
- create : 테이블이 없을 때 자동 생성한다.
- create-drop : JPA 종료 시점에 기존에 있었던 테이블을 삭제한다.
- update : JPA에 의해 변경된 부분만 update.
- validate : 테이블과 객체가 잘 매핑되어 있는지 체크한다.
- none : 초기화 동작을 하지 않는다.
- spring.jpa.generate-dll : spring.jpa.hibernate.dll-auto옵션을 사용할 것인가? default가 false. JPA에 의한 데이터베이스 자동 초기화 기능을 사용하려면 true로 설정한다.
- spring.jpa.show-sql : JPA가 생성한 SQL문을 보여준다. (로깅인지 System out인지는 모르겠음)
- Spring MVC
#17 : H2 database 연동 준비를 참고하자.
본 게시글을 보면 알 수 있듯이 mysql과 H2 database를 사용하였다. JPA란?에서 언급했듯이 JPA는 특정한 데이터베이스에 종속되어 있는 기술이 아니기 때문에 쉽게 바꿀 수 있다. 그러나 데이터베이스 간에 다음과 같은 차이점을 가지고 있다. (그 외에도 차이점은 많을 것으로 보인다.)
- 데이터 타입 : 가변 문자 타입으로 mysql은 varchar, Oracle은 varchar2를 사용한다.
- 다른 함수명 : 문자열을 자르는 함수로 SQL 표준은 substring(), Oracle은 substr()을 사용한다.
- 페이징 처리 : mysql은 limit, Oracle은 rownum을 사용한다.
이 처럼 특정 데이터베이스만의 고유한 기능을 JPA에서 방언(Dialect)라 한다. 하이버네이트는 다양한 데이터베이스 방언을 제공한다. (이외에도 많은 방언 제공함)
- H2 : org.hibernate.dialect.H2Dialect
- Oracle 10g : org.hibernate.dialect.Oracle10gDialect
- mysql : org.hibernate.dialect.MySql5InnoDBDialect
우리는 애플리케이션 코드를 변경할 필요 없이 하이버네이트의 방언만 교체해주기만 하면 된다.
예를 들어 설정 정보를 보자.
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="packagesToScan"
value="com.maenginyoung.kakaopaycardtask.model" />
<property name="dataSource" ref="dataSource" />
<property name="jpaProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.use_sql_comments">true</prop>
<prop key="hibernate.id.new_generator_mappings">true</prop>
</props>
</property>
<property name="persistenceProvider">
<bean class="org.hibernate.jpa.HibernatePersistenceProvider"></bean>
</property>
</bean>
본격적으로 애플리케이션을 개발해보자. 다음 코드와 같이 JPA를 활용할 수 있다.
여기서 jpabook은 springMVC에서 persistence.xml에서 부여한 영속성 유닛(엔티티를 영구적으로 저장하는 환경) 이름을 이야기한다.
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpabook");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
try {
tx.begin();
logic(em);
tx.commit();
} catch(Exception ex) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
public static void logic(EmtityManager em) {
String id = "dotori";
Member member = new Member();
member.setMemberId(id);
member.setMemberName("도토리");
member.setAge(28);
// 등록
em.persist(member);
// INSERT INTO MEMBER (ID, NAME, AGE) VALUES ('DOTORI', '도토리', 28)
// 수정
member.setAge(19);
// UPDATE MEMBER SET AGE=19 WHERE ID='dotori'
// 한 건 조회
Member findMember = em.find(Member.class, id);
System.out.println("findMember=" + findMember.getMemberName() + ", age=" + findMember.getAge());
// SELECT * FROM MEMBER WHERE ID='dotori'
// 목록조회
List<member> members = em.createQuery("select m from Member m", Member.class).getResultList();
System.out.println("member size=" + members.size());
// SELECT M.ID, M.NAME, M.AGE FROM MEMVER M
// 삭제
em.remove(member);
// DELETE FROM MEMBER WHERE ID='dotori'
}
}
크게 3부분으로 엔티티 매니저 설정 -> 트랜잭션 관리 -> 비즈니스 로직 실행 순으로 이루어져있다.
- 엔티티 매니저 설정
- 앤티티 매니저 팩토리
- 데이터베이스 커넥션 풀 생성하는 매개체
- 생성 비용이 크다.
- 애플리케이션 전체에서 오직 한 번만 생성하여 공유 사용 권장
- JPA의 기능 대부분을 제공한다. (이를테면 CRUD)
- 데이터베이스와 통신하는 매개체
- 스레드간에 공유하거나 재사용 금지.
- 앤티티 매니저 팩토리
- 트랜잭션 관리
- 데이터 변경이 이루어지는 공간.
- 예외가 발생하면 롤백 실행
- 비즈니스 로직
- 수행해야 하는 로직을 수행.
- 엔티티 매니저를 사용하여 데이터베이스에 CRUD 수행.
목록조회 코드를 잘 보면 sql query가 들어가 있는 것을 알 수 있다. 우리는 엔티티 객체를 중심으로 개발(객체지향적으로)하고 데이터베이스에 대한 처리는 JPA에게 맡겨야 한다. 만약 테이블이 아닌 엔티티 객체를 대상으로 검색을 하게 된다면 모든 데이터를 애플리케이션으로 불러와서 엔티티 객체로 변경한 다음 그 객체에서 검색해야할 것이다. 사실상 붕가능에 가깝다고 보여진다.
JPA는 JPQL(Java Persistence Query Language)를 지원 함으로써 검색 조건이 포함된 SQL을 사용할 수 있다. JPQL은 SQL을 추상화한 객체지향 쿼리 언어라고 정의된다. SQL과 거의 유사하지만 다음과 같은 차이점을 보인다.
- JPQL은 엔티티 객체를 대상으뤄 query를 날린다. (클래스와 필드를 대상으로)
- SQL은 데이터베이스 테이블을 대상으로 query를 날린다.
상위 코드에서 보여진 select m from Member mㅇ; 비러 JPQL이다. 당연히 이 JPQL문의 Member는 Class Member를 이야기한다.
'API > JPA' 카테고리의 다른 글
Entity와 영속성 #2 (0) | 2020.11.29 |
---|---|
Entity와 영속성 #1 (0) | 2020.11.29 |
JPA란? (0) | 2020.09.24 |
DB 연동 시 유의할 점 #2 (0) | 2020.09.18 |
DB 연동 시 유의할 점 #1 (0) | 2020.09.18 |