LUMI_dev
2. Hello JPA 실습_ H2 데이터베이스 설치와 실행, JPA와 JPQL기본(EntityManagerFactory,@Id,@Table 등 ) 본문
2. Hello JPA 실습_ H2 데이터베이스 설치와 실행, JPA와 JPQL기본(EntityManagerFactory,@Id,@Table 등 )
luminous_dev 2025. 3. 8. 02:24
1. https://h2database.com/html/main.html
H2 Database Engine
H2 Database Engine Welcome to H2, the Java SQL database. The main features of H2 are: Very fast, open source, JDBC API Embedded and server modes; in-memory databases Browser based Console application Small footprint: around 2.5 MB jar file size Supp
h2database.com
가볍고 / 웹용 쿼리툴 제공 / MySQL, Oracle 데이터베이스 시뮬레이션 기능 / 시퀀스,AutoIncrement 기능 지원
2. 윈도우는 bat 파일
3. JDBC 설정 후 실행
4. 아래 부분에 쿼리 작성
maven
자바 라이브러리, 빌드 관리
라이브러리 자동 다운로드 및 의존성 관리
최근에는 그래들(Gradle)이 점점 유명
프로젝트 생성
자바 8이상
메이븐 설정
groupId : jpa-basic
artifactId: ex1-hello-jpa
version : 1.0.0
pom.xml 추가
<dependencies>
<!-- JPA 하이버네이트 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.3.10.Final</version>
</dependency>
<!-- H2 데이터베이스 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.199</version>
</dependency>
</dependencies>
resources > META-INF > persistence.xml 생성
<?xml version="1.0" encoding="UTF-8"?>
<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"> <!--jpa 이름은 뭘로 쓸 것인지-->
<properties>
<!-- 필수 속성 -->
<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"/><!--데이터베이스 방언 : SQL 표준을 지키지 않는 특정 DB만의 고유 기능-->
<!-- <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>-->
<!-- <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>-->
<!-- 옵션 -->
<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.hbm2ddl.auto" value="create" />-->
</properties>
</persistence-unit>
</persistence>
JPA 구동 방식
@Entity = JPA가 관리할 객체
@Id = 데이터베이스 PK와 매핑
Member.java
package hellojpa;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table("USER")
//@Table("USER") : 쿼리가 나가는 테이블 지정
public class Member {
@Id //PK가 뭔지 알려주는 것 Jakarta Persistence로 넣기
private Long id;
//만약 Column이 name이고 db가 username이면 @Column (name="username")으로 지정하면 됨
// 그럼 인서트 쿼리가 name -> username으로 열 이름이 나감
@Column (name="username")
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//@Entity를 넣어야 jpa가 관리하는 것을 알고 관리해야겠다고 생각함
JpaMain
package hellojpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");//persistenceUnitName을 넘기라고 함 - persistence.xml의 <persistence-unit name="hello"> 부분임
//이걸 연결하는 순간 데이터베이스랑 연결됨
//create-entity-manger 꺼내기 - 데이터에서 커넥션 하나 받은 것임
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Member member = new Member();
//PK값 입력
member.setId(1L);
member.setName("HelloA");
em.persist(member);
//커밋
tx.commit();
emf.close();
}
}
근데 위 코드는 하나가 문제가 생겼을 때 연쇄적으로 문제가 생길 수 있음 -> try -catch로 잡기
package hellojpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");//persistenceUnitName을 넘기라고 함 - persistence.xml의 <persistence-unit name="hello"> 부분임
//이걸 연결하는 순간 데이터베이스랑 연결됨
//create-entity-manger 꺼내기 - 데이터에서 커넥션 하나 받은 것임
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
Member member = new Member();
//PK값 입력
member.setId(1L);
member.setName("HelloA");
em.persist(member);
//커밋
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
아래 코드로 바꿀 수 있음
1. 조회 & 2. 삭제
package hellojpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");//persistenceUnitName을 넘기라고 함 - persistence.xml의 <persistence-unit name="hello"> 부분임
//이걸 연결하는 순간 데이터베이스랑 연결됨
//create-entity-manger 꺼내기 - 데이터에서 커넥션 하나 받은 것임
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
//엔티티 매니저를 자바 컬렉션으로 생각 : 내 객체를 대신 저장해주는 것
//Member.class 첫번째 파라메터는 엔티티 클래스 , PK가 뭐야? 1L
//1. 조회
Member findMember = em.find(Member.class,1L);
System.out.println("findMember.id="+findMember.getId());
System.out.println("findMember.name="+findMember.getName());
//2. 삭제 - 찾은 것을 삭제
em.remove(findMember);
//커밋
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
3. 수정
package hellojpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");//persistenceUnitName을 넘기라고 함 - persistence.xml의 <persistence-unit name="hello"> 부분임
//이걸 연결하는 순간 데이터베이스랑 연결됨
//create-entity-manger 꺼내기 - 데이터에서 커넥션 하나 받은 것임
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
//엔티티 매니저를 자바 컬렉션으로 생각 : 내 객체를 대신 저장해주는 것
//1. 조회
Member findMember = em.find(Member.class,1L);
//3. 수정
findMember.setName("Hello,jp");
//수정한 다음 방금 찾은 데이터는 em.persist(findMember)로 저장 안해도 됨
//자바 컬렉션과 비슷해서
//커밋
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
수정한 다음 방금 찾은 데이터는 em.persist(findMember)로 저장 안해도 됨
자바 컬렉션과 비슷해서
조회
Member findMember = em.find(Member.class,1L);
삭제
em.remove(findMember);
수정
findMember.setName("~"); → setName();은 Member에 세팅한 setter
객체의 값만 바뀌었는데 어떻게 DB까지 바뀌는 거지(업데이트 쿼리) ?
: 뭔가 바뀌었네 하면 JPA가 알아서 트랜잭션 커밋 전에 업데이트 쿼리를 만들어서 날리고 커밋
EntityMangerFactory
- 웹서버가 올라오는 시점에 딱 하나만 생성 됨 / DB 당 하나만 생성됨
- 하나만 생성해서 애플리케이션 전체에서 공유
EntityManger
- 고객의 요청이 들어올 때마다 계속 썼다가 em.close()로 버림
- ★ 쓰레드 간에 공유 x (사용하고 버림)
★ JPA의 모든 데이터 변경은 ' 트랜잭션 안에서 실행 '
(RDBMS는 데이터 변경 자체를 트랜잭션 안에서 실행하도록 되어있음)
가장 단순한 조회 방법 = EntityManager.find(); (ex. em.find(Member.class, 1L);)
만약 나이가 18살 이상인 회원을 모두 검색하고 싶다면? (조건) - ' JPQL을 써야 함 '
JPQL 간단 실습
1) 전체 회원 조회
JpaMain
package hellojpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");//persistenceUnitName을 넘기라고 함 - persistence.xml의 <persistence-unit name="hello"> 부분임
//이걸 연결하는 순간 데이터베이스랑 연결됨
//create-entity-manger 꺼내기 - 데이터에서 커넥션 하나 받은 것임
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
List<Member> result = em.createQuery("select m from Member as m",Member.class)
.getResultList();
//차이 : 테이블을 대상으로 짜지 않음 , 멤버 객체를 대상으로 쿼리를 하는 것
// 즉 select m은 m의 모든 것을 가져와!
for(Member member : result){
System.out.println("member.name="+member.getName());
}
//커밋
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
기존 쿼리는 그냥 모든 열들을 나열
jpql은 회원 엔티티를 검색한 것
페이징도 자동으로 됨 (Limit, offset)
List<Member> result = em.createQuery("select m from Member as m",Member.class)
.setFirstResult(5)
.setMaxResults(8)
.getResultList(); //페이징 기능 : 5번부터 8개 가져와 - Limit offset이 자동으로 됨
//차이 : 테이블을 대상으로 짜지 않음 , 멤버 객체를 대상으로 쿼리를 하는 것
// 즉 select m은 m의 모든 것을 가져와!
JPQL : 객체를 대상으로 하는 객체 지향 쿼리 언어
JPA를 사용하면 엔티티 객체를 중심으로 개발
문제는 검색 커리
검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색
모든 DB 데이터를 객체로 변환해서 검색하는 것 -> 불가능
필요한 데이터만 DB에서 불러오려면 검색 조건이 포함된 SQL이 필요
근데!! 검색 조건은 DB에서 가져오지 않는다. (DB에 종속적이면 안됨)
JPQL VS SQL
JPQL : 엔티티 객체를 대상으로 쿼리 (뭘 바꿔야할 때도 JPQL은 수정하지 않아도 된다는 장점이 있음)
SQL : 데이터베이스 테이블 대상 쿼리
'JPA > 자바 ORM 표준 JPA 프로그래밍 - 기본편' 카테고리의 다른 글
5. 연관관계 매핑 기초 (0) | 2025.04.02 |
---|---|
4. 엔티티 매핑 (0) | 2025.03.23 |
3. 영속성 관리(JPA 내부 구조)_영속성 컨텍스트 (0) | 2025.03.09 |
1. JPA란? (2) | 2025.03.03 |