일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 생성자
- 객체지향 언어
- Java
- GitHub
- Git
- 포맷은 최후의 보루
- 인스턴스
- #스파르타내일배움캠프
- KPT
- TiL_1st_0419
- Github_token
- 스파르타내일배움캠프TIL
- Java의 이점
- 해우소
- 메서드
- 변수의 다양성
- 클래스
- JVM
- 회고록
- Diary 해우소
- #내일배움캠프
- 감사기록
- diary
- 스레드
- Token
- #스파르타내일배움캠프TIL
- 스파르타내일배움캠프
- 내일배움캠프
- 성장기록
- static
- Today
- Total
몬그로이
데이터베이스Driver >> JDBCTemplate 본문
데이터 베이스 Driver
역할: 애플리케이션과 데이터베이스 간의 통신을 중개
동작 방식 - Driver Manager 를 통하여 진행
1. 연결초기화 (Connection)
- Driver Manager : getConnection()
- 요청 수신 : 애플리케이션이 드라이버에 연결 요청한 것을 받음
- 연결 설정 : 서버에 로그인 후 필요 설정 수행하여 연결 완료 (네트워크 정보, 인증 자격 증명 등 사용)
2. SQL 전송 및 실행 (Statement)
- (준비된 sql문)
- Driver Manager : connection.statement(sql) 를 통해 statement 로 만들기
- SQL 명령 변환 : 애플리케이션에서 보낸 SQL 명령을 DB가 이해하는 형태로 변환
- Driver Manager : statement.execute() 으로 실행시키기
- 명령 처리 : 변환한 명령을 DB로 전송 (이 때 DB 는 쿼리를 처리하고 요구 받은 데이터를 검색하거나 변환시킴)
- (참고 : preparestatement.excute() 도 가능)
- (참고) CREATE/INSERT/UPDATE/DELETE 인 경우해당 -> SELECT인 경우는 executeQuery()
더보기** INSERT 문의 경우 집어넣기만 하면 되니까 execute() 로 끝나지만
SELECT문의 경우는 꺼내서 보여줘야 하기때문에 executeQuery() 를 통해 객체를 꺼내는 메서드를 써야함
두 경우 모두 반복문이 필요할 수는 있음 - 여러 개 저장할때, 여러개 출력할 때 - 상황에 따라 사용
3. 결과 처리 (Resultset)
- 결과 수신 : DB에서 받은 결과물을 애플리케이션이 해석할 수 있는 형태로 변환 (필요한 경우 반복 : next())
- 결과 전달 : 변환한 결과물을 애플리케이션에 전달
- Driver Manager : 필요한 경우 next() 또는 getXxx() 사용
4. 연결 종료
- Driver Manager : close()
- 연결 해제 : 위 작업들이 끝난 후 DB 서버와의 연결 종료, 시스템 초기화
String insertSql = "INSERT INTO USERS (username) VALUES ('kim')";
try (PreparedStatement statement = connection.prepareStatement(insertSql)) {
statement.execute();
} // execute () 에 의해 SQL 문을 "실행" 함 -> 따라서 executeUpdate() 가 오지 않아도 SQL 문에 따라서 작동함(INSERT됨)
prepareStatement 사용
* prepareStatement 는 Statement 를 상속하고 있는 Interface
Statement 는 executeQuery() 나 executeUpdate() 를 실행하는 시점에 파라미터로 sql 문을 전달하는데 반해
PreparedStatement 는 일단 sql 문을 parse 하여 결과를 캐싱 하므로 이후 같은 sql문을 수행할 때는 나머지 3단계만 수행하면 된
"캐싱"은 SQL 문이 처음 실행될 때 수행되는 구문 분석(parsing) 단계의 결과를 저장해두고, 이후 동일한 SQL 문이 실행될 때 구문 분석 과정을 생략하고 바로 나머지 단계들만 수행하는 것
Statement 의 4단계
구문분석 (parse) : 문법 검사, 의미 검사, 권한 검사, 실행 계획
치환 (bind) : 값을 입력 받아 변수 선언
실행 (execute) : 디스크에서 블록을 찾아 버퍼에 복사
인출 (patch) : 블록에서 원하는 데이터 추출
statement 방식 1
String selectSql = "SELECT * FROM USERS";
try (Statement statement = connection.createStatement()) {
var rs = statement.executeQuery(selectSql); //이하 생략
}
preparedStatement 방식 1
String selectSql = "SELECT * FROM USERS";
try (PreparedStatement statement = connection.prepareStatement(selectSql)) {
var rs = statement.executeQuery(); //이하 생략
}
statement 방식 2
String sqldb = "SELECT name, age FROM TABLE WHERE userID = " + userID;
Statement stmt = conn.createdateStatement();
ResultSet rst = stmt.executeQuery(sqlstr);
preparedStatement 방식 2
String sqldb = "SELECT name, age FROM TABLE WHERE userID = ? ";
PreparedStatement stmt = conn.prepareStatement(sqldb);
pstmt.setInt(1, userID);
ResultSet rst = pstmt.executeQuery();
JDBC 로 직접 SQL 작성시 문제점을 해결하기 위해
"Persistence Framework 등장"
JDBC 로 직접 SQL 작성시 문제점
- SQL 쿼리 요청시 중복 코드 발생
- DB별 예외에 대한 구분 없이 Checked Exception (SQL Exception) 처리
- Connection, Statement 등.. 자원 관리를 따로 해줘야함 (자원 해제 안해주면 메모리 꽉차서 서버 다운)
1. SQL Mapper 인 JDBC Template 와 MyBatis
JDBC Template
SQL을 직접 작성하여 사용
코드의 반복을 줄이고 예외처리를 일관되게 하는 등의 편리성이 추가된 것
SQL Mapper의 기본적인 형태
주로 개발자가 SQL 을 제어하고, 반복 작업을 줄이는 데 중점을 둠
MyBatis
더 진보된 SQL Mapper 프레임워크
SQL 을 XML 파일이나 어노테이션을 사용하여 매핑함
복잡한 객체(Object) 매핑도 지원하며
SQL 쿼리를 코드 외부로 분리하여 관리에 용이성이 높음
어노테이션 방식으로 사용할 경우
@Select("SELECT * FROM users WHERE id = #{id}") User selectUserById(int id);
매퍼방식으로 사용할 경우 (xml 파일 내부에 적어둔다)
<select id="selectUserById" resultType="com.example.User"> SELECT * FROM users WHERE id = #{id} </select>
어노테이션 예
@Mapper
@Select @Insert @Update @Delete
@Result @Results
@Param
2. ORM : JPA, Hibernate
ORM (Object-Relational Mapping)
객체지향 프로그래밍 언어의 객체와 관계형 데이터베이스의 테이블 간의 매핑을 자동화하는 기술
SQL을 직접 작성하지 않고, 객체지향 방식으로 데이터 처리 가능
SQL에 종속되지 않으므로 DB를 교체할 때 코드 변경이 최소화 됨
지연로딩을 통해 성틍 최적화
JPA (Java Persistence API)
자바 EE의 일부로, 인터페이스와 애노테이션을 정의하여 ORM 을 표준화 함(표준 API)
Entity 클래스에 어노테이션을 사용하여 DB Table 과의 매핑 설정
SQL을 직접 작성하지 않고, 객체를 사용하여 DB작업 수행
JPA는 인터페이스이므로, 구현체(Hibernate, EclipseLink) 를 사용하여 동작
JPA 의 주요 인터페이스
Entity Manager : Entity 관리, DB 연산 수행 주체
EntityTransaction: 트랜젝션 관리
Query: 쿼리 생성 및 실행
Hibernate
JPA 구현체 중 하나 JPA 표준을 구현하면서도 추가적 기능을 제공하여 더욱 강력한 ORM 기능을 제공함
JPA 에 없는 기능 : 캐싱, 페이징, 고급 조회 방법
객체 지향 쿼리 언어인 HQL(Hibernate Query Language) 를 사용하여
SQL 과 유사하지만 객체를 대상으로 쿼리를 작성할 수 있음
*또는 JPQL(Java Persistence Query Language)을 사용하기도 하며, 복잡한 경우 @Query 어노테이션을 이용함
어노테이션 뿐만아니라 XML 을 사용한 매핑도 지원
Hibernate 의 주요 특징
엔티티 클래스에 따라 자동 스키마 생성
1차 캐시와 2차 캐시를 사용하여 성능 최적화
복잡한 객체 관계를 쉽게 매핑, 관리 가능
.
@Query 어노테이션 이용
일반인 SQL 사용 방식
@Query("SELECT u FROM User u WHERE u.username = :username")
네이티브 SQL 사용시 (주로 더 복잡한 Query를 작성할 경우 nativeQuery 를 사용하며, 끝에 표기함)
@Query(value = "SELECT * FROM users WHERE username = :username", nativeQuery = true)
JdbcTemplate 도입
JDBC 를 추상화한 Spring의 클래
DataSource 설정과 함께 JdbcTemplate 를 사용하여 JDBC 코드 간소화
효과 : 자동 DB 연결 구성, DataAccessException 으로 예외 체계 통일
RowMapper 와 함께 사용 (RowMapper 는 ResultSet의 각 행을 객체로 매핑하는 역할을 함)
예 : User 라는 클래스 정의 -> 테이블 생성되어 여러 user 가 테이블에 들어 있을 때
RowMapper<User> 를 상속한 RowMapper에 구현하여 사용하면
User 테이블에 있는 각 Row를 User 라는 객체로 매핑할 수 있도록 해줌
구현 예시
public class UserRowMapper implements RowMapper<User> {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
return user;
}
}
인터페이스 RowMapper
public interface RowMapper<T> {
T mapRow(ResultSet rs, int rowNum) throws SQLException;
}
사용 예시
@Autowired
private JdbcTemplate jdbcTemplate;
public List<User> getAllUsers() {
String sql = "SELECT id, username FROM USERS";
return jdbcTemplate.query(sql, new UserRowMapper()); //SQL 문을 바로 넣어도 됨
}
JdbcTemplate .method() 사용 : Query 문 타입
template.execute : CREATE
template .update : INSERT, UPDATE, DELETE
template .queryForObject : SELECT
*DB에 접근하는 것이므로 Repository 에 JdbcTemplate 을 DI 후 메서드를 정의해 놓을 때 사용함
JDBCTemplate 사용과 Hibernate 의 @Query 사용의 차이
1. 목적과 방식
JDBCTemplate
직접 SQL 쿼리를 작성하여 데이터베이스에 접근
SQL 쿼리를 문자열로 작성, 매개변수를 전달하여 데이터베이스와 상호작용
보통 데이터베이스와 직접적인 접근을 필요로 하는 경우에 사용
Hibernate 의 @Query
JPQL(Java Persistence Query Language)이나 네이티브 SQL 쿼리를 사용하여 데이터베이스에 접근할 수 있도록 함
주로 엔티티 클래스의 메서드에 적용
2. 안정성
JDBCTemplate
SQL 쿼리를 문자열로 작성하므로 컴파일 시점에 문법적 오류를 잡기 어려움
Hibernate 의 @Query
JPQL을 사용할 경우 객체와 필드명을 기반으로 쿼리를 작성하므로 타입 안정성이 높음
컴파일 시점에 잘못된 필드명이나 타입 오류 등을 잡을 수 있음
3. ORM 기능
JDBCTemplate
순수 JDBC 코드를 사용하기 때문에 객체-관계 매핑 기능이 제한적
객체를 데이터베이스에 저장하거나 조회할 때는 직접 매핑해야
Hibernate 의 @Query
객체와 데이터베이스 간의 매핑을 자동으로 처리
4. 사용 및 관리
JDBCTemplate
JDBC의 다양한 기능을 활용할 수 있으나
데이터베이스 트랜잭션 관리나 예외 처리 등을 개발자가 직접 해야함
Hibernate 의 @Query
Hibernate는 세션 관리와 영속성 컨텍스트를 통해 객체 상태를 추적하고 관리해주므로
트랜잭션 관리나 캐싱, 지연 로딩 등의 기능을 개발자가 직접 구현할 필요가 없음
'Organizing Docs > Java Docs' 카테고리의 다른 글
페이징 (0) | 2024.06.28 |
---|---|
MyBatis (0) | 2024.06.27 |
자바의 정석 6. 객체지향 프로그래밍1 (1) | 2024.06.19 |
자바의 정석 5. 배열(Array) (0) | 2024.06.18 |
쓰기 지연 저장소와 지연 로딩 (0) | 2024.06.04 |