JPA 심화 - ORM의 탄생 배경

ayboori·2023년 8월 2일
0

Spring

목록 보기
12/24

ORM의 탄생 배경

ORM 은 갑자기 나타난것이 아니라 점차 발전해온 DB 연동 기술이론이다.

1. JDBC > ( QueryMapper > ORM(JPA)) 는 포함/개선 관계입니다.
2. 이전 기술의 문제점을 개선하기 위해서 탄생하였기 때문에 이전 기술의 기능을 포함한다.

JDBC

  • Java와 DB를 연결시키기 위해 만들어진 기술
  • JPA도 이 기술을 사용하여 구현되어 있다.
  • 사용하지 않을 때 자원을 해제 close() 해야 한다!

Docker

도커 설정

docker run -p 5432:5432 -e POSTGRES_PASSWORD=pass -e POSTGRES_USER=_사용자이름_ -e POSTGRES_DB=messenger --name postgres_boot -d postgres

 docker exec -i -t postgres_boot bash # container docker의 bash(cmd 같은 것) 실행
su - postgres # 현재 로그인 계정 변경
psql --username _사용자이름_ --dbname _db이름_
\list (데이터 베이스 조회)
\dt (테이블 조회)

JDBC Driver

여러타입의 DB 와 연결할 수 있는 기능을 제공한다.

  • JDBC Driver Manager 는 런타임 시점에
    • Connection(연결) 을 생성하여 쿼리를 요청할 수 있는 상태를 만들어주고
    • Statement(상태) 를 생성하여 쿼리를 요청하게 해주고
    • ResultSet(결과셋) 을 생성해 쿼리 결과를 받아올 수 있게 해줍니다.

close() 대신 아래와 같이 사용 가능 (try 문).. 맞을걸

  try {
        String creatSql = "CREATE TABLE ACCOUNT (id SERIAL PRIMARY KEY, username varchar(255), password varchar(255))";
        try (PreparedStatement statement = connection.prepareStatement(creatSql)) {
          statement.execute();
        }

JDBC DAO

Connection / Statement / ResultSet 일일히 수행하지 않는다

  @Test
  @DisplayName("JDBC DAO 삽입/조회 실습")
  void jdbcDAOInsertSelectTest() throws SQLException {
    // given
    AccountDAO accountDAO = new AccountDAO();

    // when
    var id = accountDAO.insertAccount(new AccountVO("new user", "new password"));

    // then
    var account = accountDAO.selectAccount(id);
    assert account.getUsername().equals("new user");
  }
}
  • AccountDAO 클래스
    Connection / Statement / ResultSet, 쿼리, CRUD 기능 메소드를 각각 선언한다.
    CRUD 시행 시 DriverManager을 사용하지 않을 수도 있다

  • AccountVO
    id, username, password 등 사용자의 정보를 담는다

++) assert 디버깅 용도, false 리턴 시에만 에러 발생

getGeneratedKeys()

가지고 있는 key 값들을 전부 리턴한다

  • executeQuery()
    수행 시 결과 값이 ResultSet 형식이다.
    rs(ResultSet 변수).next() 수행 시 결과 값을 하나씩 꺼내온다.

  • 연결정보 파라미터 정의

  • Connection 생성

  • 실행할 SQL 문 지정

  • 파라미터 선언과 파라미터 값 제공

  • Statement 준비와 실행

  • 결과 담기

  • Connection, Statement, ResultSet 닫기

  • Connection, Statement, ResultSet 예외 처리


QueryMapper

- JDBC로 직접 SQL 작성 시 자원 관리, 예외 처리 등의 문제를 개선하기 위해 등장함
- Persistence Framework 는 2가지가 있다.
	- **SQL Mapper** : JDBC Template, MyBatis 👈 요게 먼저나옴

- ORM : JPA, Hibernate

JDBC Template

  • 의존성 추가

  • 테스트 코드

