✅ 자바 어플리케이션에서 관계형 데이터베이스를 다루기 위한 자바 영속성 프레임워크
JPA(Java Persistence API)는 [[ORM]]을 위해 Java에서 지원하는 표준 API다 (인터페이스, 추상클래스의 집함)
JPA, [[JDBC]] 둘 다 데이터베이스와 상호 작용하는 데 사용되는 두 가지 다른 기술이지만 그 차이는 Persistence(영속성)에 있다.
[!info] JPA & JDBC
JDBC: 직접 SQL 쿼리를 작성하여 데이터베이스와 통신, 개발자가 연결, 처리 모두 관리
JPA: 객체 지향 프로그래밍과 관계형 데이터베이스 간의 매핑을 제공하여, 개발자는 객체를 사용하여 데이터 관리(SQL 쿼리를 직접 작성하지 않아도 됩니다.)
Persistence(영속성) : 어플리케이션 종료 후에도 객체가 유지된다
대용량 데이터베이스 솔루션이 없는 기업, 복잡한 수식이 필요없는 곳에서 주로 쓰임
최근 NoSQL이 부각되고 있음 - 쿼리 메소드 select(), where() 등 / 네이티브 Query
저장소가 달라도 일관된 데이터 처리 가능
JPA를 위한 저장소(JpaRepository) 관련기능 제공
Repository <- CrudRepository <- PagingAndSortingRepository(페이징처리, 정렬지원) <-JpaRepository
EntityManager : Entity 저장관리, 사용자마다 하나씩 사용(공유x)
EntityManagerFactory : EntityManager 생성
=> 이 클래스를 통해 사용자는 직접 SQL문을 작성하여 DB에 명령을 내리지 않고, EntityManager로 작업
YAMLConfig.java : YAML 파일에서 속성을 읽어들이기 위한 Spring Boot의 설정 클래스
아키텍쳐 설계에 관심이 있다면 YAMLConfig 부분의 학습을 깊게 하는 것도 좋음.
1. 외부 설정: 설정을 소스 코드에 직접 넣지 않고 외부 파일(YAML 또는 프로퍼티)에서 가져와 사용할 수 있습니다.
2. 환경별 설정: 다양한 환경에서 실행할 때 필요한 설정을 간편하게 변경할 수 있습니다.
3. 빈 클래스 활용: 설정 클래스는 Spring 빈으로 등록되어, 다른 부분에서 사용하기 편리합니다.
4. 유연한 관리: 여러 설정을 하나의 클래스로 묶어서 사용함으로써, 설정을 효과적으로 관리할 수 있습니다.
5. 동적인 설정 변경: 애플리케이션 실행 중에 설정 파일을 변경하면, 설정이 동적으로 업데이트됩니다.
장점 : 데이터를 넣어두는 엔티티의 영속성이 있음. 1차로 데이터가 있을 때는 엔티티에서 가져오고, 없을 때 DB에 접속하여 보다 빠르고 효과적인 데이터 사용이 가능해진다.
@SpringBootApplication
public class JpaStep1Application implements CommandLineRunner {
@Autowired
EntityManagerFactory emf;
@Autowired
YAMLConfig config;
public static void main(String[] args) {
// SpringApplication.run(JpaStep1Application.class, args);
SpringApplication app = new SpringApplication(JpaStep1Application.class);
app.setWebApplicationType(WebApplicationType.NONE);
app.run(args);
}
@Override
public void run(String... args) throws Exception {
System.out.println("config = " + config);
System.out.println("emp"+emf);
EntityManager em = emf.createEntityManager();
System.out.println("em = " + em);
EntityManager em2 = emf.createEntityManager();
System.out.println("em2 = " + em2);
EntityTransaction tx = em.getTransaction();
//Member 엔티티 생성 : 테이블 생성 및 컬럼명 설정
Member member = new Member();
member.setMem_id("kiwi");
member.setMem_name("123");
member.setMem_pw("키위");
tx.begin(); //트랜잭션 시작
/* {1.저장하기} - entity persit(엔티티-여기선 member) insert*/ em.persist(member); //member엔티티를 매니저인 em에 영속화하는 작업(저장)
// tx.commit();//트랜잭션 종료(DB 반영)
/* 1.결과확인 : Hibernate: insert into member240123 (mem_name,mem_pw,mem_id) values (?,?,?) */
/* {2.수정하기} */
/* 비번 수정 시 PersistenceContext가 변경 감지 -> update 실행
* hibernate는 하나가 수정되어도 DB에 다시 접근하는 것이 아니라
* 영속성 안의 정보(엔티티)에서 찾아 효과적으로 빠르게 찾도록 업데이트문이 만들어져있다. */
member.setMem_pw("111"); //바뀌는 정보를 감지 -> 수정처리
tx.commit();//트랜잭션 종료(DB 반영)
/* 2.결과확인 : 첫 생성때, 수정 때의 값 모두 나온다.
Hibernate: update member240123 set mem_name=?,mem_pw=? where mem_id=? Hibernate: insert into member240123 (mem_name,mem_pw,mem_id) values (?,?,?) */
/* {3.조회하기} */
/* em에 데이터 영속성이 있는 값이면 DB조회하지 않고, 조회가능(장점)
* 없다면? 그 때 DB에서 조회를 하도록 처리되어 빠르고 효율적이다. */
Member member1 = em.find(Member.class, "kiwi");
//데이터 영속성이 있는 것이기 때문에 DB 안감
System.out.println("find(member1 `kiwi`) = " + member1);
//find(member1 `kiwi`) = Member{mem_id='kiwi', mem_pw='111', mem_name='123'}
Member member2 = em.find(Member.class, "apple");
//Hibernate: select m1_0.mem_id,m1_0.mem_name,m1_0.mem_pw from member240123 m1_0 where m1_0.mem_id=?
System.out.println("member = " + member);
//member = Member{mem_id='kiwi', mem_pw='111', mem_name='123'}
System.out.println("member1 = " + member1);
//member1 = Member{mem_id='kiwi', mem_pw='111', mem_name='123'}
System.out.println("find(member2 `apple`)= " + member2);
//find(member2 `apple`)= null
/* {4.삭제하기} */
tx.begin();
em.remove(member);
System.out.println("remove(member) = " + member);
tx.commit();
}
}