열심히 끝까지

디바이스 융합 자바(Java) day67(2) - 바인드 변수, Jdbc Template 본문

디바이스 융합 자바(Java)기반 풀스택 개발자 양성과정(수업내용)

디바이스 융합 자바(Java) day67(2) - 바인드 변수, Jdbc Template

노유림 2022. 9. 16. 17:41

[오전 내용] - 디바이스 융합 자바(Java) day67(1) 참고(https://programming-studyroom.tistory.com/201)
>> .xml에 AOP 설정
        : 하찮은 로그만 찍어봄
       >> 좀더 로그다운 것을 찍으려면
       >> 어떤 포인트컷과 연결되었는지를 확인하는 것이 좋음
                => joinpoint를 이용해 받아옴
                     >> 유용한 로그 찍는 것이 가능해짐
       >> around pjp를 인자로 받아서 포인트컷 연결
                >> business 메서드에 return값이 존재하기도 하는데
                         바인드 변수를 이용해 받을 수 있음
                        >> xml에서 return 및 throw값을 받을 수 있음

 

[오후 내용]

  ※ 바인드 변수
     == 바인드는 바인딩과 비슷
      Object returnObj
      : 설정을 해준다면, 비즈니스 메서드의 반환값을 바인드 변수에 자동으로 매핑해줌!

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
@Pointcut("execution(* com.ryo.biz..*Impl.*(..))")
public void aPointcut() {}

>> @(어노테이션)이용해서 설정
     1. applicationContext.xml에서 스프링 컨테이너에게
         "나 지금부터 AOP 설정을 @으로 할 거야."라고 알려줘야 함

            >> execution(* com.ryo.biz..*Impl.select*(..))이 필요

 

    2.  <aop:aspect ref="aa"> 설정

@Before("aPointcut()")

>> 괄호 꼭 쓸 것!!!!

 

  >> @Aspect + @Service 작성

       포인트컷 + 횡단관심
           1) 포인트컷을 설정
                  : 연결하고자하는 횡단관심이 저장(작성)된 클래스에서 설정가능
                     >> @Pointcut 으로 설정
           2) 포인트컷을 별도로 클래스화하여 관리 가능

-------------예시 코드----------------

-------------------applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">

	<context:component-scan base-package="com.ryo.biz" />
	
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
	
</beans>

--------------------AroundAdvice.java

package com.ryo.biz.common;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;

// @Service, @Aspect 작성
@Service
@Aspect
// around로 사용할 advice는 반드시 pjp를 input으로 가져야한다!!!
public class AroundAdvice { // 본인이 핵심메서드를 수행하게 해야 함
	// @PointCut 지정 
	@Pointcut("execution(* com.ryo.biz..*Impl.*(..))")
	public void aPointcut() {}
	
	@Pointcut("execution(* com.ryo.biz..*Impl.select*(..))")
	public void bPointcut() {}
    
	public Object printLogAround(ProceedingJoinPoint pjp) throws Throwable {
		String methodName=pjp.getSignature().getName();
		System.out.println("수행중인 핵심 메서드 명 : " + methodName);
		
		StopWatch sw = new StopWatch();
		// 시간을 측정하는 메서드 == spring 제공
		
		sw.start();
		Object returnObj=pjp.proceed(); // 수행해야할 포인트컷
		sw.stop();
		
		System.out.println("수행시간 : " + sw.getTotalTimeMillis()+"ms");
		
		return returnObj;
	}
}

 

>>>>>>>>>> 예시코드에서 사용한 다음 로직을 포인트컷과 관련된 모든 클래스에 써주어야 함

@Pointcut("execution(* com.ryo.biz..*Impl.*(..))")
public void aPointcut() {}
	
@Pointcut("execution(* com.ryo.biz..*Impl.select*(..))")
public void bPointcut() {}

 

      >> 이게 너무 반복되니 새 클래스로 제작

      >> 이해가 안되거나 헷갈리면 LogAdvice 찾아서 볼 것

 

-----------------PrintCut.java