// 이외 의존성 클래스는 아래 깃헙링크 참조
// https://github.com/thesun4sky/jpastudy/tree/work-tea-1day/src/test/java/me/whitebear/jpastudy/jdbc

@JdbcTest // Jdbc Slice Test
@AutoConfigureTestDatabase(replace = Replace.NONE) // 테스트용 DB 쓰지 않도록
@Rollback(value = false) // Transactional 에 있는 테스트 변경은 기본적으론 롤백 하도록 되어있다.
public class JDBCTemplateTest {

  @Autowired
  private JdbcTemplate jdbcTemplate;

  @Test
  @DisplayName("SQL Mapper - JDBC Template 실습")
  void sqlMapper_JDBCTemplateTest() {
    // given
    var accountTemplateDAO = new AccountTemplateDAO(jdbcTemplate);

    // when
    var id = accountTemplateDAO.insertAccount(new AccountVO("new user2", "new password2"));

    // then
    var account = accountTemplateDAO.selectAccount(id);
    assert account.getUsername().equals("new user2");
  }
}
  • DAO
    JdbcTemplate 주입 받아옴 / 쿼리, CRUD 기능 메소드를 각각 선언한다.
    Connection, Statement, ResultSet 반복적 처리 대신 해줌

  • VO

  • MapRow
    JDBC의 인터페이스인 ResultSet에서 원하는 객체로 타입을 변환하는 역할
    row 단위로 ResultSet의 row를 매핑하기 위해 JdbcTemplate에서 사용하는 인터페이스

간단히 말해서 그냥 Row를 객체에 매핑한다고 생각하면 된다!

참조1
참조2

MyBatis

의존성 추가


- 반복적인 JDBC 프로그래밍을 단순화
- SQL 쿼리들을 XML 파일에 작성하여 코드와 SQL 을 분리!
- 😵‍💫 But, 결국 SQL을 직접 작성하는것은 피곤하다…(DB 기능에 종속적) 😫
- 😵‍💫 But, 테이블마다 비슷한 CRUD 반복, DB타입 및 테이블에 종속적이다.

DB 연결 정보를 configuration 내에 따로 명시해야 한다
쿼리문은 xml 파일 내에 따로 응답값까지 지정하여 결과를 VO에 mapping
Config 내에서는 xml 파일을 읽어서 bean에 지정한다.

// 이외 의존성 클래스는 아래 깃헙링크 참조
// https://github.com/thesun4sky/jpastudy/tree/work-tea-1day/src/test/java/me/whitebear/jpastudy/mybatis

@SpringBootTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Import(DBConfiguration.class)
public class MyBatisTest {

  // Mapper 클래스를 받으려면 mapper.xml 빌드 해야하고, 그러려면 main 으로 옮겨서 해야함...
  @Autowired
  AccountMapper accountMapper;

  @Autowired
  AccountMapperV2 accountMapperV2;

// xml 파일로 MyBatis 구현, 분리
  @Test
  @DisplayName("SQL Mapper - MyBatis 실습")
  void sqlMapper_MyBatisTest() {
    // given

    // when
    accountMapper.insertAccount(new AccountMyBatisVO("new user3", "new password3"));
    var account = accountMapper.selectAccount(1);

    // then
    assert !account.getUsername().isEmpty();
  }

// 호출 형태는 동일하지만, 쿼리를 @Select(~~~)로 작성한다.
// @Mapper을 붙이면 Bean 등록 과정 생략 가능
  @Test
  @DisplayName("SQL Mapper - MyBatis V2 실습")
  void sqlMapper_MyBatisV2Test() {
    // given

    // when
    accountMapperV2.insertAccount(new AccountMyBatisVO("new user4", "new password4"));
    var account = accountMapperV2.selectAccount(1);

    // then
    assert !account.getUsername().isEmpty();
  }
}
profile
프로 개발자가 되기 위해 뚜벅뚜벅.. 뚜벅초

0개의 댓글