자바 진영에서 제공하는 ORM 기술이다. 말그대로 객체와 데이터베이스의 릴레이션을 맵핑해주며 개발자가 직접 쿼리를 작성해 데이터를 조작하지 않고 JPA가 대신 쿼리를 생성한다.
자바와 관계형 데이터베이스를 이용해 개발을 한다고 가정해보자(대부분 이 경우 일것이다.) 이 경우 자바의 객체 지향과 관계형 모델의 패러다임 불일치가 발생한다. 그로인해 객체 모델을 관계형 모델로 또 관계형 모델을 객체 모델로 변환하는 번거로운 과정이 필요하고 중복코드를 양산하며 유지보수를 힘들게하는 원인이 되었다.
기존의 복잡한 처리 과정을 거치지 않고 단 몇줄의 코드로 CRUD를 수행할 수 있다.
기존에는 객체의 명세를 변경하면 관련된 SQL을 전부 찾아 변경해야 했지만 JPA가 모두 처리해준다.
아래는 스프링없이 순수 java와 jpa만으로 동작하는 코드이며 Member 객체를 하나 생성한 뒤 저장하는 예제이다.
public static void main(String[] args) {
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("Member1");
em.persist(member);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
코드를 분석해보면, Persistence.createEntityManagerFactory에 persistence-unit name을 넘겨서 persistence.xml에서 설정한 정보를 불러와 EntityMangerFactory를 생성하고 있다.
그 후 생성한 EntityMangerFactory를 통해 EntityManger를 생성하고 em.persist(member)를 통해 member를 저장했다.
코드를 자세히 보면 EntityTransaction을 통해 트랜잭션을 걸고 있는데 이는 Jpa의 모든 데이터 변경은 무조건 트랜잭션 안에서 동작해야하기 때문이다.
그래서 아래와 같은 양식이 꼭 필 수 로 들어가게 된다.
EntityTransaction tx = em.getTransaction();
tx.begin();
//...
tx.commit();
Maven이 아니라 Gradle을 사용하는 경우 엔티티 클래스가 자동으로 인식되지 않는다.
따로 persistence.xml에 <class></clase>로 엔티티를 추가해주어야한다.
EntityManagerFactory는 DB당 하나만 생성해서 애플리케이션 전체에서 공유해야한다.
EnitityManager는 DB의 커넥션 하나를 물고 있다고 생각하면 된다.
그렇기 때문에 client에서 요청할때 마다 생성하고 트랜잭션이 끝나면 무조건 close를 해주어야한다.
쓰레드간에 공유도 하면 안된다.
JPA에서 제공하는 SQL을 추상화한 객체 지향 쿼리 언어
id를 통한 단건 조회를 제외하고 JPA에서는 JPQL을 이용해 조회를 해야한다.
List result = em.createQuery("select m FROM Member as m")
.setFirstResult(5)
.setMaxResults(8)
.getResultList();
코드를 보면 익히 알던 SQL 쿼리와 유사하면서도 조금 다르다.
여기서 Member는 테이블이 아니라 객체를 의미하는데 이는 JPQL은 엔티티 객체를 대상으로 쿼리를 만들기 때문이다.
데이터베이스 테이블을 대상으로 쿼리를 만드는 SQL과 대조적이라 할 수 있다.
객체를 대상으로 쿼리를 만듬으로서 특정 DB에 종속되지 않는다.
그래서 DB를 변경한다고 해도 JPQL 변경없이 방언만 변경하면 해당 DB에 맞는 쿼리가 만들어진다.