package com.ryo.biz.common;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect // 횡단관심에도 붙어있어야 하고, pointcut에도 붙어있어야하기 때문에 꼭 붙여야 함 필수사항
public class PointCut { // 포인트컷 클래스를 따로 만드는 것
	@Pointcut("execution(* com.ryo.biz..*Impl.*(..))")
	public void aPointcut() {}
	
	@Pointcut("execution(* com.ryo.biz..*Impl.select*(..))")
	public void bPointcut() {}
}

-----------------바뀐 AroundAdvice.java

package com.ryo.biz.common;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;

@Service
@Aspect
// around로 사용할 advice는 반드시 pjp를 input으로 가져야한다!!!
public class AroundAdvice { // 본인이 핵심메서드를 수행하게 해야 함
	
	@Around("PointCut.aPointcut()")
	public Object printLogAround(ProceedingJoinPoint pjp) throws Throwable {
		String methodName=pjp.getSignature().getName();
		System.out.println("수행중인 핵심 메서드 명 : " + methodName);
		
		StopWatch sw = new StopWatch();
		// 시간을 측정하는 메서드 == spring 제공
		
		sw.start();
		Object returnObj=pjp.proceed(); // 수행해야할 포인트컷
		sw.stop();
		
		System.out.println("수행시간 : " + sw.getTotalTimeMillis()+"ms");
		
		return returnObj;
	}
}

-----------------AfterReturningAdvice.java

package com.ryo.biz.common;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Service;

import com.ryo.biz.member.MemberVO;

@Service
@Aspect
public class AfterReturningAdvice {
	
	@AfterReturning(pointcut="PointCut.aPointcut()", returning="returnObj")
	public void printLogAfterReturning(JoinPoint jp, Object returnObj) {
		String methodName=jp.getSignature().getName();
		Object[] args=jp.getArgs();
		
		System.out.println("수행중인 핵심 메서드 명 : " + methodName);
		System.out.println("사용하는 인자");
		System.out.println("++++");
		for(Object v : args) {
			System.out.println(v);
		}
		System.out.println("====");
		
		if(returnObj instanceof MemberVO) {
			MemberVO mvo = (MemberVO)returnObj;
			if(mvo.getRole().equals("ADMIN")) {
				System.out.println("관리자입니다.");
			}
			else {
				System.out.println("일반계정입니다.");
			}
		}
		System.out.println("핵심메서드의 반환값 : " + returnObj);
	}
}

-----------------AfterThrowingAdvice.java

package com.ryo.biz.common;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Service;

@Service
@Aspect
public class AfterThrowingAdvice {
	
	@AfterThrowing(pointcut="PointCut.aPointcut()", throwing="exceptObj")
	public void printLogAfterThrowing(JoinPoint jp, Exception exceptObj) {
		String methodName=jp.getSignature().getName();
		Object[] args=jp.getArgs();
		
		System.out.println("수행중인 핵심 메서드 명 : " + methodName);
		System.out.println("사용하는 인자");
		System.out.println("++++");
		for(Object v : args) {
			System.out.println(v);
		}
		System.out.println("====");
		
		// 약식(이런 형태로 사용 가능)
		System.out.println("발생한 예외" + exceptObj.getMessage());
		if(exceptObj instanceof IllegalArgumentException) {
			System.out.println("올바르지 않은 인자값을 사용했습니다...");
		}
		else if(exceptObj instanceof NumberFormatException) {
			System.out.println("숫자 형식이 아닌 값을 사용했습니다...");
		}
		else if(exceptObj instanceof Exception) {
			System.out.println("예외가 발생했습니다...");
		}
		else {
			System.out.println("확인되지 않은 에러가 발생했습니다!!!");
		}
	}
}

-----------------LogAdvice.java >> 자세한 설명이 쓰여있는 기본판 참고

package com.ryo.biz.common;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Service;

// component 써도 되지만 service로 작성
// 그냥 서비스로만 쓰면 스프링컨테이너 입장에서 판단하기 힘듬(비즈니스로직)
// == aspect의 서비스다 라고 인식을 시켜주기 위해 서비스 아래에 작성(결합했다! 라는 것을 의미)
@Service
@Aspect
public class LogAdvice {
	
