본문 바로가기
개발/Spring

[Spring] 데이터 액세스 층의 설계와 구현

by devhooney 2022. 7. 20.
728x90

4.1 데이터 액세스 층과 스프링

- 데이터 액세스 층은 데이터 액세스 처리를 비즈니스 로직 층에서 분리하여 따로 만들어준 층

- 데이터 액세스 처리와 비즈니스 로직이 섞여있으면 유지보수가 어렵고, 코드 가독성이 떨어진다.

 

4.1.1 DAO 패턴이란?

- DAO 패턴은 데이터의 취득, 변경 등 데이터 액세스 처리를 DAO라고 하는 오브젝트로 분리하는 패턴

- 데이터 액세스 방식이 바뀌어도 DAO만 변경하면 된다.

https://velog.io/@dlwldbs/%EC%8A%A4%ED%94%84%EB%A7%81-JDBC

- DAO 클래스는 DB의 테이블별로 만든다.

 

4.1.2 자바의 데이터 액세스 기술과 스프링의 기능

- 자바의 데이터 액세스 기술

(1) JDBC

(2) 하이버네이트 & JPA 등 고성능 ORM 프레임워크

(3) MyBatis(iBATIS)

(4) 독자 개발한 프레임 워크 등

 

- 스프링은 여러 자바의 데이터 액세스 기슬과 연계 기능을 제공한다.

- 스프링과 연계함으로써 얻을 수 있는 장점

(1) 데이터 액세스 처리를 간결하게 기술할 수 있다.

(2) 스프링이 제공하는 범용적이고 체계적인 데이터 액세스 예외를 이용할 수 있다.

(3) 스프링 트랜잭션 기능을 이용할 수 있다.

 

4.1.3 범용 데이터 액세스 예외 처리

4.1.4 데이터 소스

- 데이터 액세스 기술의 종류와 상관없이 DB 접속은 필요하다.

- DB 접속을 관리해주는 것이 데이터 소스

https://velog.io/@dlwldbs/%EC%8A%A4%ED%94%84%EB%A7%81-JDBC

 

4.2 스프링 JDBC

- 스프링 JDBC는 JDBC를 래핑한 API를 제공하고 JDBC보다 간결하게 사용할 수 있는 스프링의 기능

 

4.2.1 JDBC를 직접 사용한 경우의 문제점

- 대량의 소스 코드를 기술

- 다양한 에러 원인을 파악하기 위한 코딩 필요

- DB 제품마다 에러코드가 다름 -> 코드의 일관성 유지 어려움

 

4.2.2 스프링 JDBC의 이용

- JDBC를 래핑한 API 제공 -> 소스 코드 단순화

- JDBC를 직접 사용할 때 발생하는 장황한 코드를 숨겨준다.

 

4.2.3 Template 클래스

- 가장 중요한 클래스

(1) JdbcTemplate

(2) NamedParameterTemplate

queryForObject : 하나의 결과 레코드 중에서 하나의 컬럼 값을 가져옴
queryForMap : 하나의 결과 레코드 정보를 Map 형태로 매핑
queryForList : 여러 개의 Map 형태의 결과 레코드 다룸
query : 여러 개의 레코드를 객체로 변환 후 처리
update : 데이터의 변경 (insert, update, delete)

 

4.2.4 SELECT 문(도메인으로 변환하지 않을 때)

queryForObject 메소드

- 취득 결과를 도메인으로 변환하지 않는 경우라는 것은, 레코드의 건수를 취득하거나 1 레코드 중에서 특정 컬럼만 취득하는 등의 단순하게 취득하는 경우

int count = jdbcTemplate.queryForObject(
	"SELECT COUNT(*) FROM PET", Integer.class);
    
int count2 = jdbcTemplate.queryForObject(
	"SELECT COUNT(*) FROM PET WHERE OWNER_NAME = ?", Integer.class, ownerNm);

- queryForObject 메소드의 리턴값은 Object지만, 제네릭에 따라서 2번째에 준 인수에서 지정한 형으로 리턴된다.

- String이나 Date도 가능하다.

 

queryForMap 메소드

- 컬럼 하나가 아니라 한 레코드의 값을 가져오는 경우 Map으로 가져온다.(컬럼 이름이 Key)

Map<String, Object> pet = jdbcTemplate.queryForMap(
	"SELECT * FROM PET WHERE PET_ID = ?", id);

- 만약 PET_NAME 컬럼의 값을 참조하고 싶다면

String petNm = (String)pet.get("PET_NAME");

 

queryForList 메소드

- 여러 레코드의 Map 데이터를 가져올 때 사용한다.

List<Map<String, Object>> petList = jdbcTemplate.queryForList(
	"SELECT * FROM PET WHERE OWNER_NAME = ?", ownerNm);

 

4.2.5 SELECT 문(도메인으로 변환할 때)

queryForObject 메소드

- 익명클래스를 사용했을 때

Pet pet = jdbcTemplate.queryForObject(
	"SELECT * FROM PET WHERE PET_ID = ?"
    , new RowMapper<Pet>() {
    	public Pet mapRow(ResultSet rs, int rowNum) throws SQLException {
            Pet p = new Pet();
            p.setPetId(rs.getInt("PET_ID");
            p.setPetName(rs.getString("PET_NAME");
            
            return p;
        }
    }
    , id);

- 익명클래스를 사용하지 않았을 때는 생략

 

query 메소드

- 여러 레코드를 가져올 때 사용한다.

List<Pet> petList = jdbcTemplate.query(
	"SELECT * FROM PET WHERE OWNER_NAME = ?"
    , new RowMapper<Pet>() {
    	 Pet p = new Pet();
         p.setPetId(rs.getInt("PET_ID");
         p.setPetName(rs.getString("PET_NAME");
    }
)

 

4.2.6 INSERT/UPDATE/DELETE 문

- 데이터 삽입, 수정, 삭제 시 사용

// insert
jdbcTemplate.update(
	"INSERT INTO PET (PET_ID, PET_NAME) VALUES (?, ?)"
    , pet.getPetId(), pet.getPetName()
);

// update
jdbcTemplate.update(
	"UPDATE PET SET PET_NAME = ? WHERE PET_ID = ?"
    ,pet.getPetName(), pet.getPetId()
);

// delete
jdbcTemplate.update("DELETE FROM PET WHERE PET_ID = ?", pet.getPetId());

- jdbcTemplate.update 시 리턴 값은 int로 갱신된 레코드 수

 

4.2.7 NamedParameterJdbcTemplate

- ?(플레이스홀더)를 사용할 경우 파라미터 순서가 중요하다. 숫자가 많아지면 분명히 한번 씩 틀린다.

- 이럴 때 NamedParameterJdbcTemplate를 사용한다.

namedParameterJdbcTemplate.update(
	"INSERT INTO PET(PET_ID, PET_NAME) VALUES (:PET_ID, :PET_NAME)"
    ,new MapSqlParameterSource()
    	.addValue("PET_ID", pet.getPetId())
        .addValue("PET_NAME", pet.getPetName())
);

 

4.3 Spring Data JPA

- 따로 JPA 카테고리가 있으니 참고!

https://devhooney.tistory.com/33

 

[JPA] 기본 영속성 관리 - 내부 동작 방식

김영한님의 자바 ORM 표준 JPA 프로그래밍 - 기본편 정리 1. JPA에서 가장 중요한 2가지 - 객체와 관계형 데이터메이스 매핑하기 - 영속성 컨텍스트 2. 엔티티 매니저 팩토리와 엔티티 매니저 - EntityMa

devhooney.tistory.com

 

728x90