본문 바로가기

Spring

7. JDBC, SQL Mapper, ORM

Youtube [10분 테코톡] 🧘‍♂️코즈의 JDBC, SQLMAPPER, ORM,⏰ 아마찌의 ORM vs SQL Mapper vs JDBC을 참고하여 정리하였습니다.


Persistence

JDBC, SQL Mapper, ORM은 데이터들이 사라지지 않도록 하는 Persistence(영속성)와 관련이 있다.

프로그램이 실행된 후 객체지향의 데이터들은 객체 생성 후 RAM에 저장되어 있다가 프로그램이 종료 되면서 날라가게 된다. 온라인을 활용한 비즈니스가 증가하면서 데이터의 영속성은 반드시 필요했고 데이터베이스를 활용해 데이터들이 지워지지 않도록 하였다.

 

Layerd Archhitecure 좌) 90년대 이전 계층 구조 우) 90년대 이후 계층 구조

출처 : https://herbertograca.com/2017/08/03/layered-architecture/

 

클라우드 환경의 발달로 단순했던 Layered Architecture는 역할과 관심사를 세분화하여 위와 같은 계층으로 나눴다. 브라우저를 통해 사용자의 요청이 들어와 Domain Model에서 가공을 통해서, 위의 3가지의 기술(JDBC,SQLMapper,ORM/ SQL Mapper와 ORM은 JDBC를 구현한 persistence 프레임워크이다.)이 포함된 Persistence layer를 거쳐 데이터에 영속성을 부여한다.

 

JDBC, SQLMapper, ORM

1. JDBC

Java에서 DB에 접근하기 위해 만든 API가 JDBC(Java Database Connectivity)이다.

JDBC는 여러 DB의 Driver를 제공하기 때문에 사용자는 어떠한 데이터베이스를 쓰든 동일한 접근 로직으로 어디든 접속할 수 있다. 

 

동작순서

  1. DriverManager로 Connection 인스턴스를 받아옴(Connection 인스턴스는 접근해야할 DB 정보가 저장되어 있다.)
    • DriverManager.getConnection()
  2. Statement를 이용하여 쿼리 실행
  3. DB로 부터 데이터 GET
    • ResultSet에 데이터를 받아와 조회하게 되는데 사용자는 리스트를 생성해서 해당하는 엔티티를 직접 넣어야 한다. 

단점

  • 직접 작성해야하는 코드가 많음
    •  DB 연결(연결, 종료), 예외처리, statement 준비, 실행, 반복문, ResultSet  등
  • 따라서 중복 코드 발생
  • 커넥션을 관리해 주어야 함(에러가 발생하지 않게 하기 위해 쓰고 반환해줘야 함)
    • ※ 커넥션 풀 : 웹 컨테이너(WAS)가 실행되면서 DB와 미리 connection을 연결해 놓은 객체들을 pool에 저장해두었다가 클라이언트의 요청이 오면 connection을 빌려주고, 처리가 끝나면 다시 connection을 반납받아 pool에 저장하는 방식을 말한다.
  • DB별로 적절한 예외처리를 해 주어야 함

→ 오타로 인한 오류가능성이 있어 이러한 불편함을 해결하기 위해 SQL Mapper가 등장한다.

 

2.SQL Mapper

 

SQL Mapper는개발자가 직접 작성한 SQL 문과 객체의 필드를  매핑하여 데이터를 객체화 해주는 프레임 워크이다.

이전의 Java JDBC의 경우 각 클래스마다 쿼리문을 작성하였지만, Mapper 방식을 사용한다면 중복되는 코드들을 줄일 수 있다. 하지만 SQL Mapper 또한 개발자가 직접 다뤄야 하기 때문에 불편한 점이 있다. DBMS에 따라서 문법이 다르기 때문에 DBMS에 종속적이다.

 

SQL Mapper에는 Mybatis와 Spring JDBC가 있다. 서로는 Java의 JDBC에 관한 문제점을 서로 다르게 해석하여 기술을 만들었다. 

2-1 Spring JDBC(JdbcTemplate)

동작 스프링 개발자
연결 파라미터 정의   O
연결 오픈 O  
SQL 문 지정   O
파라미터 선언과 파라미터 값 제공   O
Statement 준비와 실행 O  
결과를 반복하는 루프 설정 O  
각 이터레이션에 대한 작업 수행   O
모든 예외처리 O  
트랜잭션 제어 O  
연결, statement, resultSet 닫기 O  

스프링 JDBC는 Java의 JDBC의 불편한 점을 추상화하여 개발자가 처리하지 않도록 하였다.

Data Access Layer

JDBC Interface에서 DataSource를 통해 커넥션을 위한 설정들(드라이버 이름, url, 유저 이름, 비밀번호 등)을 관리한다.

@Configuration
public class AppCtx {

	@Bean(destroyMethod = "close")
	public DataSource dataSource() {
		DataSource ds = new DataSource();
		ds.setDriverClassName("com.mysql.jdbc.Driver");
		ds.setUrl("jdbc:mysql://localhost/spring5fs?characterEncoding=utf8");
		ds.setUsername("spring5");
		ds.setPassword("spring5");
		ds.setInitialSize(2);
		ds.setMaxActive(10);
		ds.setTestWhileIdle(true);
		ds.setMinEvictableIdleTimeMillis(60000 * 3);
		ds.setTimeBetweenEvictionRunsMillis(10 * 1000);
		return ds;
	}