	// 연결할 횡단관심사 위에다가 설정
	// 메서드 몸체는 쓰지 않음 ==> 지정된 행동을 할 예정
	/*
	 * @Pointcut("execution(* com.ryo.biz..*Impl.*(..))") public void aPointcut() {}
	 * 
	 * @Pointcut("execution(* com.ryo.biz..*Impl.select*(..))") public void
	 * bPointcut() {}
	 */
	
	@Before("PointCut.aPointcut()") // 괄호 안에 꼭 써줄 것
	public void printLog(JoinPoint jp) {
		// 인자로 joinpoint 제공(=aspectj 통해 import)
		
		// output == signature
		// getName() == 현재 수행중인 포인트컷(핵심로직, CRUD)의 메서드명
		String methodName=jp.getSignature().getName();
		
		// output == object  어떤 것이든 다 뱉음
		Object[] args=jp.getArgs();
		
		System.out.println("수행중인 핵심메서드명 : " + methodName);
		
		System.out.println("사용하는 인자");
		System.out.println("++++++++++++++++++++++");
		// 오버라이딩 + 동적바인딩
		for(Object v : args) {
			System.out.println(v);
		}
		System.out.println("======================");
		// System.out.println(">>> 공통로직 <<<     핵심로직 수행 전에 호출됨");
	}
}

-----------------LogAdvice2.java

package com.ryo.biz.common;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Service;

@Service
@Aspect
public class LogAdvice2 {
	@Before("PointCut.bPointcut()")
	public void printLog2() {
		System.out.println("!!!!!!업그레이드된 공통로직!!!!!!     select문 수행전에 호출됨");
	}
}

 


 

 

>> JDBC 적용시키기
    : 현재의 JDBC는 개발자가 직접 관리해야하는 코드가 많은 편!!
    : 템플릿 메서드 패턴 중에 하나인 "JdbcTemplate 클래스"를 활용해볼 것

    >> 템플릿 매서드 패턴이 언제 사용되는가?
          - 반복적인 로직을 가지는 부분을 "캡슐화"해서 사용
          - 코딩 순서가 정형화된 기술을 재사용하기 용이하게 "모듈화"해놓은 것
                : 정형화 == 반복적
  
 사용하기 위해서 필요한 것
  1) Library라이브러리 추가
      pom.xml------------

<!-- DBCP -->
<dependency>
	<groupId>commons-dbcp</groupId>
	<artifactId>commons-dbcp</artifactId>
	<version>1.4</version>
</dependency>
<!-- 위의 설치를 했음에도 작동이 잘 안되면 아래 것도 할 것 -->
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-jdbc</artifactId>
	<version>${org.springframework-version}</version>
</dependency>

     --------------------------
>>>> 작성 후 Maven Dependencies에 다음 파일이 추가되었는지 확인
  2) JdbcTemplate에서 활용할 DataSource가 필요
          1. DataSource를 applicationContext.xml에서 생성
            : 원래라면 DataSource ds = new DataSource(); 했을 가능성 농후

                  우리가 만드는 클래스는 @을 달 수 있음
                  클래스나 데이터소스를 외부에서 제공받으면 어노테이션을 하지 못함
                  >> xml이 boot로 넘어가도 사라지지 않는 이유
                  >> DataSource는 .xml 쓰는 것이 맞음
           2. setter인젝션 사용하여 drivername, user, password, url 입력(DI)
   >> ref가 아니라 value를 사용

<!-- DataSource 설정하기 JDBCUtil 격 -->
<!-- drivername, user, password, url을 입력받아야함 -->
<!-- setter인젝션 사용(의존성 주입) -->

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
	<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
	<property name="url" value="jdbc:oracle:thin:@localhost:포트번호:이름"></property>
	<property name="username" value="이름값"></property>
	<property name="password" value="비밀번호"></property>
</bean>

 

   3 ) JdbcTemplate을 new해서 DAO에서 활용할 예정
           -> .xml

<!-- Spring에서 사용하는 JDBC 방법(테이블 제작) -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"/>
</bean>

 

>> JdbcTemplate에서 자주 사용하는 것

 

- executeUpdate문

INSERT
UPDATE
DELETE
    1. int update(String sql,Object args,...) 
         : 시그니쳐만 오픈
    2. int update(String sql, Object[] args)

