기록/Spring framework

스프링으로JDBC Template을 이용한 DB연동 (JDBC API vs JDBC Template).2022-02-08

최동훈1 2022. 2. 18. 12:55

●들어가기전.

스프링으로 JDBC Template을 공부하면서, 일반 JDBC API를 썼을때와 어떤 차이점이 존재하는지, 유념하면서 공부해야지만이 JDBC Template을 완벽히 이해할 수 있다. 그러므로 내가 JDBC API를 공부할떄의 포스팅을 한번 복습하고 넘어와야 된다. 또, 진도를 나가며 계속 이 두 기술의 차이를 생각하면서 공부하면, 쉽게 머리에 들어온다. 나도 계속 비교하면서 공부할것이다.

 

스프링을 이용할려면, 아래의 자바 개념들을 숙지해야 한다.

람다식이란 한줄로 설명하자면, 람다식 그 자체로 익명 객체이고, 메서드이름과 반환값을 생략하여 메서드를 간단히 나나탠 것이다.

스트림은 DB에 접속해 데이터를 가공하는 SELECT 문과 비슷하게, 데이터의 가공처리를 초기단계-중간단계-마지막 단계에 걸쳐서 해주는 클래스이다.

지네릭 타입은,  오토박싱,언박싱을 자동으로 해주고, 클래스 형 불일치를 런타임이 아닌 컴파일 단계에서 잡아내기 위해서 고안된 타입이다.

 

기본적인 DB연동의 구조인, 연결/인증- 문장실행 -결과집합 은 스프링으로 하나 JDBC API로 하나 다 똑같다. 다만, 스프링의 JDBCtemplate을 이용하면 유지보수성이 증가하고 코드가 간결하다.

예로 들자면,

 

JDBC API 를 사용했을때의 연결/인증 -문장실행 -결과집합 과정.

Class.forName(oracle.jdbc.driver.OracleDriver)

Connection con=DriverManager.getConnection(url,user,PW);

Statement st=con.createStatement();

Resultset rs=st.executeQuery();

rs.next();

rs.close();

 

이렇게 복잡하다. 또 이런 복잡한 연결/인증 과정을 JDBC API에서는  CRUD마다 매번 새로 DB와의 커넥션을 만들어줄 수 밖에 없었지만, 스프링 tomcatJDBC 에 구현된 DataSource 클래스를 이용하면, 커넥션 풀 뿐만아니라, 연결/인증 단계를 한꺼번에 해결 할 수 있다. 또 이 DataSource를 이용하는 JdbcTemplate을 DAO 클래스에 한번 구현하면, CRUD 마다 DB커넥션을 일일이 다시 해 줄 필요가 없다. 

DataSource객체를 스프링 빈으로 등록해서 DAO 클래스로 DI 해준다면, 언제든지 똑같은 연결/인증+커넥션 풀을 이용할수 있다. 아래의 코드처럼 이렇게 애너테이션을 통해 DataSource를 빈으로 스프링 설정 클래스에 등록했다.

 

DAO 클래스(CRUD 전담 역할) 에 JDBC Template에 DataSource를 전달해서, 연결/인증 과정을 끝낸 모습. 앞으로 JDBC Template에 구현된 메서드를  쓰며, 복잡한 DB 커넥션 과정을 안해도 된다.

import org.apache.tomcat.jdbc.pool.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppCtx {
	
	@Bean
	public MemberDao dao() {
		return new MemberDao(datasource());
        //DAO 클래스의 멤버인 JDBC Template를 
        //위해 datasource를 DI하는 모습(생성자를 통한 DI)
	}
	
	@Bean
	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);
		return ds;

	}
	

}

 


import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

public class MemberDao {
	
	private JdbcTemplate jdbcTemplate;
	
	public MemberDao(DataSource ds) {
		this.jdbcTemplate=new JdbcTemplate(ds);
        //JDBC template를 생성할때,인자로 DataSource가
        //왔기 때문에, JDBC tempate을 쓰는 것만으로,
        //연결/인증 문장실행이 가능함.
	}
	
	
	public void insert(Member member) {
		
	}
	public void update(Member member) {
		
	}
	public Collection<Member> selectAll(){
		
	}
}

 

 

 