	@Bean
	public MemberDao memberDao() {
		return new MemberDao(dataSource());
	}
}
  • RowMapper를 재활용 할 수 있음
    • ※RowMapper : RowMapper 인터페이스의 mapRow() 메서드로 ResultSet에서 항 행의 데이터를 읽어와 자바 객체로 변환하는 mapper기능을 구현, 따라서 사용자가 원하는 형태의 결과값을 반환할 수 있다.
  • JDBC에서 반복되는 작업들을 개발자가 하지 않아도 됨

 

 

 

2-2 MyBatis

MyBatis역시 JDBC를 단순화하였고 SQL을 xml 파일에 작성해놓고 코드와 SQL을 분리하여 사용하는 방식이다. 따라서 소스코드에 SQL을 작성하지 않기 때문에 코드의 복잡성을 줄일 수 있다.

 

xml 예시

https://mybatis.org/mybatis-3/ko/sqlmap-xml.html

http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="org.apache.ibatis.submitted.rounding.Mapper">
	<resultMap type="org.apache.ibatis.submitted.rounding.User" id="usermap">
		<id column="id" property="id"/>
		<result column="name" property="name"/>
		<result column="funkyNumber" property="funkyNumber"/>
		<result column="roundingMode" property="roundingMode"/>
	</resultMap>

	<select id="getUser" resultMap="usermap">
		select * from users
	</select>
	<insert id="insert">
	    insert into users (id, name, funkyNumber, roundingMode) values (
	    	#{id}, #{name}, #{funkyNumber}, #{roundingMode}
	    )
	</insert>

	<resultMap type="org.apache.ibatis.submitted.rounding.User" id="usermap2">
		<id column="id" property="id"/>
		<result column="name" property="name"/>
		<result column="funkyNumber" property="funkyNumber"/>
		<result column="roundingMode" property="roundingMode" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
	</resultMap>
	<select id="getUser2" resultMap="usermap2">
		select * from users2
	</select>
	<insert id="insert2">
	    insert into users2 (id, name, funkyNumber, roundingMode) values (
	    	#{id}, #{name}, #{funkyNumber}, #{roundingMode, typeHandler=org.apache.ibatis.type.EnumTypeHandler}
	    )
	</insert>

</mapper>

개발자는 Mapper Interface와 MappingFile만 구현하면 된다.

 

문제점

  • 여전히 존재하는 비슷한 SQL문
  • 테이블의 필드가 추가되거나 삭제 될 경우 이와 관련된 모든 DAO의 SQL문, 객체의 필드 등을 수정해야함
  • SQL과 JDBC API를 분리 했다고 하지만 논리적으로는 강한 의존 관계이 있다.

→ 여전히 SQL에 의존적인 개발이 많아서 많은 시간이 소요된다.

 

3. ORM(Object Relational Mapper)

객체지향적으로 구현된 모델을 관계형 DB 모델로 맞추기에는 너무 힘들다. 그래서 나온 것이 ORM이다.

// CASE 1
// 변경 전
public class Student{
  private int studentId;
  private String name;
}

// 변경 후
public class Student{
  private int studentId;
  private String name;
  private int score;
}

//CASE 2
public class Student{
  private int studentId;
  private String name;
  private School school;
}

IF)

  • 만약 객체의 필드가 추가된다면?

        → 모든 SQL문에 변경 필요(삽입, 수정, 삭제)

  • 객체를 가진 필드가 생겨난다면?

         → School 의 Primary key를 student에게  Foreign key로 하여 연관관계를 가지도록 한다.

 

 

관계형 데이터베이스와 객체지향은 설계 원칙이 다르기 때문에 사용 방법과 표현방식에 차이가 있을 수 밖에 없다.

 

ORM 목적 : 객체와 DB 테이블을 매핑하여 데이터를 객체화하자.

 

장점

  • ORM은 객체간의 관계를 바탕으로 SQL을 자동으로 생성하고 메서드를 통해 조작한다.
    • ex) SELECT * FROM user userRepository.findAll();
  • SQL을 직접 작성할 필요없이 자바 코드만으로 SQL을 사용할 수 있다. → 유지보수가 쉬움
  • 필드가 추가되거나 삭제될 시에 해당 엔티티만 수정하면 된다.

단점

  • 프로젝트가 복잡해질수록 어려움이 있다.
  • 복잡한 SQL의 경우 개발자가 직접 추가하여야 한다.(JPQL)

Ex)

  • JPA(자바 진영의 인터페이스)
    • LazyLoading(필요할 때 가져오자)
    • Dirty Checking(바뀐 내용만 파악)
    • Caching
  • Hibernate(JPA의 구현체)

 

  • Spring-Data-JPA(스프링에서 JPA를 한단계 추상화 시킨 것, Repository 인터페이스가 이것에 해당)
    • CrudRepository
    • JPARepository

 

 


 

참고하면 좋은 사이트

 

RowMapper에 대해!

앞에서 말하길 queryForObject의 반환형은 데이터형만 가능하다고 했다.하지만 말도 안된다.그럼 "SELECT \* FROM USER" 구문으로 User 객체 자체를 반환받는건 포기해야 하는걸까?그걸 위해서 필요한 것이

velog.io

 

 

GitHub - WeareSoft/tech-interview: 🙍 tech interview

:loudspeaker:🙍 tech interview. Contribute to WeareSoft/tech-interview development by creating an account on GitHub.

github.com

 

 

JDBC, SQLMapper, ORM 비교

최근 유튜브 우아한Tech라는 채널에서 우아한테크캠프, 우아한테크코스 크루분들이 여러 기술을 공부하시면서 내용을 잘 정리한 영상을 올려주셔서 매우 유익하게 보고있습니다. 기존에 헷갈리

sdesigner.tistory.com