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()
FlushModeType
FlushModeType.AUTO
FlushModeType.COMMIT
em.detach(entity)
em.clear()
em.close()