----------------------

- executeQuery문

SELECT
    1. Object queryForObject(String sql,Object[] args, 매핑정보)
         ex ) SELECT * FROM 테이블명 WHERE PK=?;
        >> RESULTSET과 VO의 매핑정보가 필요!
    2. List query(String sql,Object[] args, 매핑정보)
         ex ) SELECT * FROM 테이블명;

    >> 1번은 하나만 출력할 때, 사용

※ 과거에 queryForInt이 존재했으나 더이상사용하지않음!
queryForObject로 대체해서 사용해야하며,  별도의 매핑이 필요할경우 새로운 class Mapper를 만들어서 사용
   
>> 매핑정보는 RowMapper통해서 

-------------------------------------------------------

>>> 기존에서 신규 DAO로 바꿀 때,

   1. @Repository("테이블DAO") 가져오기

            > 그 전 테이블에서는 참조 못하게 삭제할 것

   2. @Autowired
       private JdbcTemplate jdbcTemplate;

      클래스 안에 추가할 것

      >> xml에 있는 jdbc 정보 가져오는 것

    3. 위에 적은 JdbcTemplate을 이용해 관련 로직 바꿔주기

    4. SelectOne 과 SelectAll에게는 추가 매핑정보가 필요한데

        추가 매핑정보를 클래스 아래에 RowMapper를 참조하는 클래스를 만들어서 사용할 것

ex ) 

class BoardRowMapper implements RowMapper<BoardVO>{

	@Override
	public BoardVO mapRow(ResultSet rs, int rowNum) throws SQLException {
		// 알아서 rowNum을 판단하기 때문에 걱정하지 말 것
		BoardVO data=new BoardVO();
		data.setBid(rs.getInt("BID"));
		data.setContent(rs.getString("CONTENT"));
		data.setTitle(rs.getString("TITLE"));
		data.setWriter(rs.getString("WRITER"));
		data.setCnt(rs.getInt("CNT"));
		data.setRegdate(rs.getString("REGDATE"));
		return data;
	}
	
}

 

예시--------------------------

----------------------BoardDAO 바꾸기 전

package com.ryo.biz.board.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Repository;

import com.ryo.biz.board.BoardVO;
import com.ryo.biz.common.JDBCUtil;

public class BoardDAO {
	private Connection conn;
	private PreparedStatement pstmt;

	final String sql_selectOne="SELECT * FROM BOARD WHERE BID=?";
	final String sql_selectAll="SELECT * FROM BOARD ORDER BY BID DESC";
	final String sql_insert="INSERT INTO BOARD(BID,TITLE,WRITER,CONTENT) VALUES((SELECT NVL(MAX(BID),0)+1 FROM BOARD),?,?,?)";
	final String sql_update="UPDATE BOARD SET TITLE=?, CONTENT=? WHERE BID=?";
	final String sql_delete="DELETE BOARD WHERE BID=?";


