BackEnd/Spring

22장. 스프링 JDBC 기능

제이드Jade 2022. 3. 2. 00:02

22.1 스프링 JDBC로 데이터베이스와의 연동 설정하기

  • 기존 JDBC(Java Database Connectivity)의 장점을 유지하고 단점을 보완한 스프링 JDBC는 간결한 API 뿐만 아니라 확장된 JDBC의 기능도 제공
    • 실제 개발할 때는 스프링 JDBC 기능보다 마이바티스나 하이버네이트 같은 데이터베이스 연동 관련 프레임워크를 사용하지만 스프링 JDBC의 기본적인 기능을 알아두면 좋음
  • < 스프링 JDBC 설정 파일들 >
파일 설명
web.xml ContextLoaderListener를 이용해 빈 설정 XML 파일들을 읽어드림
action-dataSource.xml 스프링 JDBC 설정에 필요한 정보를 설정
jdbc.properties 데이터베이스 연결 정보를 저장
action-service.xml 서비스 빈 생성을 설정

 

  • < 구현 과정 >

- WebContent 폴더내에 config 폴더 생성 후 그 안에 action-service.xml / action-dataSource.xml / jdbc.properties 파일 생성

- action-servlet.xml / action-service.xml / action-dataSource.xml : 앞서 실습한 action-servlet.xml의 상단 <beans> 태그를 붙여넣음

 

- web.xml

>> 한개의 파일에서 몽땅 빈을 설정/주입하지 않고 빈의 종류에 따라 나누어 xml 파일에서 설정

1. 스프링의 ContextLoaderListener를 설정

2. action-servlet.xml 외에 추가로 service와 dao 빈 설정(주입)을 두개의 xml파일에 나누어 설정할 것임을 명시 

     => context param의 contextConfigLocation 매개변수의 값으로 두 xml파일 위치 설정

     => 애플리케이션 실행 시 위에서 설정한 리스너로 해당 위치의 설정 파일을 읽어드림

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<listener>
	<listener-class>
		org.springframework.web.context.ContextLoaderListener
	</listener-class>
</listener>

<context-param>
	<param-name>contextCongifLocation</param-name>
	<param-value>
		/WEB-INF/config/action-service.xml
		/WEB-INF/config/action-dataSource.xml
	</param-value>
</context-param>

<servlet>
	<servlet-name>action</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>

<servlet-mapping>
	<servlet-name>action</servlet-name>
	<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>

 

- action-servlet.xml

>> viewResolver의 prefix를 /WEB-INF/views폴더로

>> 컨트롤러에 methodNameResolver 빈과 memberService 빈을 주입

>> methodNameResolver에서는 list, add, form, detail 요청명과 메서드를 매핑

~ 그 외에는 이전 action-servlet과 동일 ~

...
<bean id="memberController" class="com.spring.member.controller.MemberControllerImpl">
    <property name="methodNameResolver">
        <ref local="methodResolver"/>
    </property>
    <property name="memberService" ref="memberService"></property>
</bean>

<bean id="methodResolver" class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
    <property name="mappings">
        <props>
            <prop key="/member/listMembers.do">listMembers</prop>
            <prop key="/member/addMember.do">addMember</prop>
            <prop key="/member/memberForm.do">memberForm</prop>
            <prop key="/member/memberDetail.do">memberDetail</prop>
        </props>
    </property>
</bean>



<bean id="userUrlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
        <props>
            <prop key="/member/*.do">memberController</prop>
        </props>
    </property>
</bean>



<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/views/" />
    <property name="suffix" value=".jsp"/>
</bean>
</beans>

 

- action-service.xml

...
<bean id="memberService" class="com.spring.member.service.MemberServiceImpl">
	<property name="memberDAO" ref="memberDAO"/>
</bean>
</beans>

>> memberService 빈을 생성하고 memberDAO 빈을 여기에 주입!!

 

- action-dataSource.xml

>> 스프링에서 사용할 데이터베이스 연동 정보를 설정!!

...
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
	<property name="locations">
		<list>
			<value>/WEB-INF/config/jdbc.properties</value>
		</list>
	</property>
</bean>

<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
	<property name="driverClass" value="${jdbc.driverClassName}"></property>
	<property name="url" value="${jdbc.url}"></property>
	<property name="username" value="${jdbc.username}"></property>
	<property name="password" value="${jdbc.password}"></property>
</bean>

<bean id="memberDAO" class="com.spring.member.dao.MemberDAOImpl">
	<property name="dataSource" ref="dataSource"/>
</bean>

</beans>

>> property~configurer의 location으로 데이터베이스 연결정보가 담긴 properties파일 위치를 지정

     => properties 파일 내에 설정한 jdbc연결정보 변수를 표현언어로 사용할 수 있음

