diff --git "a/\354\225\210\354\236\254\353\257\274/2.4_JPA.md" "b/\354\225\210\354\236\254\353\257\274/2.4_JPA.md"
new file mode 100644
index 0000000..d30ab5c
--- /dev/null
+++ "b/\354\225\210\354\236\254\353\257\274/2.4_JPA.md"
@@ -0,0 +1,248 @@
+## 2.4 JPA
+
+### 기존 문제점
+
+근본적으로 RDB와 자바 오브젝트의 성격이 다르기 때문에 발생하는 많은 불일치를 코드로 일일이 다뤄줘야함
+
+- 텍스트 문장인 SQL을 직접 작성하고 파라미터를 바인딩하는 작업이 수고스러움
+- RDB 테이블에 자바오브젝트를 담기 위해서는 번거로운 작업이 필요함
+
+### ORM (Object-Relational Mapping)
+
+> 오브젝트를 RDB에 저장하기 적절한 형태로 변환해주거나, RDB에 저장되어있는 데이터를 오브젝트로 변환해주는 기술
+
+이러한 ORM 기술을 이용하여 자바 애플리케이션에서 데이터베이스와 상호작용하기 위한 자바 표준 스펙이 `JPA` 이다.
+
+
+### 4.1 EntityManagerFactory 등록
+
+`EntityManager` : JPA 영속성 컨텍스트를 관리하고, 데이터베이스와 상호작용을 담당하는 인터페이스
+이러한 `EntityManager`를 사용하기 위해서는 `EntityManagerFactory` 타입의 빈 등록이 필요하다.
+
+1. `LocalEntityManagerFactoryBean`
+
+- 프로바이더를 찾고 `META-INF/persistence.xml` 에 담긴 퍼시스턴스 유닛의 정보를 활용하여 `EntityManagerFactory` 를 생성
+- `DataSource` 빈을 사용할 수 없고, 바이트코드 위빙 기법도 적용할 수 없음
+- 이런 방법이 가능하다는 정도만 기억하고, 사용할 일이 드뭄
+
+2. `LocalContainerEntityManagerFacotryBean`
+
+- 스프링이 직접 제공하는 컨테이너 관리하는 `EntityManageFactory`를 생성해준다.
+- 이를 활용하면 JavaEE 서버에 배치하지 않아도 컨테이너에서 동작하는 JPA의 기능을 활용할 수 있다.
+
+```xml
+
+
+
+
+```
+
+스프링에 빈으로 등록된 `Datasource` 를 JPA 에서 사용할 수 있음
+
+```xml
+
+
+
+ springbook.learn.spring.jpa.Member
+
+
+
+
+
+```
+
+```java
+import jakarta.persistence.Column;
+import jakarta.persistence.Id;
+
+@Entity
+public class Member {
+ @Id
+ int id;
+
+ @Column(length = 100)
+ String name;
+
+ @Column(nullable = false)
+ double point;
+}
+```
+
+**`loadTimeWeaver`**
+JPA는 그래서 단순한 자바 코드로 만들어진 엔티티 클래스의 바이트코드를 직접 조작해서 확장된 기능을 추가하는 방식을 이용한다.
+이를 통해 엔티티 오브젝트 사 이에 지연된로딩이 가능하고, 엔티티 값의 변화를추적할수있으며,최적화와 그룹 페칭 등의 고급 기능을 적용할 수 있다.
+이렇게 이미 컴파일된 클래스 바이트 코드를 조작해서 새로운 기능을 추가하는 것을 바이트코드 항상 기법이라고 한다.
+
+1. 바이트 코드를 빌드중에 변경하는 방법
+
+- 바이트코드 컴파일러를 통해 매번 빌드 과정에 바이트 코드를 조작한다.
+
+2. 런타임 시에 바이트 코드를 메모리에 로딩하여 다이나믹하게 변경하는 방법
+
+- 런타 임 시에 클래스를 로딩하면서 기능을 추가하는 것을 로드타임 위빙(loadtimeweaving) 이라 하고,이런 기능을 가진 클래스를 로드타임 위버 (loadtimeweaver) 라고 부른다.
+
+**`트랜잭션 매니저`**
+스프링 JDBC는 자동 트랜잭션 모드를 갖고 있기 때문에 명시적으로 트랜잭션 관리를 해주지 않아도 된다.
+반면에 JPA는 반드시 트랜잭션 안에서 동작하도록 설계되어 있다.
+
+```xml
+
+
+
+
+```
+
+다음과 같이 트랜잭션 매니저를 등록하고 `@Transactional` 이나 트랜잭션 AOP를 이용하여 자동으로
+JPA 트랜잭션을 시작하고 커밋하도록 만들 수 있다.
+
+### 4.2 EntityManager 와 JpaTemplate
+
+1. JpaTemplate
+
+- 템플릿 방식으로 JPA 코드를 작성할 수 있게 해준다.
+
+```java
+List ms=templateDao.jpaTemplate.execute(new JpaCallback>(){
+public List doInJpa(EntityManager em)throws PersistenceException{
+ return em.createQuery("select m from Member m").getResultList();
+ }
+ });
+```
+
+`JpaTemplate`은 콜백 오브젝트 없이도 간단한 메소드를 이용해서 EntityManager 가 제공하는 대부분의 기능을 사용하게 해준다.
+다음은 `EntityManager`의 `persist()` 와 `find()` 에 각각 대응되는 JpaTemplate의 `persist()`와 `find()` 메소드를 이용해서 Member 오브젝트를 저장한 뒤에
+이를 조회히는 코드다.
+
+```java
+Member m=new Member(1,"Spring",8.9);
+ jpaTemplate.persist(m);
+ Member m2=templateDao.jpaTemplate.find(Member.class,1);
+```
+
+2. 애플리케이션 관리 EntityManager 와 @PersistenceUnit
+ 애플리케이션 코드가 관리하는 EntityManager 를 이용하는 것이기 때문에 JavaEE, JavaSE 모두 가능하다.
+
+```java
+em.getTransaction().begin();
+ Member m=new Member(1,"Spring",7.8);
+ em.persist(m);
+ Long count=em.createQuery("select count(m) from Member m",
+ Long.class).getSingleResult();
+ em.getTransaction().commit();
+```
+
+이렇게 EntityManager를 DAO 클래스에 DI 하는 방법은 두 가지가 있다.
+
+1. @Autowired, @Resource
+ EntityManagerFactory 타입의 빈을 일반적인 스프링 DI 방식으로 DAO로 가져와 사용한다.
+2. @PersistenceUnit
+ `@PersistenceUnit` 어노테이션을 이용하여 DI 받는데, 이는 스프링 프레임워크에 대한 의존도가 전혀 없는 코드이며, 따라서
+ 스프링이 아닌 JPA 환경에서도 사용할 수 있다는 장점이 있다.
+
+
+3. 컨테이너 관리 EntityManager 와 @PersistenceContext
+
+```java
+public class MemberDao {
+ @PersistenceContext
+ EntityManager em;
+
+ public void addMember(Member member) {
+ em.persist(member);
+ }
+}
+```
+
+잘 보면 factory가 아닌 EntityManager 자체를 주입받게 된다. em은 빈으로 등록되지 않는 객체인데 어떻게 가능할까?
+여기서 주입받는 EntityManager는 실제 EntityManager 가 아닌 일종의 프록시로 현재 진행중인 트랜잭션에 연결된다.
+이러한 방식은 스프링이 제공해주는 템플릿/콜백 방식을 시용하지 않아도 된다는 장점이 있다. 코드는 간결해지지만 스프링의 트랜잭션 경계설정과 동기화 기법을 적용한 것 과 같은 혜택은 그대로 얻을 수 있다.
+
+4. @PersistenceContext 와 확장된 퍼시스턴스 컨텍스트
+ 3번 방식과 동일하지만, 주입받는 EntityManager의 스코프가 다르다.
+ type이 PersistenceContextType.EXTENDED로 설정되어 트랜잭션 스코프 대신 확장된 스코프를 갖는 em을 주입받아
+ 상태유지 세션빈에 사용할 수 있는 EntityManager를 생성해준다.
+
+**JPA 예외 변환 AOP**
+JPA API를 이용하는 경우에도 JPA 예외를 스프링의 DataAccessException 예외로 전환시킬 수 있다.
+이를 위해서는 스프링의 AOP를 이용하면 된다.
+
+- @Repository
+ 해당 애노테이션이 붙은 클래스의 메소드는 예외 변한 기능이 부가될 빈으로 선정된다.
+- PersistenceExceptionTranslationPostProcessor
+ 예외 변환 기능을 가진 AOP 어드바이스를 적용해주는 후처리기가 필요하다.
+ `PersistenceExceptionTranslationPostProcessor`를 빈으로 등록해주기만 하면
+ JPA 예외가 스프링의 DataAccessException 으로 전환되어 서비스 계층으로 던져지게 된다.
+ 그러나 DataAccessException 의 다양한 서브클래스로 매핑돼서 던져지지는 않는다.
+
+## 2.5 하이버네이트 (Hibernate)
+
+### 5.1 SessionFactory 등록
+
+하이버네이트에는 JPA의 EntityManagerFactory 처럼 핵심 엔진 역할을 하는 SessionFactory가 있다.
+스프링에서는 이를 생성하는 두가지 팩토리 빈을 제공한다.
+
+**`LocalSessionFactoryBean`**
+빈으로 등록된 DataSource를 이용하여 스프링이 제공하는 트랜잭션 매니저와 연동할 수 있도록 설정된 `SessionFactory`를 만들어주는 빈이다.
+
+**`AnnotationSessionFactoryBean`**
+하이버네이트는 JPA처럼 엔티티 클래스에 애노테이션을 이용하는 방법을 제공한다.
+스프링에서는 XML 매핑파일 대신 애노테이션 매핑정보를 이용해서 SessionFactory를 생성해주는 AnnotationSessionFactoryBean을 제공한다.
+
+**`트랜잭션 매니저`**
+
+1. HibernateTransactionManager
+ 단일 DB를 사용하고 JTA를 이용할 필요가 없다면 간단히 HibernateTransactionManager 빈을 추가해주면 된다.
+2. JtaTransactionManager
+ 여러 개의 DB에 대한 작업을 하나의 트랜잭션으로 묶으려면 JTA를 통해서 서버가 제공하는 글로벌 트랜잭션 기능을 이용해야 한다.
+
+### 5.2 Session 과 HibernateTemplate
+
+Session은 하이벼네이트의 핵심 API다. Session은 SessionFactory로부터 만들어지며 보통 트랜잭션과 동일한 스코프를 갖고 있다.
+하이버네이트 DAO는 스프링이 관리하는 트랜잭션과 동기화된 Session을 가져와 사용한다. 스프링은 Session을 사용하는 두 가지 방법을 제공한다.
+**`HibernateTemplate`**
+HibernateTemplate을 이용하면 복잡한 설정 없이도 간단히 DAO를 테스트할 수 있다.
+```java
+public class MemberDao {
+ private HibernateTemplate hibernateTemplate;
+
+ @Autowired
+ public void setSessionFactory(SessionFactory sessionFactory) {
+ hibernateTemplate = new HibernateTemplate(sessionFactory);
+ }
+
+ public void addMember(Member member) {
+ hibernateTemplate.save(member);
+ }
+}
+```
+
+```java
+public class MemberDao extends HibernateDaoSupport {
+ public void addMember(Member member) {
+ getHibernateTemplate().save(member);
+ }
+}
+```
+
+
+**`SessionFactory.getCurrentSession()`**
+하이버네이트 SessionFactory의 getCurrentSession() 메소드는 현재 트랜잭션에 연결되어 있는 하이버네이트 Session을 돌려준다.
+이를 이용하면 스프링의 트랜잭션 매니저 또는 JTA의 트랜잭션에 연동되어 만들어지는 Session을 가져올 수 있다.
+```java
+public class MemberDao {
+ private SessionFactory sessionFactory;
+ public void setSessionFactory(SessionFactory sessionFactory) {
+ this.sessionFactory = sessionFactory;
+ }
+ public void addMember(Member member) {
+ sessionFactory.getCurrentSession().save(member);
+ }
+}
+```
+MemberDao에는 스프링 API가 전혀 등장하지 않는다. 펑범한 하이버네이트 API를 시용하는 코드로만 만들어졌다.
+그러면서도 스프링의 트랜잭션 통기화 기능과 완벽하게 연동돼서 동작하는 코드다.
\ No newline at end of file