	BoardVO selectOneBoard(BoardVO vo) {
		conn=JDBCUtil.connect();
		try {
			pstmt=conn.prepareStatement(sql_selectOne);
			pstmt.setInt(1, vo.getBid());
			ResultSet rs=pstmt.executeQuery();
			if(rs.next()) {
				BoardVO data=new BoardVO();
				data.setBid(rs.getInt("BID"));
				data.setContent(rs.getString("CONTENT"));
				data.setTitle(rs.getString("TITLE"));
				data.setWriter(rs.getString("WRITER"));
				data.setCnt(rs.getInt("CNT"));
				data.setRegdate(rs.getString("REGDATE"));
				return data;
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			JDBCUtil.disconnect(pstmt, conn);
		}		
		return null;
	}
	List<BoardVO> selectAllBoard(BoardVO vo) {
		List<BoardVO> datas=new ArrayList<BoardVO>();
		conn=JDBCUtil.connect();
		try {
			pstmt=conn.prepareStatement(sql_selectAll);
			ResultSet rs=pstmt.executeQuery();
			while(rs.next()) {
				BoardVO data=new BoardVO();
				data.setBid(rs.getInt("BID"));
				data.setContent(rs.getString("CONTENT"));
				data.setTitle(rs.getString("TITLE"));
				data.setWriter(rs.getString("WRITER"));
				data.setCnt(rs.getInt("CNT"));
				data.setRegdate(rs.getString("REGDATE"));
				datas.add(data);
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			JDBCUtil.disconnect(pstmt, conn);
		}		
		return datas;
	}
	void insertBoard(BoardVO vo) {
		conn=JDBCUtil.connect();
		try {
			pstmt=conn.prepareStatement(sql_insert);
			pstmt.setString(1, vo.getTitle());
			pstmt.setString(3, vo.getContent());
			pstmt.setString(2, vo.getWriter());
			pstmt.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JDBCUtil.disconnect(pstmt, conn);
		}
	}
	void updateBoard(BoardVO vo) {
		conn=JDBCUtil.connect();
		try {
			pstmt=conn.prepareStatement(sql_update);
			pstmt.setString(1, vo.getTitle());
			pstmt.setString(2, vo.getContent());
			pstmt.setInt(3,vo.getBid());
			pstmt.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JDBCUtil.disconnect(pstmt, conn);
		}
	}
	void deleteBoard(BoardVO vo) {
		conn=JDBCUtil.connect();
		try {
			pstmt=conn.prepareStatement(sql_delete);
			pstmt.setInt(1,vo.getBid());
			pstmt.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JDBCUtil.disconnect(pstmt, conn);
		}
	}	
}

----------------------BoardDAO 바꾼 후

package com.ryo.biz.board.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import com.ryo.biz.board.BoardVO;

@Repository("boardDAO")
public class BoardDAO2 {
	
	// 의존 관계 + 의존성 주입 필요
	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	final String sql_selectOne="SELECT * FROM BOARD WHERE BID=?";
	final String sql_selectAll="SELECT * FROM BOARD ORDER BY BID DESC";
	final String sql_insert="INSERT INTO BOARD(BID,TITLE,WRITER,CONTENT) VALUES((SELECT NVL(MAX(BID),0)+1 FROM BOARD),?,?,?)";
	final String sql_update="UPDATE BOARD SET TITLE=?, CONTENT=? WHERE BID=?";
	final String sql_delete="DELETE BOARD WHERE BID=?";

	BoardVO selectOneBoard(BoardVO vo) {
		Object[] args= {vo.getBid()};
		return jdbcTemplate.queryForObject(sql_selectOne,args,new BoardRowMapper());
	}
	List<BoardVO> selectAllBoard(BoardVO vo) {
		return jdbcTemplate.query(sql_selectAll,new BoardRowMapper());
	}
	void insertBoard(BoardVO vo) {
		System.out.println("★");
		jdbcTemplate.update(sql_insert,vo.getTitle(),vo.getWriter(),vo.getContent());
	}
	void updateBoard(BoardVO vo) {
		jdbcTemplate.update(sql_update,vo.getTitle(),vo.getContent(),vo.getBid());
	}
	void deleteBoard(BoardVO vo) {
		jdbcTemplate.update(sql_update,vo.getBid());
	}	

}
class BoardRowMapper implements RowMapper<BoardVO>{

	@Override
	public BoardVO mapRow(ResultSet rs, int rowNum) throws SQLException {
		// 알아서 rowNum을 판단하기 때문에 걱정하지 말 것
		BoardVO data=new BoardVO();
		data.setBid(rs.getInt("BID"));
		data.setContent(rs.getString("CONTENT"));
		data.setTitle(rs.getString("TITLE"));
		data.setWriter(rs.getString("WRITER"));
		data.setCnt(rs.getInt("CNT"));
		data.setRegdate(rs.getString("REGDATE"));
		return data;
	}
	
}

--------기세를 몰아 Member 까지 변경

 

----------------------MemberDAO 바꾸기 전

package com.ryo.biz.member.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.stereotype.Repository;

import com.ryo.biz.common.JDBCUtil;
import com.ryo.biz.member.MemberVO;

public class MemberDAO {
	private Connection conn;
	private PreparedStatement pstmt;

	final String sql_selectAll="SELECT * FROM MEMBER";
	final String sql_selectOne="SELECT * FROM MEMBER WHERE MID=? AND MPW=?";
	final String sql_insert="INSERT INTO MEMBER(MID,MPW,NAME,ROLE) VALUES(?,?,?,?)";
	final String sql_update="UPDATE BOARD SET NAME=?, MPW=? WHERE MID=?";
	final String sql_delete="DELETE BOARD WHERE MID=?";
	
	public MemberVO selectOneMember(MemberVO vo) {
		conn=JDBCUtil.connect();
		try {
			pstmt=conn.prepareStatement(sql_selectOne);
			pstmt.setString(1, vo.getMid());
			pstmt.setString(2, vo.getMpw());
			ResultSet rs=pstmt.executeQuery();
			if(rs.next()) {
				MemberVO data=new MemberVO();
				data.setMid(rs.getString("MID"));
				data.setMpw(rs.getString("MPW"));
				data.setName(rs.getString("NAME"));
				data.setRole(rs.getString("ROLE"));
				System.out.println("로그 : 로그인 완료 " + vo);
				return data;
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			JDBCUtil.disconnect(pstmt, conn);
		}		
		return null;
	}
	public void insertMember(MemberVO vo) {
		conn=JDBCUtil.connect();
		try {
			pstmt=conn.prepareStatement(sql_insert);
			pstmt.setString(1, vo.getMid());
			pstmt.setString(2, vo.getMpw());
			pstmt.setString(3, vo.getName());
			pstmt.setString(4, vo.getRole());
			pstmt.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JDBCUtil.disconnect(pstmt, conn);
		}
	}
	public void updateMember(MemberVO vo) {
		conn=JDBCUtil.connect();
		try {
			pstmt=conn.prepareStatement(sql_update);
			pstmt.setString(1, vo.getName());
			pstmt.setString(2, vo.getMpw());
			pstmt.setString(3,vo.getMid());
			pstmt.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JDBCUtil.disconnect(pstmt, conn);
		}
	}
	public void deleteMember(MemberVO vo) {
		conn=JDBCUtil.connect();
		try {
			pstmt=conn.prepareStatement(sql_delete);
			pstmt.setString(1,vo.getMid());
			pstmt.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JDBCUtil.disconnect(pstmt, conn);
		}
	}	
}

----------------------MemberDAO 바꾼 후

package com.ryo.biz.member.impl;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import com.ryo.biz.member.MemberVO;

@Repository("memberDAO")
public class MemberDAO2 {
	
	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	final String sql_selectAll="SELECT * FROM MEMBER";
	final String sql_selectOne="SELECT * FROM MEMBER WHERE MID=? AND MPW=?";
	final String sql_insert="INSERT INTO MEMBER(MID,MPW,NAME,ROLE) VALUES(?,?,?,?)";
	final String sql_update="UPDATE BOARD SET MPW=? WHERE MID=?";
	final String sql_delete="DELETE BOARD WHERE MID=?";
	
	public MemberVO selectOneMember(MemberVO vo) {
		Object[] args= {vo.getMid(),vo.getMpw()};
		System.out.println("★");
		return jdbcTemplate.queryForObject(sql_selectOne, args,new MemberRowMapper());
	}
	public void insertMember(MemberVO vo) {
		Object[] args= {vo.getMid(),vo.getMpw(),vo.getName(),vo.getRole()};
		jdbcTemplate.update(sql_insert,args);
	}
	public void updateMember(MemberVO vo) {
		Object[] args= {vo.getMpw(),vo.getMid()};
		jdbcTemplate.update(sql_update,args);
	}
	public void deleteMember(MemberVO vo) {
		jdbcTemplate.update(sql_delete,vo.getMid());
	}	
	
	
}
class MemberRowMapper implements RowMapper<MemberVO>{

	@Override
	public MemberVO mapRow(ResultSet rs, int rowNum) throws SQLException {
		MemberVO data=new MemberVO();
		data.setMid(rs.getString("MID"));
		data.setMpw(rs.getString("MPW"));
		data.setName(rs.getString("NAME"));
		data.setRole(rs.getString("ROLE"));
		System.out.println("로그 : 로그인 완료 " + data);
		return data;
	}
	
}