22장. 스프링 JDBC 기능
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>
...