DataSource
Connection
Statement
PreparedStatement
ResultSet
RowMapper
모든 쿼리 수행에 대해 템플릿 코드 패턴
Jdbc API 예시 코드
Connection conn = null;
PreparedStatement pstm = null;
ResultSet rs = null;
try {
// 1. Connection
conn = dataSource.getConnection();
conn.setTransactionIsolation(TRANSACTION_SERIALIZABLE);
conn.setAutoCommit(false);
log.info("{} {}", conn, pstm);
// 2. Statement
pstm = conn.prepareStatement("SELECT * FROM SPRING_USER");
// 3. Execute Statement
rs = pstm.executeQuery();
// 4. ResultSet Row Mapping
while (rs.next()) {
int userId = rs.getInt(USER_TABLE.getColumn(0));
String userName = rs.getString(USER_TABLE.getColumn(1));
User user = new User(userId, userName);
users.add(user);
}
} catch (SQLException e) {
log.error(e.getMessage());
throw e;
} finally {
// 5. Close Connection
closeConnection(conn, pstm, rs);
}
Jdbc Connection close 예시 코드
private void closeConnection(
Connection conn, PreparedStatement pstm, ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (pstm != null) {
pstm.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
JdbcTemplate 예시 코드
JdbcTemplateUserRepository.java
오직 쿼리와 쿼리 파라미터만 신경쓰면 된다.
ResultSet에 대한 rowMapping도 설정해줘야 한다.
객체는 참조를 사용해서 다른 객체와 연관관계를 가지고 참조에 접근해서 연관된 객체를 조회한다.
테이블은 외래 키를 사용해서 다른 테이블과 연관관계를 가지고 조인을 사용해서 연관된 테이블을 조회한다.
SQL을 직접 다루면 처음 실행하는 SQL에 따라 객체 그래프를 어디까지 탐색할 수 있는지 정해진다.
- 이는 굉장히 데이터베이스에 의존적이고, 비지니스 개발에 제약사항이 된다.

Java Persistence API
Java 진영의 ORM 기술에 대한 API 표준 명세
Object Relational Mapping
객체와 관계형 데이터베이스를 매핑
// INSERT
entityManager.persist(member);
// SELECT
Member member = entityManager.find(Member.class, 1001L);
// UPDATE
member.setName("guest");
// DELETE
member.remove(member);



EntityManager 예시 코드
import org.hibernate.Transaction;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public abstract class JpaMainTemplate {
protected EntityManagerFactory emf;
protected EntityManager em;
protected EntityTransaction tx;
public void run() {
run("test");
}
public void run(String persistenceUnitName) {
emf = Persistence.createEntityManagerFactory(persistenceUnitName);
em = emf.createEntityManager();
tx = em.getTransaction();
tx.begin();
try {
logic(em);
System.out.println("===== BEFORE COMMIT =====");
tx.commit();
System.out.println("===== AFTER COMMIT =====");
} catch (Exception e) {
System.out.println("===== BEFORE ROLLBACK =====");
tx.rollback();
e.printStackTrace();
System.out.println("===== AFTER ROLLBACK =====");
} finally {
em.close();
}
emf.close();
}
abstract public void logic(EntityManager em);
}
Entity를 영구 저장하는 환경
비영속)영속)준영속)삭제)Persistence Context에서 삭제 요청된 상태

Persitence Context는 Entity를 식별자 값(@Id)으로 구분한다.Persistence Context에 저장된 Entity들은 flush시점에 데이터베이스에 저장된다.


@DynamicUpdate , @DynamicInsert![]()
Flush영속성 컨텍스트의 변경 내용을 데이터 베이스에 동기화하는 것
em.flush() tx.commit()em.createQuery("${JPQL}").getResultList()FlushModeTypeFlushModeType.AUTOFlushModeType.COMMITem.detach(entity)em.clear()em.close()