일반 JDBC API를 스프링 없이 이용할때는, SELECT 로 DB에서 테이블을 가져올 때, Connection,Prestatement,ResultSet등을 다 써서 이용했지만, 스프링 빈에 등록된 DataSource 객체로 Connection 과정을 없앨수 있고,

 

스프링의 JDBCtemplate에 구현된 메서드인, query()를 이용하면, 나머지 Statement,Resultset 과정도 없앨수 있다. 방법은  RowMapper<T> 란 클래스 를 구현후, query() 의 인자에 넣으면 리턴값으로 해당 쿼리를 실행한 결과집합을 객체의 형태로 리스트를 반환한다.

public Member MemberSelectByEmail(String email) {
		List<Member> results=jdbcTemplate.query("select * from member where email = ?", 
				new RowMapper<Member>() {

					@Override
					public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
						// TODO Auto-generated method stub
						Member member=new Member(rs.getString("EMAIL"), rs.getString("name"),
								 rs.getString("Password")
								 ,rs.getTimestamp("Regdate").toLocalDateTime());
						member.setId(rs.getLong("ID"));
						return member;
					}
			
			
		},email);
		return results.isEmpty()?null:results.get(0);
		
				
		
	}

익명클래스로 query()메서드의 인자인 RowMapper<Member>를 구현한 모습.

RowMapper<Member> 클래스의 역할 -> DB의 데이터를 객체로 변경시키는 역할을 한다.

JDBC API만 썻을때와 스프링의 JDBC Template을 썼을때의 차이를 알아야 한다. 예를 들어 CRUD 중 Select() 를 구현할려면, JDBC API로는 아예 리스트를 반환하는 과정을 While문으로 Resultset.next()으로 돌리면서 하나하나 entity를 생성한뒤 List에 추가하여서 반환해야한다.

반면, JDBC Template을 쓰면, while 문 쓸 필요없이, 위의 코드처럼 query()메서드만 사용하면 된다.

 

JDBC API를 쓸 경우.(내 토이 프로젝트 코드.)

public class NoticeService {
	public List<Notice> getList() throws ClassNotFoundException, SQLException{
    
    //List<Notice> 형 객체를 반환타입으로 가지는 메서드 생성.
    
		String url="jdbc:oracle:thin:@localhost:1521/xepdb1";
        String sql ="select * from notice";
		
		
		Class.forName("oracle.jdbc.driver.OracleDriver");
		Connection con = 
		DriverManager.getConnection(url,"newlec","vdongv1620");
	
	    Statement st=con.createStatement();
	    ResultSet rs=st.executeQuery(sql);
	    List<Notice> list=new ArrayList();
	    
	    
		while(rs.next()) {
			int id=rs.getInt("id");
			String title=rs.getString("title");
			String writer_id=rs.getString("writer_id");
			String content=rs.getString("content");
			String regdate=rs.getString("Regdate");
			int hit=rs.getInt("hit");
			Notice notice=new Notice(id,title,writer_id,content,regdate,hit);
            // Notice 클래스의 생성자로 서버에서 받아온 칼럼값을 
            //맴버로 가지는 클래스 생성
			
		list.add(notice);
        //생성한 클래스를 리스트에 삽입.
		
		}
		
		st.close();
		con.close();
        
		return list;
        //삽입이 완료된 리스트 타입을 반환

	}

 

확연히 더 복잡함을 느낄 수 있다.

 

 

 

 

 

공부시간 4시간.

순공시간 2시간.

 

 

DAO, Entity 클래스의 기능+ 왜 필요한지에 대한 설명.

DB에 접속하기 위한 연결/인증->문장실행->결과집합이라는 과정을 DAO클래스에서 보통 구현하고, CRUD 서비스를 구현하는 책임을 가진 클래스는 DAO이다. 당연한것이, CRUD를 할려면 어차피 DB 커넥션을 해야되기에 그렇다.

참고 : 블로그 

DTO(VO), DAO , Entity에 대해서 알아보자! - Retrospect (tistory.com)