>> datasource빈을 생성해서 속성값으로 jdbc연결정보를 넣음

>> 이렇게 생성한 datasource빈을 dao 빈에 주입

 

- jdbc.properties

>> 데이터베이스 연결 정보를 작성

jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521:XE
jdbc.username=C##scott
jdbc.password=tiger

 

 

 

 

22.2 JdbcTemplate 클래스 이용해 회원 정보 조회하기

~ 회원 테이블에서 조회한 회원정보를 JSP에 출력해보자~

  • DAO 클래스에서 실제 스프링의 JDBC 기능을 제공하는 클래스는 JdbcTemplate
  • JdbcTemplate : 이때까지 JDBC API를 사용하면서 계속 반복됐던 작업을 (pstmt 객체 생성, 마지막에 close처리 등) 줄이기 위해서 스프링에서 제공하는 클래스
  • <JdbcTemplate 클래스에서 제공하는 SQL 관련 메서드>

+) 여기 listMembers 메서드에서는 List query(String query, RowMapper rowmapper)메서드를 사용!!

 

- ControllerImpl.java

public class MemberControllerImpl extends MultiActionController implements MemberController {

	private MemberService memberService;
	
	public void setMemberService(MemberService memberService) {
		this.memberService = memberService;
	}

	@Override
	public ModelAndView listMembers(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String viewName=getViewName(request);
		ModelAndView mav=new ModelAndView(viewName);
		
		List membersList=memberService.listMembers();
		mav.addObject("membersList",membersList);
		
		return mav;
	}

	private String getViewName(HttpServletRequest request) throws Exception{
    ...

- ServiceImpl.java

public class MemberServiceImpl implements MemberService {

	private MemberDAO memberDAO;
	
	public void setMemberDAO(MemberDAO memberDAO) {
		this.memberDAO = memberDAO;
	}

	
	@Override
	public List listMembers() throws DataAccessException{
		
		return memberDAO.selectAllMembers();
	}

}

- DAOImpl.java

>> 실제 스프링의 JDBC 기능을 제공하는 JdbcTemplate 객체를 선언

>> setter에서 주입된 dataSource빈을 JdbcTemplate 클래스 생성자의 인자로 입력

public class MemberDAOImpl implements MemberDAO {

	private JdbcTemplate jdbcTemplate;
	
	public void setDataSource(DataSource dataSource) {
		this.jdbcTemplate = new JdbcTemplate(dataSource);
	}

	@Override
	public List selectAllMembers() {
		String query="select id, pwd, name, email, joinDate from t_member order by joinDate desc";
		List membersList=new ArrayList();
		
		membersList=jdbcTemplate.query(query, new RowMapper<MemberVO>() {

			@Override
			public MemberVO mapRow(ResultSet rs, int rowNum) throws SQLException {
				return new MemberVO(rs.getString("id"), rs.getString("pwd"), rs.getString("name"), rs.getString("email"), rs.getDate("joinDate"));
			
		}});
		
		return membersList;
	}

	@Override
	public int addMember(MemberVO memberVO) throws DataAccessException{
		
		String query="insert into t_member(id,pwd,name,email) values('"
					+memberVO.getId()+"','"+memberVO.getPwd()+"','"+memberVO.getName()+"','"+memberVO.getEmail()+"')";
		
		return jdbcTemplate.update(query);
	}

}

>>setDataSource임에 주의. 주입할 때 name과 set뒤에 name이 같아야 한닷

>> membersList=jdbcTemplate.query() ... : select문을 넘겨줘서 조회한 레코드의 개수만큼 MemberVO 객체를 생성하여 리스트를 생성

List<T> query(String sql, RowMapper<T> rowMapper) - sql 파라미터로 전달받은 쿼리를 실행하고 RowMapper를 이용해서 ResultSet의 결과를 자바 객체로 변환

- 임의 클래스 람다식으로 RowMapper의 객체를 생성해서 query() 메서드에 전달함(RowMapper인터페이스를 구현한 클래스를 작성할 수도 있음)
* RowMapper 인터페이스 형태
public interface RowMapper<T> {
   T mapRow(ResultSet rs, int rowNum) throws SQLException;
}
- mapRow() 메서드 : SQL 실행 결과로 구한 ResultSet에서 한 행의 데이터를 읽어와 자바 객체로 변환하는 매퍼 기능을 구현

출처: https://jaehoney.tistory.com/34

 

- views/membersList.jsp

...
<c:forEach var="mem" items=${membersList }>
	   <tr align="center">
	      <td>${mem.id}</td>
	      <td>${mem.pwd}</td>
	      <td>${mem.name}</td>
	      <td>${mem.email}</td>
	      <td>${mem.joinDate }</td>
	    </tr>
    </c:forEach>
 ...