TODAY TOTAL
Back-End (44)
[JSP] MyBatis Mapper,Log4j,싱글톤 패턴 써보기

학원에 다니면서 전에 만들었던 자유게시판, 회원목록, 페이징을 만들었는데, 오늘부터 xml파일을 이용하고 mybatis 를 이용하니 좀 더 간결하고 쉽게 만들었지는거 같다.

 

전에는 DaoOracle에 append로 쿼리를 싹다 붙이고 코드줄이 엄청 길었는데, 오늘 MyBatis퍼시스턴스 프레임워크를 쓰니 세상 편하다. 쓰는 이유가 다 있구나

 

처음에는 View단에 싹다 JDBC나 이것저것 놨다가 두번째는 DaoOracle,Service로 나눠서 서버단과 뷰단을 나누고 하니

원리를 이해 할 수 있어서 좋았다. 마지막은 최종 스프링인데, 뭔가 엄청 어려워 보이지만 끝까지 해보자!

 

 

https://mybatis.org/mybatis-3/ko/index.html

 

MyBatis – 마이바티스 3 | 소개

Copyright © 2009–2021MyBatis.org. .

mybatis.org

홈페이지에 시작하기를 눌러 천천히 따라하기.

 

 

홈페이지가 한글번역이 된 MyBatis.

 

메이븐을 지금은 사용하지 않기 때문에 

메뉴상단바 Help-Eclipse Marketplace에서

'MyBatipse' 라고 치면 

 

install 후 약관 동의 후 완료 클릭

 

 

 

전에 만들었던 자유게시판을 수정도 하고, mapper,xml 파일을 추가할 것이다.

 

전에는 Dao에서 만들었던 것이 Mapper로 바뀌는 것이다. 즉, DB에 접근해서 데이터를 조회하고 조작

하는 기능 담당했던 객체 Dao가 Mapper로 바뀌는 것이다.

 

 

그러면 Mapper는 무엇이길래 Dao에서 갑자기 바꾸는 것일까?

 

바꾸면 다음과 같이 좋은 점이 있다.

 

  • SQLSession을 등록 하지 않아도 된다.
  • DAO인터페이스와 인터페이스를 구현한 DAO클래스를 생성 안해도 된다.
  • 문자열을 작성할때 실수가 줄어든다.
  • IDE에서 제공하는 Code assist를 사용할 수 있다.

 

그리고 싱글톤 패턴이 있다.

 

오직 하나의 인스턴스만 사용할 수 있도록 객체를 생성하는 방법이다.

여기서 인스턴스는 클래스를 복제 해 쉽게 관리해주는 게 인스턴스다.

 

 

FreeBoardServiceImpl.java

 

package com.study.free.service;
	
import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import com.study.exception.BizNotFoundException;
import com.study.exception.BizPasswordNotMatchedException;
import com.study.free.vo.FreeBoardSearchVO;
import com.study.free.vo.FreeBoardVO;
import com.study.util.MybatisSqlSessionFactory;
	
public class FreeBoardServiceImpl implements IFreeBoardService {
	
	//싱글톤 패턴
	
//	오직 하나의 인스턴스만 사용할 수 있도록 객체를 생성하는 방법이다.
//	최초 하나의(Single) 인스턴스만 생성하고, 이후에는 이 인스턴스를 참조하게 된다.
//	정적인 클래스 멤버변수 선언 ( - private), 관례적으로 변수명은 instance
//	생성자 숨김(private) <- 외부에서 new 생성 금지 내부에서만 호출 가능 
//	new를 통해서 가져가라
//	정적멤버변수를 제공(return)하는 공개 매서드 생성, 관레적으로 메서드명은 getInstance()
	private static FreeBoardServiceImpl instance = new FreeBoardServiceImpl(); //내부에서 호출가능 new FreeBoardServiceImpl();는 자기자신
	//생성된 인스턴스를 넘겨줘야하고, public으로 이동
	private FreeBoardServiceImpl () {
		//생성자는 막아줘야한다. 외부에서 생성 못하게
	}
	//생성된 인스턴스 도착.
	public static FreeBoardServiceImpl getInstance() { //FreeBoardServiceImpl.getInstance
		if(instance == null) instance = new FreeBoardServiceImpl();
		return instance;
	}
	
	private SqlSessionFactory factory = MybatisSqlSessionFactory.getSqlSessionFactory(); 
	
	
	//private String JDBC_URL = "jdbc:apache:commons:dbcp:study";
	//private IFreeBoardDao boardDao = new FreeBoardDaoOracle();				 //
	
	@Override
	public int getBoardCount(FreeBoardSearchVO searchVO) {

		try(SqlSession session = factory.openSession()) {
			//insert() , update(), delect(), selectOne(), selectList(), selectMap()
			int tot = session.selectOne("com.study.free.dao.IFreeBoardDao.getBoardCount",searchVO);
			
			return tot;
			
		} 
		
	}
	
	@Override
	public List<FreeBoardVO> getBoardList(FreeBoardSearchVO searchVO) {

		try(SqlSession session = factory.openSession()) {
			//insert() , update(), delect(), selectOne(), selectList(), selectMap()
			List<FreeBoardVO> list = session.selectList("com.study.free.dao.IFreeBoardDao.getBoardList",searchVO);
			
			return list;
			
		} 
		
		
	}

	@Override
	public FreeBoardVO getBoard(int boNo) throws BizNotFoundException {
		
		try(SqlSession session = factory.openSession()) {
			FreeBoardVO Board = session.selectOne(
									"com.study.free.dao.IFreeBoardDao.getBoard",boNo);
			if(Board == null) {
				throw new BizNotFoundException("글번호 ["+boNo + "] 조회 실패");
			} 
			return Board;
			
		} 
		
		
//		Connection conn = null;
//		try {
//			conn = DriverManager.getConnection(JDBC_URL);
//			
//			FreeBoardVO Board = boardDao.getBoard(boNo);
//			//Board가 널인 경우 BizNotFoundException 예외발생
//			if(Board == null) {
//				throw new BizNotFoundException("글번호 ["+boNo + "] 조회 실패");
//			} 
//			return Board;
//		} catch (SQLException e) {
//			e.printStackTrace();
//			throw new RuntimeException(e.getMessage(), e);
//		}finally {
//			if (conn != null) try {conn.close();} catch (SQLException e) {}
//		}
	}

	@Override
	public void registBoard(FreeBoardVO board) {
//		Connection conn = null;
//		try {
//			conn = DriverManager.getConnection(JDBC_URL);
//			conn.setAutoCommit(false);
//			
//			boardDao.insertBoard(board);
//			
//			conn.commit();
//		}catch (SQLException e) {
//			e.printStackTrace();
//			try {
//				conn.rollback();
//			}catch (SQLException e2) {}
//			throw new RuntimeException(e.getMessage(),e);
//		}finally {
//			if (conn != null) try {conn.close();
//			}catch (SQLException e) {}
//		}
		
	}

	@Override
	public void modifyBoard(FreeBoardVO board) 
			throws BizNotFoundException, BizPasswordNotMatchedException {
//		Connection conn = null;
//		try {
//			conn = DriverManager.getConnection(JDBC_URL);
//			conn.setAutoCommit(false);
//			
//			FreeBoardVO vo = boardDao.getBoard(board.getBoNo());
//			if(vo == null) {
//				throw new BizNotFoundException("글 번호 [" + board.getBoNo() + "] 글 조회 실패");
//			}
//			if( !vo.getBoPass().equals(board.getBoPass() ) ) {
//				throw new BizPasswordNotMatchedException("패스워드가 다릅니다.");
//			}
//			
//			boardDao.insertBoard(board);
//			
//			conn.commit();
//		}catch (SQLException e) {
//			e.printStackTrace();
//			try {
//				conn.rollback();
//			}catch (SQLException e2) {}
//			throw new RuntimeException(e.getMessage(),e);
//		}finally {
//			if (conn != null) try {conn.close();
//			}catch (SQLException e) {}
//		}
		
	}

	@Override
	public void removeBoard(FreeBoardVO board) 
			throws BizNotFoundException, BizPasswordNotMatchedException {
	//제거
//		Connection conn = null;
//		try {
//			conn = DriverManager.getConnection(JDBC_URL);
//			conn.setAutoCommit(false);
//			//비밀번호 확인
//			FreeBoardVO vo = boardDao.getBoard(board.getBoNo());
//			if(vo == null) {
//				throw new BizNotFoundException("글 번호 [" + board.getBoNo() + "] 글 조회 실패");
//			}
//			if( !vo.getBoPass().equals(board.getBoPass() ) ) {
//				throw new BizPasswordNotMatchedException("패스워드가 다릅니다.");
//			}
//			//비밀번호 확인
//			
//			boardDao.deleteBoard(board);
//			// TODO cnt가 0 인 경우 BizNotEffectedException 예외 발생
//			
//			conn.commit();
//		} catch (SQLException e) {
//			e.printStackTrace();
//			try {conn.rollback();} catch (SQLException e2) {}
//			throw new RuntimeException(e.getMessage(), e);
//		}finally {
//			if (conn != null) try {conn.close();} catch (SQLException e) {}
//		}		
		
	}

	@Override
	public void increaseHit(int boNo) {
//		Connection conn = null;
//		try {
//			conn = DriverManager.getConnection(JDBC_URL);
//			conn.setAutoCommit(false);
//			
//			boardDao.increaseHit(boNo);
//			
//			conn.commit();
//		} catch (SQLException e) {
//			e.printStackTrace();
//			try {conn.rollback();} catch (SQLException e2) {}
//			throw new RuntimeException(e.getMessage(), e);
//		}finally {
//			if (conn != null) try {conn.close();} catch (SQLException e) {}
//		}	
		
		
		
	}

}

:: 주석 단게 전에 했던 Dao

 

이렇게 바꿨다면 이제 List,Edit,View,Delete,Modify,Regist에 getInstance를 넣어줘야한다.

전에는 객체를 계속 생성해서 바뀌는데, 오직하나의 인스턴스만 생성하기 때문에 바뀌지 않는다.

 

최초 하나의(Single) 인스턴스만 생성하고, 이후에는 이 인스턴스를 참조하게 된다.

정적인 클래스 멤버변수 선언 ( - private), 관례적으로 변수명은 instance

 

ICodeService codeService = new CodeServiceImpl(); (전)

 

ICodeService codeService = CodeServiceImpl.getInstance(); (후)

 

(코드 주석 참조)

 


WEB-INF/lib에 넣어놨다.

 

 

 

log4j.xml

 

log4j는 아파치에서 만든 오픈소스 라이브러리로써 로그를 남기 위해 사용되는 자바기반 로깅 유틸리티입니다.

디버그용 도구로 사용합니다.

 

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration 
		PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" 
		"http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
<!--
  ** 1. jar : log4j-1.2.17.jar
     2. log4.xml 파일은 /WEB-INF/classes 바로 존재해야함    
     		maven인 경우 resource폴더 바로 밑에
     		일반 웹어플인 경우 src 폴더 밑에
     
 -->
 
 
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  
<!--  콘솔 로그   -->
<appender name="console" class="org.apache.log4j.ConsoleAppender"> 
    <layout class="org.apache.log4j.PatternLayout"> 
        <param name="ConversionPattern" value="[%-5p] %t %c.%M:%L - %m %n "/> 
    </layout> 
</appender>
  
<!--  날짜별 로그 --> 
<appender name="dailyFile" class="org.apache.log4j.DailyRollingFileAppender">
    <!-- 이것은 날짜별로  로그를 남김. 파일명.확장자.DatePattern으로 정의 함--> 
     <param name="File" value="${user.home}/log/study3.log" />

    <param name="Append" value="true" />
    <param name="Encoding" value="UTF-8" />
    <!-- param name="MaxFileSize" value="100000KB" /> -->
    <!-- param name="MaxBackupIndex" value="10" /> -->
    <param name="DatePattern" value="'.'yyMMdd"/>  
    <!--yyMMddHHmm, 시간별로 하고싶다 HH, 일별로 하고 싶다 ddd  -->
    <layout class="org.apache.log4j.PatternLayout"> 
        <param name="ConversionPattern" value="[%-5p] %t %c.%M:%L - %m %n"/>
         
         <!--
          <param name="ConversionPattern" value="%t> 
              [%d{yyyy-MM-dd HH:mm:ss}] [%c{1}] [%L] [%p] %m %n"/>
           위 pattern 결과 :http-bio-8080-exec-6> [2017-01-12 12:07:44] [root] [179] [ERROR]
         --> 
    </layout> 
</appender>     
 
<!-- xml 로그--> 
<!-- xml형식으로 로그를 남김 
<appender name="xmlout" class="org.apache.log4j.FileAppender"> 
    <param name="file" value="log4jxml.xml"/> 
    <param name="Append" value="true"/> 
    <layout class="org.apache.log4j.xml.XMLLayout"/> 
</appender> 
 -->
 
<!--  팩키지별 로그 설정 -->
<logger name="org.springframework" additivity="false">
    <level value="WARN" />
    <appender-ref ref="dailyFile" />
    <appender-ref ref="console" />
</logger>

<logger name="com.study" additivity="false">
    <level value="debug" />
    
</logger>

 
<!--
  root 로거 기본 설정  
    - ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF
    
    DEBUG : 개발자가 변수들 확인하기 위한 용도
    INFO  : 개발자가 중요한 변수 확인하기 위한 용도
    WARN  : 에러는 아니지만 뭔가 의심스러운 변수를 확인하기 위한 용도
    ERROR : 오류가 발생한 경우, 대단히 의심스러운 경우 확인
    FATAL : 애플리케이션 운영에 심각한 영향이 있을 경우 FATAL로 로그를 남긴다. 
-->
<root>
  <level value="info" />
  <appender-ref ref="console"/>
  <appender-ref ref="dailyFile"/>
</root>
 
</log4j:configuration>

 

root 로거 기본 설정  
    - ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF
    
    DEBUG : 개발자가 변수들 확인하기 위한 용도
    INFO  : 개발자가 중요한 변수 확인하기 위한 용도
    WARN  : 에러는 아니지만 뭔가 의심스러운 변수를 확인하기 위한 용도
    ERROR : 오류가 발생한 경우, 대단히 의심스러운 경우 확인
    FATAL : 애플리케이션 운영에 심각한 영향이 있을 경우 FATAL로 로그를 남긴다. 

 

ALL이나 TRACE는 사용을 잘 안하고 DEBUG부터 5단계 보통 시작한다.

 

 

 

app_config.properties

 

#config/ app_config.properties


jdbc.driverClassName =oracle.jdbc.driver.OracleDriver
jdbc.url =jdbc:oracle:thin:@127.0.0.1:1521:xe
jdbc.user =java
jdbc.password =사용하는 DB 비밀번호 입력

 

mybatis-config.xml

 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

	<properties resource="config/app_config.properties" />

	<settings>
			<!-- table : bo_no vo : boNo 
			전통적인 데이터베이스 칼럼명 형태인
			A_COLUMN을 CamelCase형태의 자바 프로퍼티명 형태인
			aColumn으로 자동으로 매핑하도록 함
			-->
		 <setting name="mapUnderscoreToCamelCase" value="true" />
		
		<!-- JDBC타입을 파라미터에 제공하지 않을때 null값을 처리한 JDBC타입을 명시한다.
		     일부 드라이버는 칼럼의 JDBC타입을 정의하도록 요구하지만
		     대부분은 NULL, VARCHAR 나 OTHER 처럼 일반적인 값을 사용해서 동작한다. -->
		<setting name="jdbcTypeForNull" value="NULL" />
		<!-- 가져온 값이 null일 때 setter나 맵의 put 메소드를 호출할지를 명시
		 Map.keySet() 이나 null값을 초기화할때 유용하다.
		  int, boolean 등과 같은 원시타입은 null을 설정할 수 없다는 점은 알아두면 좋다. -->
		<setting name="callSettersOnNulls" value="true" />
	
	</settings>

  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.user}"/>
        <property name="password" value="${jdbc.password}"/>
      </dataSource>
    </environment>
  </environments>
  
  
  <!-- 작성한 매퍼파일 등록 
  		스프링 연동시 "*" 사용가능 mybatis/mapper/*.xml
  -->
  <mappers>
    <mapper resource="mybatis/mapper/freeboard.xml"/>
  </mappers>
</configuration>

app_config.properties에 있는 jdbc 프로퍼티를 가져온다.

 

 

 

freeboard.xml

 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  
<mapper namespace="com.study.free.dao.IFreeBoardDao">
	
 	<select id="getBoardCount" 
 	resultType="int">
 		SELECT COUNT(*) AS tot 
		 FROM free_board         
		WHERE bo_del_yn ='N'   
 	</select>
	
	<select id="getBoardList" 
	resultType="com.study.free.vo.FreeBoardVO">
 		SELECT bo_no   	
				    , bo_title    
				    , bo_category 
					 ,(SELECT comm_nm from comm_code WHERE comm_cd = bo_category ) as bo_category_nm 
				    , bo_writer  
				    , bo_content 
				    , bo_pass    
				    , bo_ip      
				    , bo_hit     
				    , TO_CHAR(bo_reg_date, 'YYYY-MM-DD') AS bo_reg_date  
				    , TO_CHAR(bo_mod_date, 'YYYY-MM-DD') AS bo_mod_date  
				    , bo_del_yn    
				 FROM free_board   
				 WHERE bo_del_yn = 'N'
				 ORDER BY bo_no DESC 
 	</select>
 	<!-- 프리미티브형(기본형)은 변수 자체에 값을 보유하기 때문에, 이름은 아무렇게해도 되지만
 			의미 있게 짓는게 좋다. -->
 	<select id="getBoard" 
 			parameterType="int" 
 			resultType="com.study.free.vo.FreeBoardVO">
 		SELECT bo_no  
		    , bo_title  
		    , bo_category   
			 ,(SELECT comm_nm from comm_code WHERE comm_cd = bo_category ) as bo_category_nm 
		    , bo_writer  
		    , bo_content  
		    , bo_pass  
		    , bo_ip  
		    , bo_hit  
		    , TO_CHAR(bo_reg_date, 'YYYY-MM-DD-HH24:MI:SS') AS bo_reg_date   
		    , TO_CHAR(bo_mod_date, 'YYYY-MM-DD-HH24:MI:SS') AS bo_mod_date   
		    , bo_del_yn  
		 FROM free_board   
		 WHERE bo_no = #{티스토리짱} 
 	</select>
 	
 	<insert id="insertBoard" parameterType="com.study.free.vo.FreeBoardVO">
 					INSERT INTO free_board (
				      bo_no        
				    , bo_title   
				    , bo_category
				    , bo_writer  
				    , bo_pass    
				    , bo_content 
				    , bo_ip      
				    , bo_hit     
				    , bo_reg_date
				    , bo_del_yn  
				) VALUES (      
				<![CDATA[ 
				      seq_free_board.nextval
				    , #{boTitle}
				    , #{boCategory} 
				    , #{boWriter} 
				    , #{boPass} 
				    , #{boContent} 
				    , #{boIp} 
				     , 0 
				    , SYSDATE 
					 , 'N' ]]>)      
 		
 	</insert>
 	
 	<update id="updateBoard" parameterType="com.study.free.vo.FreeBoardVO">
 		<![CDATA[ 
 		UPDATE free_board 
		 SET bo_title = #{boTitle}        
		    , bo_category = #{boCategory}    
		    , bo_writer = #{boWriter}    
		    , bo_content = #{boContent}   
		    , bo_ip  = #{boIp}    
		    , bo_mod_date = SYSDATE     
		      where bo_no = #{boNo}
 		]]>
 	</update>
 	
 	<delete id="deleteBoard">
 	<![CDATA[
 	 UPDATE free_board
					SET  bo_del_yn = 'Y'    
					WHERE	bo_no = #{boNo}    
 	]]>
 	</delete>
 	
 	<update id="increaseHit" >
 	<![CDATA[
 			UPDATE free_board 
		  	SET bo_Hit = bo_hit + 1   
			WHERE	bo_no = #{은하철도999}    
 	]]>
 	</update>
 	
	
</mapper>

 

![CDATA] :

 

태그 안에서는 전부 문자열로 치환 합니다.

쿼리를 작성 할때 >, < 를 사용하게 되는데 닫힘 태그로 인식하기 때문에 조심해야합니다.

 

예를 들어

 

<select id = "test" resultMap="testMap">


	select test_id
    
    from supertest
    
    where salary > 99
    
</select>

이런 경우 에러가 나는데 그 이유는 where절에 있는 '>'가 닫힘 태그로 인식하기 때문입니다.

 

그래서

 

<select id = "test" resultMap="testMap">

	<![CDATA[
	select test_id
    
    from supertest
    
    where salary > 99
    ]]>
</select>

이렇게 쓰면 문자열로 인식하기 때문에 실행이 됩니다.

 

 

'Back-End > JSP' 카테고리의 다른 글

[JSP] Log4j, slf4j 설치  (0) 2021.07.23
[JSP] 디자인 패턴 및 SOLID 원칙  (0) 2021.07.22
[JSP] 페이징  (0) 2021.07.22
[JSP] 회원 정보 만들기-3  (0) 2021.07.20
[JSP] 회원 정보 만들기-2  (0) 2021.07.20
  Comments,     Trackbacks
[JSP] 디자인 패턴 및 SOLID 원칙

 

디자인 패턴(건축쪽에서 사용하는 용어)

 

 

이름의 중요성.

디자인 패턴이란 기존 환경 내에서 반복적으로 일어나는 문제들을 어떻게 풀어나갈 것인가에 대한 일종의 솔루션 같은 것입니다.
디자인 패턴 계의 교과서로 불리는 [GoF의 디자인패턴]에서는 객체지향적 디자인 패턴의 카테고리를



  "생성 패턴(Creational Pattern)"
  - 객체를 생성하는데 관련된 패턴들
    객체가 생성되는 과정의 유연성을 높이고 코드의 유지를 쉽게 함
    
, "구조 패턴(Structural Pattern)"
  - 프로그램 구조에 관련된 패턴들
    프로그램 내의 자료구조나 인터페이스 구조 등 프로그램의 구조를 설계하는데 활용할 수 있는 패턴들
    
, "행동 패턴(Behavioral Pattern)" 
  - 반복적으로 사용되는 객체들의 상호작용을 패턴화 해놓은 것들
  



3가지로 구분하고 있습니다.


객체지향 소프트웨어를 '잘' 설계한다는 것은 쉬운 일이 아니다.
게다가, 재사용할 수 있는 객체지향 소프트웨어를 만드는 것은 더 힘들기 때문에
설계를 할 때에는 지금 당장 갖고 있는 문제를 해결할 수 있어야 
하지만, 나중에 생길 수 있는 문제나 추가된 요구 사항들도 수용할 수 있도록 일반적이고 포괄적이어야 합니다.

이를 위해 설계할 때 고려사항으로 SOLID 원칙 등 객체지향적 소프트웨어 설계 방법론이 있고, 현업에서는 이에 따라 개발하기 위해 노력하고 있습니다.
개발의 경험이 쌓이다 보면 자신들이 전에 사용했던 코드와 유사한 기능을 구현해야 해서 이전의 코드를 들여다보는 경험을 종종 하게 됩니다.

그러다 전에 사용했던 해결책을 그대로 반복해서 사용하기도 하고, 변형해서 쓰기도 하고, 혹은 상황에 맞지 않다고 판단하여 다른 방향의 구현을 고민하기도 합니다.

디자인 패턴은 설계자로 하여금 재사용이 가능한 설계는 선택하고, 재사용을 방해하는 설계는 배제하도록 도와줍니다.
또한 패턴을 쓰면 이미 만든 시스템의 유지보수나 문서화도 개선할 수 있고, 클래스의 명세도 정확하게 할 수 있으며, 객체 간의 상호작용 또는 설계 의도까지 명확하게 정의할 수 있습니다.
간단하게 말해서 디자인 패턴은 설계자들이 "올바른" 설계를 "빨리" 만들 수 있도록 도와줍니다.

 

 


SOLID 원칙

 

S : SRP(Single Responsiblity Principle 단일 책임 원칙)

 - 소프트웨어의 설계 부품(클래스, 함수 등)은 단 하나의 책임만을 가져야 한다.
 - 응집도는 높고 결합도는 낮은 프로그램을 뜻한다.
 - 하나의 클래스, 메서드에 많은 기능을 넣지 말고, 하나의 기능에 집중
   그렇지 않다면 유지보수 시 너무 힘들다.

 

 

 

O : Open-Closed Principle (개방-패쇄 원칙)


 - 기존의 코드를 변경하지 않고(Closed) 기능을 수정하거나 추가할 수 있도록(Open) 설계해야 한다.
   OCP에 만족하는 설계를 할 때 변경되는 것이 무엇인지에 초점을 맞춘다.
   자주 변경되는 내용은 수정하기 쉽게 설계 하고, 
   변경되지 않아야 하는 것은 수정되는 내용에 영향을 받지 않게 하는 것이 포인트다. 
   이를 위해 자주 사용되는 문법이 인터페이스(Interface)이다.
   유지보수 비용을 줄여주고 코드의 가독성 또한 높아지는 효과를 얻을 수 있다.

 

 

L : Liskov Substitution Principle (리스코프 치환 원칙)
 
 - 자식 클래스는 부모클래스에서 가능한 행위를 수행할 수 있어야 한다.  - 리스코프 치환 원칙은 MIT 컴퓨터 사이

   언스 교수인 리스코프가 제안한 설계 원칙이다.
   부모 클래스와 자식 클래스 사이의 행위에는 일관성이 있어야 한다는 원칙이며,
   이는 객체 지향 프로그래밍에서 부모 클래스의 인스턴스 대신 자식 클래스의 인스터스를 사용해도 문제가 없어야

   한다는 것을 의미한다.

 

 

 

I : Interface Segregation Principle (인터페이스 분리 원칙)

  - 한 클래스는 자신이 사용하지 않는 인터페이스는 구현하지 말아야 한다. 하나의 일반적인 인터페이스보다는,

    여러개의 구체적인 인터페이스가 낫다.
  - 우리는 스마트폰으로 전화, 웹서핑, 사진 촬영 등 다양한 기능을 사용할 수 있다. 
    그런데 전화를 할 때에는 웹서핑, 사진촬영 등 다른 기능은 사용하지 않는다. 
    따라서 전화기능과 웹서핑 기능 사진 촬영 기능은 각각 독립된 인터페이스로 구현하여,
    서로에게 영향을 받지 않도록 설계해야 한다. 
    
  - 이렇게 설계된 소프트웨어는 인터페이스 분리 원칙을 통해 시스템의 내부 의존성을 약화시켜 리팩토링, 수정,

    재배포를 쉽게 할 수 있다.

 

 

D : Dependency Inversion Principle (의존 역전 원칙)

  - 의존 관계를 맺을 때, 변화하기 쉬운것 보단 변화하기 어려운 것에 의존해야 한다는 원칙이다. 
  - 변화하기 어려운 것이란 추상적인 것을 말한다. 
    객체지향적인 관점에서 보자면 변화하기 쉬운것이란 구체화 된 클래스를 의미하고, 변화하기 어려운 것은

    추상클래스나 인터페이스를 의미한다

  - 의존관계를 맺을 때, 구체적인 클래스보다 인터페이스나 추상 클래스와 관계를 맺는다는 것을 의미한다.

 

'Back-End > JSP' 카테고리의 다른 글

[JSP] Log4j, slf4j 설치  (0) 2021.07.23
[JSP] MyBatis Mapper,Log4j,싱글톤 패턴 써보기  (0) 2021.07.23
[JSP] 페이징  (0) 2021.07.22
[JSP] 회원 정보 만들기-3  (0) 2021.07.20
[JSP] 회원 정보 만들기-2  (0) 2021.07.20
  Comments,     Trackbacks
[JSP] 페이징

페이징 자체는 회원목록처럼 코드흐름은 비슷한데

계산도 해야하고 회원리스트에 있는 자바스크립트도 있어 생각을 많이 해야되서

수업 내내 많이 힘들었던 페이징. 선생님, 형의 도움으로 만들었다.

 

CodeDAO, CodeDaoOracle 등등 Member와 같은 이름 같은 흐름이다.

 

 

 

CodeVO.java

package com.study.code.vo;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

public class CodeVO {
	
	private int commOrd;                                  //순번
	private String commParent;                             //부모 코드
	private String commNm;                                //코드명
	private String commCd;                                  //코드
	
	
	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
	}

	public int getCommOrd() {
		return commOrd;
	}

	public void setCommOrd(int commOrd) {
		this.commOrd = commOrd;
	}

	public String getCommParent() {
		return commParent;
	}

	public void setCommParent(String commParent) {
		this.commParent = commParent;
	}

	public String getCommNm() {
		return commNm;
	}

	public void setCommNm(String commNm) {
		this.commNm = commNm;
	}

	public String getCommCd() {
		return commCd;
	}

	public void setCommCd(String commCd) {
		this.commCd = commCd;
	}
}

 

ICodeDao.java

 

package com.study.code.dao;

import java.sql.Connection;
import java.util.List;

import com.study.code.vo.CodeVO;

public interface ICodeDao {
	/**
	 * <b>공통코드에 조회목록을 리턴한다.</b>
	 *  
	 * @param conn
	 * @param code
	 * @return 코드목록 List<CodeVO>
	 * @throws DaoException	
	 */
	public List<CodeVO> getCodeListByParent(Connection conn, String parentCode);
	
}

 

 

ICodeService.java

 

package com.study.code.service;

import java.util.List;

import com.study.code.vo.CodeVO;

public interface ICodeService {
	
	/**
	 * <b>공통코드에 조회목록을 리턴한다.</b>
	 *  
	 * @param parentCode
	 * @return 코드목록 List<CodeVO>
	 */
	List<CodeVO> getCodeListByParent(String parentCode) ;
	
}

 

CodeDaoOracle.java

 

package com.study.code.dao;

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 com.study.code.vo.CodeVO;

public class CodeDaoOracle implements ICodeDao{

	@Override
	public List<CodeVO> getCodeListByParent(Connection conn, String parentCode) {
		//코드VO가 들어있는 List를 반환하겠다.
		// 변수 선언
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		StringBuilder sb = new StringBuilder();
		List<CodeVO> list = new ArrayList<CodeVO>();

		sb.append("	SELECT comm_cd 	");
		sb.append("     , comm_nm		"); 
		sb.append("     , comm_parent ");
		sb.append("     , comm_ord 	");
		sb.append("     FROM comm_code ");
		sb.append("     WHERE comm_parent = ? ");
		sb.append("     ORDER BY comm_ord ASC ");
		
		System.out.println(sb.toString());
		
		try {
			// 3. 구문 객체 생성
			pstmt = conn.prepareStatement(sb.toString());
			//바인드변수 
			pstmt.setString(1, parentCode);
			
			rs = pstmt.executeQuery();
			while(rs.next()) { // ResultSet 은 next밖에 못
				CodeVO code = new CodeVO();
				code.setCommCd(rs.getString("comm_cd"));
				code.setCommNm(rs.getString("comm_nm"));
				code.setCommParent(rs.getString("comm_parent"));
				code.setCommOrd(rs.getInt("comm_ord"));
				list.add(code);
			}
			//res = pstmt.executeUpdate();
			return list;
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e);
		} finally {
			// 자원종료
			if (rs != null) try {rs.close();} catch (SQLException e) {}
			if (pstmt != null) try {pstmt.close();} catch (SQLException e) {}
		}
	}
}

 

 

 

CodeServiceImpl.java

 

package com.study.code.service;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;

import com.study.exception.BizNotFoundException;
import com.study.exception.BizPasswordNotMatchedException;

import com.study.code.dao.CodeDaoOracle;
import com.study.code.dao.ICodeDao;
import com.study.code.vo.CodeVO;
;

public class CodeServiceImpl implements ICodeService{
	
	private ICodeDao codeDao = new CodeDaoOracle();
	private String JDBC_URL = "jdbc:apache:commons:dbcp:study";
	
	@Override
	
	public List<CodeVO> getCodeListByParent(String parentCode) {
		
		Connection conn = null;
		try {
			conn = DriverManager.getConnection(JDBC_URL);
			
			//conn.setAutoCommit(false);
			List<CodeVO> list = codeDao.getCodeListByParent(conn, parentCode);
			
			return list;
		} catch (SQLException e) {
			e.printStackTrace();
			try {conn.rollback();} catch (SQLException e2) {}
			throw new RuntimeException(e.getMessage(), e);
		}finally {
			if (conn != null) try {conn.close();} catch (SQLException e) {}
		}	
	}
}

 

만들어 주고 페이징은 getMemberList와 밀접한 연관이 있기 때문에 Member나 Free List에 있는 네임이나 쿼리, 조건을

바꿔줘야 한다.

그리고 getMemberCount도 바꿔줘야 한다.

 

MemberDaoOracle.java (getMemberCount)

 

 

@Override
	public int getMemberCount(Connection conn, MemberSearchVO searchVO) {
		// 변수 선언
				PreparedStatement pstmt = null;
				ResultSet rs = null;
				StringBuilder sb = new StringBuilder();

				// SQL 구문
				sb.append(" SELECT COUNT(*) AS tot         ");
				sb.append(" FROM member         		 ");
				sb.append(" WHERE 1 = 1          ");
				//sb.append(" WHERE bo_del_yn ='N'          ");
				
				//검색은 물음표
				//삭제때문에 쓴 append WHERE 삭제여부가 N 인 것만 출력
				//그렇다면 삭제는 'Y'인건 안보이게 하면 된다.
				
				
				if (StringUtils.isNotBlank(searchVO.getSearchWord())) {
					switch (searchVO.getSearchType()) {
					case "I":
						sb.append(" AND mem_id LIKE '%' || ? || '%'  ");
						break;
					case "M":
						sb.append(" AND mem_name LIKE '%' || ? || '%'  ");
						break;
					case "P":
						sb.append(" AND mem_hp LIKE '%' || ? || '%'  ");
						break;
					default:
						sb.append(" AND mem_id LIKE '%' || ? || '%'  ");
						break;
					}
				}
				// 분류(searchCategory)가 존재하면

				if (StringUtils.isNotBlank(searchVO.getSearchLike())) {
					sb.append(" AND mem_like = ? ");
				}
				if (StringUtils.isNotBlank(searchVO.getSearchJob())) {
					sb.append(" AND mem_job = ? ");
				}
				

				
				
				
				System.out.println(sb.toString());
				try {
					// 3. 구문 객체 생성
					pstmt = conn.prepareStatement(sb.toString());
					
					int idx = 1;
					if (StringUtils.isNotBlank(searchVO.getSearchWord())) {
						pstmt.setString(idx++, searchVO.getSearchWord());
					}
					// 분류(searchCategory)가 존재하면
					
					if (StringUtils.isNotBlank(searchVO.getSearchJob())) {
						pstmt.setString(idx++, searchVO.getSearchJob());
					}
					if (StringUtils.isNotBlank(searchVO.getSearchLike())) {
						pstmt.setString(idx++, searchVO.getSearchLike());
					}
					
					rs = pstmt.executeQuery();
					
					int tot = 0;
					if(rs.next()) {
						
						tot = rs.getInt(1); //레코드 전체 수 int로
					}
					return tot;
				} catch (SQLException e) {
					e.printStackTrace();
					throw new RuntimeException(e.getMessage(), e);
				} finally {
					// 자원종료
					if (rs != null) try {rs.close();} catch (SQLException e) {}
					if (pstmt != null) try {pstmt.close();} catch (SQLException e) {}
				}
			}

 

MemberDaoOracle.java (getMemberList)

 

@Override
	public List<MemberVO> getMemberList(Connection conn, MemberSearchVO searchVO) {
		// 변수 선언
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		StringBuilder sb = new StringBuilder();
		List<MemberVO> list = new ArrayList<MemberVO>();

		// SQL 구문
		//페이징 쿼리 추가
		sb.append("SELECT * ");
		sb.append("FROM ( SELECT rownum AS rnum ");
		sb.append("				, a.* ");
		//a.*  : 어느 테이블의 모든 것
		sb.append("		FROM (        ");
		
		sb.append("SELECT mem_id      ");
		sb.append("     , mem_name    ");
		sb.append("     , mem_pass    ");
		sb.append("     , mem_zip     ");
		sb.append("     , mem_add1    ");
		sb.append("     , mem_add2    ");
		sb.append("     , mem_hp      ");
		sb.append("     , mem_mail    ");
		sb.append("     , mem_job     ");
		sb.append("     , (SELECT comm_nm from comm_code WHERE mem_job = comm_cd ) as mem_job_nm ");
		sb.append("     , (SELECT comm_nm from comm_code WHERE mem_like = comm_cd ) as mem_like_nm ");
		sb.append("     , mem_mileage ");
		sb.append("     , mem_delete  ");
		sb.append("  FROM member      ");
		sb.append("  WHERE 1 = 1 ");
        //조건을 무조건 줘야한다. 밑에 AND이라서 조건이 없으면 오류.
        //그래서 조건이 무조건 참인것을 끼워 넣는다.
		if (StringUtils.isNotBlank(searchVO.getSearchWord())) {
			switch (searchVO.getSearchType()) {
			case "I":
				sb.append(" AND mem_id LIKE '%' || ? || '%'  ");
				break;
			case "M":
				sb.append(" AND mem_name LIKE '%' || ? || '%'  ");
				break;
			case "P":
				sb.append(" AND mem_hp LIKE '%' || ? || '%'  ");
				break;
			default:
				sb.append(" AND mem_hp LIKE '%' || ? || '%'  ");
				break;
			}
		}
		// 분류(searchCategory)가 존재하면

		if (StringUtils.isNotBlank(searchVO.getSearchJob())) {
//			sb.append(" AND mem_id = ? ");
			sb.append(" AND mem_job = ? ");
		}
		if (StringUtils.isNotBlank(searchVO.getSearchLike())) {
//			sb.append(" AND mem_id = ? ");
			sb.append(" AND mem_like = ? ");
		}
		sb.append(" ORDER BY mem_id ");
		sb.append("  			) a " );
		sb.append("  	where rownum <= ?  ");
		sb.append("  ) b  			       ");
		sb.append("  where rnum BETWEEN ? AND ?  ");
		//삭제때문에 쓴 append WHERE 삭제여부가 N 인 것만 출력
		//그렇다면 삭제는 'Y'인건 안보이게 하면 된다.
		System.out.println(sb.toString());
		
		try {
			// 3. 구문 객체 생성
			pstmt = conn.prepareStatement(sb.toString());
			int idx = 1;
			if (StringUtils.isNotBlank(searchVO.getSearchWord())) {
				pstmt.setString(idx++, searchVO.getSearchWord());
			}
			if (StringUtils.isNotBlank(searchVO.getSearchJob())) {
				pstmt.setString(idx++, searchVO.getSearchJob());
			} 
			if (StringUtils.isNotBlank(searchVO.getSearchLike())) {
				pstmt.setString(idx++, searchVO.getSearchLike());
			} 

			// 4. 바인드 변수 설정
			pstmt.setInt(idx++, searchVO.getEndRow());
			pstmt.setInt(idx++, searchVO.getStartRow());
			pstmt.setInt(idx++, searchVO.getEndRow());
			// 5. 구문객체 실행
			rs = pstmt.executeQuery();
			while(rs.next()) { // ResultSet 은 next밖에 못한다.
				MemberVO member = new MemberVO();
				member.setMemId(rs.getString("mem_id"));
				member.setMemName(rs.getString("mem_name"));
				member.setMemZip(rs.getString("mem_zip"));
				member.setMemAdd1(rs.getString("mem_add1"));
				member.setMemAdd2(rs.getString("mem_add2"));
				member.setMemHp(rs.getString("mem_hp"));
				member.setMemMail(rs.getString("mem_mail"));
				member.setMemJob(rs.getString("mem_job"));
				member.setMemJobnm(rs.getString("mem_job_nm"));
				member.setMemLikenm(rs.getString("mem_like_nm"));
				member.setMemLikenm(rs.getString("mem_mileage"));
				member.setMemLikenm(rs.getString("mem_delete"));
				list.add(member);
			}
			return list;
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e);
		} finally {
			// 자원종료
			if (rs != null) try {rs.close();} catch (SQLException e) {}
			if (pstmt != null) try {pstmt.close();} catch (SQLException e) {}
		}
	}

 

 

  Comments,     Trackbacks
[JSP] 회원 정보 만들기-3

게시판의 꽃 페이징.


몇 개의 게시글로 page를 나눌 것인가

 

게시글 수 만큼 page 번호가 존재할 것인가

 

고정된 page 번호를 보여줄 것인가

 


PagingVO.java

package com.study.common.vo;

import java.io.Serializable;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

@SuppressWarnings("serial")
public class PagingVO implements Serializable {
	
	//--외부로부터 받는 것 (게터 세터가 있다는 것 ) 게터 세터가 있어야 받을꺼니깐.
	private int curPage;          // 현재 페이지 번호
	private int rowSizePerPage;   // 한 페이지당 레코드 수
	private int totalPageCount;   // 총 페이지 건수
	private int pageSize;   // 페이지 리스트에서 보여줄 페이지 갯수
	
	
	 // --내부에서 계산 (getter) 왜? 사용자로부터 받는게 없기 때
	private int startRow ;        // 시작 레크드 번호   
	private int endRow;          // 마지막 레크드 번호 
	private int totalRowCount ;   // 총 레코드 건수
	
	
	private int startPage;  // 페이지 리스트에서 시작  페이지 번호 
	private int endPage;   // 페이지 리스트에서 마지막 페이지 번호 
	
	/**
	 * 입력 받은 변수를 기반으로
	 * 페이징 관련 변수 계산 
	 */
	public void setting() {
		if(rowSizePerPage < 1) rowSizePerPage = 10;
		if(curPage < 1) curPage = 1;
		if(pageSize < 1) pageSize = 10;
		 
		 //totalPageCount = (int)Math.ceil(totalRowCount /rowSizePerPage); //현재 33이 되야 함
		 totalPageCount = (totalRowCount - 1) / rowSizePerPage + 1; //현재 33이 되야 함
		 System.out.println("totalPageCount = " +totalPageCount);
		 startRow = (curPage -1) * rowSizePerPage + 1;
		 //curPage * rowSizePerPage
		 endRow = startRow + rowSizePerPage - 1 ; // curPage + rowSizePerPage
		 System.out.println("curPage = " +curPage);
		 System.out.println("pageSize = " +pageSize);
		 
		 startPage = (curPage -1) /pageSize * pageSize + 1; //11
		 endPage = startPage + pageSize - 1 ; //15
		 if(endPage > totalPageCount) endPage = totalPageCount;
		 
    }

	public int getCurPage() {
		return curPage;
	}
	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
	}
	public void setCurPage(int curPage) {
		this.curPage = curPage;
	}

	public int getRowSizePerPage() {
		return rowSizePerPage;
	}

	public void setRowSizePerPage(int rowSizePerPage) {
		this.rowSizePerPage = rowSizePerPage;
	}

	public int getTotalPageCount() {
		return totalPageCount;
	}

	public void setTotalPageCount(int totalPageCount) {
		this.totalPageCount = totalPageCount;
	}

	public int getPageSize() {
		return pageSize;
	}

	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}

	public int getStartRow() {
		return startRow;
	}

	public void setStartRow(int startRow) {
		this.startRow = startRow;
	}

	public int getEndRow() {
		return endRow;
	}

	public void setEndRow(int endRow) {
		this.endRow = endRow;
	}

	public int getTotalRowCount() {
		return totalRowCount;
	}

	public void setTotalRowCount(int totalRowCount) {
		this.totalRowCount = totalRowCount;
	}

	public int getStartPage() {
		return startPage;
	}

	public void setStartPage(int startPage) {
		this.startPage = startPage;
	}

	public int getEndPage() {
		return endPage;
	}

	public void setEndPage(int endPage) {
		this.endPage = endPage;
	}
	
	
}

 

 

CodeVO.java

 

 

 

package com.study.code.vo;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

public class CodeVO {
	
	private int commOrd;                                  //순번
	private String commParent;                             //부모 코드
	private String commNm;                                //코드명
	private String commCd;                                  //코드
	
	
	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
	}

	public int getCommOrd() {
		return commOrd;
	}

	public void setCommOrd(int commOrd) {
		this.commOrd = commOrd;
	}

	public String getCommParent() {
		return commParent;
	}

	public void setCommParent(String commParent) {
		this.commParent = commParent;
	}

	public String getCommNm() {
		return commNm;
	}

	public void setCommNm(String commNm) {
		this.commNm = commNm;
	}

	public String getCommCd() {
		return commCd;
	}

	public void setCommCd(String commCd) {
		this.commCd = commCd;
	}
}

 

 

CodeServiceImpl.java

 

 

package com.study.code.service;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;

import com.study.exception.BizNotFoundException;
import com.study.exception.BizPasswordNotMatchedException;

import com.study.code.dao.CodeDaoOracle;
import com.study.code.dao.ICodeDao;
import com.study.code.vo.CodeVO;
;

public class CodeServiceImpl implements ICodeService{
	
	private ICodeDao codeDao = new CodeDaoOracle();
	private String JDBC_URL = "jdbc:apache:commons:dbcp:study";
	
	@Override
	
	public List<CodeVO> getCodeListByParent(String parentCode) {
		
		Connection conn = null;
		try {
			conn = DriverManager.getConnection(JDBC_URL);
			
			//conn.setAutoCommit(false);
			List<CodeVO> list = codeDao.getCodeListByParent(conn, parentCode);
			
			return list;
		} catch (SQLException e) {
			e.printStackTrace();
			try {conn.rollback();} catch (SQLException e2) {}
			throw new RuntimeException(e.getMessage(), e);
		}finally {
			if (conn != null) try {conn.close();} catch (SQLException e) {}
		}	
	}
}

 

 

공부해서 다시 추가해 올릴 예정

'Back-End > JSP' 카테고리의 다른 글

[JSP] 디자인 패턴 및 SOLID 원칙  (0) 2021.07.22
[JSP] 페이징  (0) 2021.07.22
[JSP] 회원 정보 만들기-2  (0) 2021.07.20
[JSP] 회원 정보 만들기-1  (0) 2021.07.20
[JSP] 회원 정보 만들기 전  (0) 2021.07.16
  Comments,     Trackbacks
[JSP] 회원 정보 만들기-2

 

 

페이징부터 멘붕이 와서ㅠㅠ 일단은 쓰고 나중에 다시 이해 한 후 주석을 달 예정이다.

 

 

MemberList.jsp

 

<%@page import="com.study.code.vo.CodeVO"%>
<%@page import="com.study.code.service.CodeServiceImpl"%>
<%@page import="com.study.code.service.ICodeService"%>
<%@page import="com.study.member.vo.MemberVO"%>
<%@page import="com.study.member.service.MemberServiceImpl"%>
<%@page import="com.study.member.service.IMemberService"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<%
	request.setCharacterEncoding("UTF-8");
%>

<!DOCTYPE html>
<html lang="ko">
<head>
<%@include file="/WEB-INF/inc/header.jsp"%>
<meta charset="UTF-8">
<title></title>
</head>
<body>
	<%@include file="/WEB-INF/inc/top.jsp"%>
	<div class="container">
		<div class = "page-header">
		<h3>회원목록 </h3> </div>
		
		<jsp:useBean id="searchVO" class="com.study.member.vo.MemberSearchVO" />
		<jsp:setProperty property="*" name="searchVO" />
		
		<%
			IMemberService memberService = new MemberServiceImpl();
			searchVO.setTotalRowCount(memberService.getMemberCount(searchVO)); //175같은거 넣
			searchVO.setting();

			List<MemberVO> r = memberService.getMemberList(searchVO);
			request.setAttribute("results", r);
		%>
		
		
		<%
		ICodeService codeService = new CodeServiceImpl();
		List<CodeVO> categories = codeService.getCodeListByParent("BC00");
		List<CodeVO> jobs = codeService.getCodeListByParent("JB00");
		List<CodeVO> hobbies = codeService.getCodeListByParent("HB00");
		request.setAttribute("categories", categories);
		request.setAttribute("jobs", jobs);
		request.setAttribute("hobbies", hobbies);
		%>
        
		<pre>
		${searchVO}
		</pre>
	<!-- START : 검색 폼  -->
	<div class="panel panel-default">
			<div class="panel-body">
				<form name="frm_search" action="freeList.jsp" method="post"
					class="form-horizontal">
					
					<input type="text" name="curPage" value="${searchVO.curPage}"> <input
						type="text" name="rowSizePerPage" value="${searchVO.rowSizePerPage}">
						
					<div class="form-group">
						<label for="id_searchType" class="col-sm-2 control-label">검색</label>
						<div class="col-sm-2">
							<select id="id_searchType" name="searchType"
								class="form-control input-sm">
								<option value="T">아이디</option>
								<option value="W">회원명</option>
								<option value="C">연락</option>
							</select>
						</div>
						<div class="col-sm-3">
							<input type="text" name="searchWord"
								class="form-control input-sm" value="" placeholder="검색어">
						</div>
						<label for="id_searchCategory"
							class="col-sm-2 col-sm-offset-2 control-label">분류</label>
						<div class="col-sm-2">
							<select id="id_searchCategory" name="searchCategory"
								class="form-control input-sm">
								<option value="">-- 직업 전체 --</option>
								<c:forEach items="${jobs}" var="code">
									<option value="${code.commCd}">${code.commNm}</option>
								</c:forEach>
							</select>
						</div>
						<!-- 취미 카테고리 -->
						<div class="col-sm-2">
							<select id="id_searchCategory" name="searchCategory"
								class="form-control input-sm">
								<option value="">-- 취미 전체 --</option>
								<c:forEach items="${hobbies}" var="code">
									<option value="${code.commCd}">${code.commNm}</option>
								</c:forEach>
							</select>
						</div>
					</div>
					<div class="form-group">
						<div class="col-sm-2 col-sm-offset-9 text-right">
							<button type="button" id="id_btn_reset"
								class="btn btn-sm btn-default">
								<i class="fa fa-sync"></i> &nbsp;&nbsp;초기화
							</button>
						</div>
						<div class="col-sm-1 text-right">
							<button type="submit" class="btn btn-sm btn-primary ">
								<i class="fa fa-search"></i> &nbsp;&nbsp;검 색
							</button>
						</div>
					</div>
				</form>
			</div>
		</div>
		<div class="pull-right">
			<a href="memberForm.jsp" class = "btn btn-sm btn-primary"
			style ="margin-bottom:80px;">
			<i class = "glyphicon glyphicon-plus"></i>회원가입</a>
		</div>
		<!-- START : 목록건수 및 새글쓰기 버튼  -->
		<div class="row mb-10">
			<div class="col-sm-3 form-inline">
				전체 ${searchVO.totalRowCount} 건 조회 <select id="id_rowSizePerPage" name="rowSizePerPage"
					class="form-control input-sm">
					<option value="10" ${searchVO.rowSizePerPage eq 10 ? 'selected="selected"' : ''}>10</option>
					<option value="20" ${searchVO.rowSizePerPage eq 20 ? 'selected="selected"' : ''}>20</option>
					<option value="30" ${searchVO.rowSizePerPage eq 30 ? 'selected="selected"' : ''}>30</option>
					<option value="50" ${searchVO.rowSizePerPage eq 50 ? 'selected="selected"' : ''}>50</option>
				</select>
			</div>
			<div class="col-sm-2 col-sm-offset-7 text-right">
				
				<button type = "submit">눌러봐.</button>
			</div>
		</div>
		<!-- END : 목록건수 및 새글쓰기 버튼  -->
		<div class="grid">
			<table class="table table-bordered border-primary">
				<colgroup>
					<col style="width: 15%" />
					<col style="width: 15%" />
					<col />
					<col style="width: 20%" />
					<col style="width: 15%" />
				</colgroup>
				<thead class="table-dark">
					<tr>
						<th>아이디</th>
						<th>회원명</th>
						<th>주소</th>
						<th>직업</th>
						<th>연락처</th>
					</tr>
				</thead>
				<tbody>
				
				
				<c:forEach items="${results}" var="vo">
					<tr>
						<td>${vo.memId}</td>
						<td><a href="memberView.jsp?memId=${vo.memId}">
						${vo.memName}</a></td>
						
						<td>${vo.memAdd1}${vo.memAdd2}</td>
						<td>${vo.memJobnm}</td>
						<td>${vo.memHp}</td>
					</tr>
					</c:forEach>
					
		</tbody>
				
			</table>
		</div>
		<nav>
			<ul class="pagination">
				<!-- 이전페이지 if(startPage -1) -->
		 		<c:if test="${searchVO.startPage > 1}">
					<li><a href="memberList.jsp?curPage=${searchVO.startPage-1}" 
					data-page="${searchVO.startPage-1}"
						aria-label="Previous"> <span aria-hidden="true">&laquo;</span>
					</a></li>
				</c:if>

				<c:forEach begin="${searchVO.startPage}" end="${searchVO.endPage}"
					var="i">
					<!-- 만약 i하고 curPage가 같으면  )-->
					<c:if test="${i eq searchVO.curPage}">
						<li class="active"><a>${i}</a></li>
					</c:if>

					<c:if test="${i ne searchVO.curPage}">
						<li><a href="memberList.jsp?curPage=${i}">${i}</a></li>
					</c:if>
					<!-- "freeList.jsp 없어도 된다. -->
				</c:forEach>

				<!-- 다음 페이지  -->
			 	<c:if test="${searchVO.endPage < searchVO.totalPageCount}">
					<li><a href="freeList.jsp?curPage=${searchVO.endPage+1}"
					data-page="${searchVO.endPage+1}" aria-label="Next">
					<span aria-hidden="true">&raquo;</span> 
					</a></li>
				</c:if> 
			</ul>
		</nav>

		<!--  //end .pagination-->
		</div>
		<!-- end grid -->
			<!--end.container -->
			<script type="text/javascript">
	
	// -- 전역 변수 설정
	//자바스크립트객체하고 jQuery 객체하고 구분하기 위해 jQuery 객체 변수는 $fh 시작
	$frm = $('form[name=frm_search]');
	
	// --일반 함수 설정
	var fn_frm_submit = function(p,r){
		console.log('p',p);
		console.log('r',r);
		$frm.find('input[name=curPage]').val(p);
		$frm.submit();
	}
	
	
	
	// --이벤트 함수 설정
	
	// $frm 서브밋 이벤트가 발생 할 때
	// curPage = 1로 변경 후 서브밋
	 $('button[type=submit]' ,$frm).click(function(e) {
		 e.preventDefault();
		 //먼저 막고
		$frm.find("input[name=curPage]").val(1);
	    $frm.submit();
	});

	// id_btn_reset 클릭 할 때
	//curPage = 1
	//모든 객체는 초기화 해주면 됨
	
	
	//페이지네이션의 a 링크 클릭 
	$('nav ul.pagination a[data-page]').click(function(e){
	    e.preventDefault();
	    
	    $this = $(this);
	    // console.log('this', this.dataset.page); //javascript 객체
	    // console.log('$this',$this.data('page') ); //jQuery 객체
	    $frm.find("input[name=curPage]").val($this.data('page'));
	    $frm.submit();
	}); // end 'nav ul.pagination a[data-page]').click
	
	
	
		// 로우 사이즈 변경
		
		$('#id_rowSizePerPage').change(function(e){
			e.preventDefault();
			$this = $(this);
			console.log('select val', $this.val());
			$frm.find("input[name=curPage]").val(1);
			$frm.find("input[name=rowSizePerPage]").val($this.val());
			$frm.submit();
			});

	</script>
</body>
</html>

 

MemberEdit.jsp

 

 

<%@page import="com.study.exception.BizNotFoundException"%>
<%@page import="com.study.code.vo.CodeVO"%>
<%@page import="java.util.List"%>
<%@page import="com.study.code.service.ICodeService"%>
<%@page import="com.study.code.service.CodeServiceImpl"%>
<%@page import="com.study.free.vo.FreeBoardVO"%>
<%@page import="com.study.free.service.IFreeBoardService"%>
<%@page import="com.study.free.service.FreeBoardServiceImpl"%>
<%@page import="com.study.member.vo.MemberVO"%>
<%@page import="com.study.member.service.MemberServiceImpl"%>
<%@page import="com.study.member.service.IMemberService"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ page import="java.sql.*"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%
	request.setCharacterEncoding("UTF-8");
%>
<!DOCTYPE html>
<html lang="ko">

<head>
<%@ include file="/WEB-INF/inc/header.jsp"%>
<title>memberForm.jsp</title>
</head>
<body>
	<%@include file="/WEB-INF/inc/top.jsp"%>
	<div class="container">
		<%

			//memId가 없다면 예외처리 있다면 다시 홈으로 이동.
			String memId = request.getParameter("memId");
			if (memId == null || "".equals(memId)) {
				response.sendRedirect("memberList.jsp");
				return;
			}
			try {
				ICodeService codeService = new CodeServiceImpl();
				List<CodeVO> categories = codeService.getCodeListByParent("BC00");
				request.setAttribute("categories", categories);
				IMemberService  memberService = new MemberServiceImpl();
				MemberVO member = memberService.getMember(memId);
				request.setAttribute("member", member);
			
			}catch(BizNotFoundException ex){
				request.setAttribute("ex", ex);
			}
		%>
		<div>
			<div class="page-header">
				<h3>수정하기</h3>
			</div>
			<c:if test="${not empty member}">
			<form action="memberModify.jsp" method="GET">
				<table class="table">
					<tbody>
						<tr>
							<th>아이디</th>
							<td><input type="hidden"
								name="memId" class="form-control"
								value="${member.memId}"></td>
						</tr>
						<tr>
							<th>회원명</th>
							<td><input type="text" name="memName"
								class="form-control input-sm"
								value="${member.memName}"></td>
						</tr>
						<tr>
							<th>생일</th>
							<td><input type="date" name="memBir"
								class="form-control input-sm"
								value="${member.memBir}"></td>
						</tr>
						<tr>
							<th>우편번호</th>
							<td><input type="text" name="memZip"
								class="form-control input-sm"
								value="${member.memZip}"></td>
						</tr>
						<tr>
							<th>주소</th>
							<td><input type="tel" name="memAdd1"
								class="form-control input-sm"
								value="${member.memAdd1}"> <input
								type="tel" name="memAdd2" class="form-control input-sm"
								value="${member.memAdd2}"></td>
						</tr>
						<tr>
							<th>헨드폰</th>
							<td><input type="tel" name="memHp"
								class="form-control input-sm"
								value="${member.memHp}"></td>
						</tr>
						<tr>
							<th>메일</th>
							<td><input type="email" name="memMail"
								class="form-control input-sm" value = "${member.memMail}"/></td>
						</tr>
						<tr>
							<th>직업</th>
			<td>
				<c:set var = "memJob" value = "${member.memJob} " />
				<c:set var = "memLike" value = "${member.memLike} " />
				
				<select name="boCategory" class="form-control input-sm" required="required">
					<option value="">-- 직업 선택--</option>
					<c:forEach items = "${jobs}" var = "code">
										<!-- $memJob eq code.commCd ? "selected=\'selected\'" : ""%> -->
						<option value = "${code.commCd}">$memJob eq code.commCd ? "selected=\'selected\'" : ""%> </option>
					</c:forEach>	
					</select>	</td>
					</tr>
						<tr>
							<th>취미</th>
			<td>
				<select name="boCategory" class="form-control input-sm" required="required">
					<option value="">-- 취미 선택--</option>
					<c:forEach items = "${hobbies}" var = "code">
						<option value = "${code.commCd}">${code.commCd}">$memLike eq code.commCd ? "selected=\'selected\'" : ""%> </option>
					</c:forEach>	
					</select>	</td>
					</tr>
						<tr>
							<th>마일리지</th>
							<td>${member.memMileage}</td>
						</tr>
					</tbody>
				</table>
				</c:if>
				<c:if test="${empty member}">
				<div class="panel panel-sucess">
					<div class="panel-heading">회원가입실패
					<div class="panel-body"></div>
					</div>
					</div>
					</c:if>
					
					<div>
						<div class="pull-left">
							<a href="memberList.jsp" class="glyphicon glyphicon-list"> 
							<i class = "glyphicon glyphicon-list"></i>&nbsp;목록으로
							</a>
						</div>
						<div class="pull-right">
							<button type = "submit" class="btn btn-sm-primary">
							<i class="glyphicon glyphicon-save"></i>&nbsp;수정
								</button>
						</div>
					</div>
			</form>
		</div>
	</div>
</body>
</html>

 

 

MeberForm.jsp

 

 

<%@page import="com.study.code.vo.CodeVO"%>
<%@page import="java.util.List"%>
<%@page import="com.study.code.service.CodeServiceImpl"%>
<%@page import="com.study.code.service.ICodeService"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import = "java.sql.*" %>
<%@ taglib prefix = "c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%
	request.setCharacterEncoding("UTF-8");    	
%>
<!DOCTYPE html>
<html lang="ko">

<head>
	<%@ include file="/WEB-INF/inc/header.jsp" %>
	<title>memberForm.jsp </title>
</head>
<body>
<%@include file = "/WEB-INF/inc/top.jsp" %>
<div class = "container">
 <div>	
 	<div class ="page-header">
	<h3>회원가입</h3>		
</div>
<%
		ICodeService codeService = new CodeServiceImpl();
		List<CodeVO> categories = codeService.getCodeListByParent("BC00");
		List<CodeVO> jobs = codeService.getCodeListByParent("JB00");
		//Dao가 JBOO을 받아서 
		List<CodeVO> hobbies = codeService.getCodeListByParent("HB00");
		request.setAttribute("categories", categories);
		request.setAttribute("jobs", jobs);
		//jobs가 담긴건 List<CodeVO> jobs 
		request.setAttribute("hobbies", hobbies);
	
%>
	<form action="memberRegist.jsp" method="GET" >
	<table class = "table">
		<tbody>
			<tr>
				<th>아이디</th>
				<td><input type="text" name="memId"  class ="form-control"></td>
			</tr>
			<tr>
				<th>비밀번호</th>
				<td><input type="password" name="memPass" class="form-control input-sm"></td>
			</tr>
			<tr>
				<th>회원명</th>
				<td><input type="text" name="memName" class="form-control input-sm"></td>
			</tr>
			<tr>
				<th>생일</th>
				<td><input type="date" name="memBir" class="form-control input-sm"></td>
			</tr>
			<tr>
				<th>우편번호</th>
					<td><input type="text" name="memZip" class="form-control input-sm"></td>
				</tr>
			<tr>
				<th>주소</th>
				<td><input type="tel" name="memAdd1" class="form-control input-sm"><input type="tel" name="memAdd2" class="form-control input-sm"></td>
			</tr>
			<tr>
				<th>헨드폰</th>
				<td><input type="tel" name="memHp" class="form-control input-sm"></td>
			</tr>
			<tr>
				<th>메일</th>
					<td><input type="tel" name="memMail" class="form-control input-sm"></td>
				</tr>
			<tr>
				<th>직업</th>
			<td>
				<select name="boCategory" class="form-control input-sm" required="required">
					<option value="">-- 직업 선택--</option>
					<c:forEach items = "${jobs}" var = "code">
						<option value = "${code.commCd}">${code.commNm} </option>
					</c:forEach>	
					</select>	</td>
					</tr>
			<tr>
				<th>취미</th>
			<td>
				<select name="boCategory" class="form-control input-sm" required="required">
					<option value="">-- 취미 선택--</option>
					<c:forEach items = "${hobbies}" var = "code">
						<option value = "${code.commCd}">${code.commNm} </option>
					</c:forEach>	
					</select>	</td>
					</tr>
		</tbody>	
	</table>
	<div>
	<div class = "pull-left">
		<a href = "memberList.jsp">
		<i class = "glyphicon glyphicon-list"></i>
		&nbsp;목록으로</a>
	</div>
	<div class ="pull-right">
	<button type="submit" class="btn btn-sm btn-primary">
	<i class = "glyphicon glyphicon-save"></i>
	<i class = "glyphicon glyphicon-user"></i>
		&nbsp;회원가입
		</button>
		</div>
	</div>
	</form>
</div>
</div>
</body>
</html>

 

 

MemberModify.jsp

 

 

<%@page import="com.study.member.service.MemberServiceImpl"%>
<%@page import="com.study.member.service.IMemberService"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<%
	request.setCharacterEncoding("UTF-8");
%>
<!DOCTYPE html>
<html lang="ko">
<head>
<%@include file="/WEB-INF/inc/header.jsp"%>
<meta charset="UTF-8">
<title></title>
</head>
<body>
	<%@include file="/WEB-INF/inc/top.jsp"%>
	<div class="container">

		<jsp:useBean id="member" class="com.study.member.vo.MemberVO"/>
		<jsp:setProperty property="*" name="member" />
		<% // 각 프로퍼티의 값을 같은 이름을 갖는 파라미터를 다 가져온다. %>
		<pre>${member}</pre>
		<% 
		//변수 선언	
		String memId = request.getParameter("memId");
		if (memId == null || "".equals(memId)) 
		{
			response.sendRedirect("memberList.jsp");
			return;
		}
		%>
		<c:catch var="ex">
		
		<%
		IMemberService memberService = new MemberServiceImpl();
			memberService.modifyMember(member);
		%>
		
		
		<div class="panel panel-sucess">
			<div class="panel-heading">수정성공
			<div class="panel-body"></div>
			추카해요!!</div>
		</div>
	</c:catch>
		<c:if test="${not empty ex}">
		<div class="panel panel-default">
			<div class="panel-heading">
			수정실패</div>
			<div class="panel-body"></div>
		</div>
	</div>
	</c:if>
	<div class="pull-left">
				<a href="memberList.jsp" class="btn btn-sm btn-default"> 
				<i class="glyphicon glyphicon-list"></i> &nbsp;목록으로
				</a>
			</div>
			<!--end.container -->
</body>
</html>

 

 

MemberRegist.jsp

 

 

 

<%@page import="com.study.member.service.MemberServiceImpl"%>
<%@page import="com.study.member.vo.MemberVO"%>
<%@page import="com.study.member.service.IMemberService"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<%
	request.setCharacterEncoding("UTF-8");
%>
<!DOCTYPE html>
<html lang="ko">
<head>
<%@include file="/WEB-INF/inc/header.jsp"%>
<meta charset="UTF-8">
<title></title>
</head>
<body>
	<%@include file="/WEB-INF/inc/top.jsp"%>
	<div class="container">

		<jsp:useBean id="member" class="com.study.member.vo.MemberVO"></jsp:useBean>
		<jsp:setProperty property="*" name="member" />
		<pre>
${member}
</pre>

		<%
	IMemberService memberService = new MemberServiceImpl();
	memberService.registMember(member);
	%>
		<c:catch var="ex">
			<div class="panel panel-sucess">
				<div class="panel-heading">회원가입성공
				<div class="panel-body"></div>
				ㅊㅋㅊㅋ
				</div>
		</c:catch>
		<c:if test="${not empty ex}">
			<div class="panel panel-default">
				<div class="panel-heading">회원가입실패
				<div class="panel-body">큰일</div>
			</div>
			</div>
		</c:if>
		<div class="pull-left">
				<a href="memberList.jsp" class="btn btn-sm btn-default"> 
				<i class="glyphicon glyphicon-list"></i> &nbsp;목록으로
				</a>
			</div>
	</div>
	<!--end.container -->
</body>
</html>

 

 

MemberView.jsp

 

 

 

<%@page import="com.study.code.vo.CodeVO"%>
<%@page import="java.util.List"%>
<%@page import="com.study.code.service.CodeServiceImpl"%>
<%@page import="com.study.code.service.ICodeService"%>
<%@page import="com.study.member.vo.MemberVO"%>
<%@page import="com.study.member.service.MemberServiceImpl"%>
<%@page import="com.study.member.service.IMemberService"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%
	request.setCharacterEncoding("UTF-8");
%>

<!DOCTYPE html>
<html lang="ko">

<head>
<%@ include file="/WEB-INF/inc/header.jsp"%>
<title>memberForm.jsp</title>
</head>
<body>
	<%@include file="/WEB-INF/inc/top.jsp"%>
	<div class="container">
<%-- <%
		ICodeService codeService = new CodeServiceImpl();
		List<CodeVO> categories = codeService.getCodeListByParent("BC00");
		List<CodeVO> jobs = codeService.getCodeListByParent("JB00");
		List<CodeVO> hobbies = codeService.getCodeListByParent("HB00");
		request.setAttribute("categories", categories);
		request.setAttribute("jobs", jobs);
		request.setAttribute("hobbies", hobbies);
	
%> --%>
			<%
			String memId = request.getParameter("memId");
			//memId가 없다면 예외처리 또는 홈으로 이동
			if (memId == null || "".equals(memId)) {
				response.sendRedirect("memberList.jsp");
				return;
			}
			
			 IMemberService memberService = new MemberServiceImpl();
			 MemberVO member = memberService.getMember(memId);
			 request.setAttribute("member", member);
			%>
			 
	
		<div class="page-header">
			<h3>회원정보</h3>
		</div>
		

	<c:if test="${not empty member}">
	
			<table class="table">
				<tbody>
					<tr>
						<th>아이디</th>
						<td>${member.memId}</td>
					</tr>
					<tr>
						<th>비밀번호</th>
						<td>${member.memPass}</td>
					</tr>
					<tr>
						<th>회원명</th>
						<td>${member.memName}</td>
					</tr>
					<tr>
						<th>생일</th>
						<td>${member.memBir}</td>
					</tr>
					<tr>
						<th>우편번호</th>
						<td>${member.memZip}</td>
					</tr>
					<tr>
						<th>주소</th>
						<td>${member.memAdd1}${member.memAdd2}</td>
					</tr>
					<tr>
						<th>헨드폰</th>
						<td>${member.memHp}</td>
					</tr>
					<tr>
						<th>메일</th>
						<td>${member.memMail}</td>
					</tr>
					<tr>
						<th>직업</th>
						<td>${member.memJobnm}</td>
					</tr>
					<tr>
						<th>취미</th>
						<td>${member.memLikenm}</td>
					</tr>
					<tr>
						<th>마일리지</th>
						<td><fmt:formatNumber value='${member.memMileage}' /></td>
					</tr>
				</tbody>
			</table>
			<div>
				<div class="pull-left">
				<a href="memberList.jsp" class="btn btn-sm btn-default"> <i
					class="glyphicon glyphicon-list"></i> &nbsp;목록으로
				</a>
			</div>
			<div class="pull-right">
				<a href="memberEdit.jsp?memId=<%=memId%>"
					class="btn btn-sm btn-default"> <i
					class="glyphicon glyphicon-list"></i> &nbsp;수정
				</a>
			</div>
		</div>
		</c:if>
		<c:if test="${empty member}">
		<div class="panel panel-default">
			<div class="panel-heading">
				회원가입 실패
				<div class="panel-body">큰일났네...</div>
			</div>
		</div>
		<div>
			<div class="pull-left">
				<a href="memberList.jsp" class="btn btn-sm btn-default"> <i
					class="glyphicon glyphicon-list"></i> &nbsp;목록으로
				</a>
			</div>
		</div>
		</c:if>
		
	</div>
</body>
</html>

 

 

'Back-End > JSP' 카테고리의 다른 글

[JSP] 페이징  (0) 2021.07.22
[JSP] 회원 정보 만들기-3  (0) 2021.07.20
[JSP] 회원 정보 만들기-1  (0) 2021.07.20
[JSP] 회원 정보 만들기 전  (0) 2021.07.16
[JSP] 9. 표준 태그 라이브러리(JSTL)  (0) 2021.06.20
  Comments,     Trackbacks
[JSP] 회원 정보 만들기-1

 

 

MemberVO.java

 

package com.study.member.vo;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

public class MemberVO {
	
	// VO(Value Object) : MVC 디자인 패턴에서 Model 클래스
	
	//멤버 변수
	private String memId; // 회원아이디
	private String memPass; // 회원비밀번호
	private String memName; // 회원이름
	private String memBir; // 회원생년월일
	private String memZip; // 회원 
	private String memAdd1; //회원 주소1
	private String memAdd2; //회원 주소2
	private String memHp; // 회원 휴대폰
	private String memMail; // 회원 메일
	private String memJob; // 회원 직업
	private String memLike; // 회원 취미
	private int memMileage; // 회원 마일리지
	private String memDelete; // 삭제유무 때문에
	private String memJobnm; // 직업 넘버
	private String memLikenm; // 취미 넘버
	

	//getter,setter
	
	public String getMemJobnm() {
		return memJobnm;
	}
	public void setMemJobnm(String memJobnm) {
		this.memJobnm = memJobnm;
	}
	public String getMemLikenm() {
		return memLikenm;
	}
	public void setMemLikenm(String memLikenm) {
		this.memLikenm = memLikenm;
	}
	public String getMemId() {
		return memId;
	}
	public void setMemId(String memId) {
		this.memId = memId;
	}
	public String getMemPass() {
		return memPass;
	}
	public void setMemPass(String memPass) {
		this.memPass = memPass;
	}
	public String getMemName() {
		return memName;
	}
	public void setMemName(String memName) {
		this.memName = memName;
	}
	public String getMemBir() {
		return memBir;
	}
	public void setMemBir(String memBir) {
		this.memBir = memBir;
	}
	public String getMemZip() {
		return memZip;
	}
	public void setMemZip(String memZip) {
		this.memZip = memZip;
	}
	public String getMemAdd1() {
		return memAdd1;
	}
	public void setMemAdd1(String memAdd1) {
		this.memAdd1 = memAdd1;
	}
	public String getMemAdd2() {
		return memAdd2;
	}
	public void setMemAdd2(String memAdd2) {
		this.memAdd2 = memAdd2;
	}
	public String getMemHp() {
		return memHp;
	}
	public void setMemHp(String memHp) {
		this.memHp = memHp;
	}
	public String getMemMail() {
		return memMail;
	}
	public void setMemMail(String memMail) {
		this.memMail = memMail;
	}
	public String getMemJob() {
		return memJob;
	}
	public void setMemJob(String memJob) {
		this.memJob = memJob;
	}
	public String getMemLike() {
		return memLike;
	}
	public void setMemLike(String memLike) {
		this.memLike = memLike;
	}
	public int getMemMileage() {
		return memMileage;
	}
	public void setMemMileage(int memMileage) {
		this.memMileage = memMileage;
	}
	public String getMemDelete() {
		return memDelete;
	}
	public void setMemDelete(String memDelete) {
		this.memDelete = memDelete;
	}

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
	}
	
}

 

DB에서 받을 멤버 변수, getter/setter 설정

 

 

IMemberService.java

 

package com.study.member.service;

import java.util.List;

import com.study.exception.BizNotFoundException;
import com.study.member.vo.MemberSearchVO;
import com.study.member.vo.MemberVO;


public interface IMemberService {
	
	
	/**
	 * <b>레코드 건수 반환</b><br>
	 * 검색조건이 존재하는 경우 해당 건수를 리턴 
	 * @param conn
	 * @return int 검색건수
	 */
	//내부에서 하는 것이기 때문에 커넥션은 conn 필요없다.
	public int getMemberCount(MemberSearchVO searchVO) ;
	
	
	/**
	 * <b>회원등록</b>
	 * <pre>
	 * 회원정보를 등록처리합니다.
	 * 
	 * 아이디가 중복된 경우 BizDuplicateException
	 * 등록에 실패한 경우  BizNotEffectedException
	 * </pre>
	 * @param member
	 */
	public void registMember(MemberVO member) ;
	
	/**
	 * <b>회원수정</b>
	 * <pre>
	 * 회원정보를 변경처리합니다.
	 * 
	 * 비번이 틀린경우 BizPasswordNotMatchedException
	 * 변경에 실패한 경우  BizNotEffectedException
	 * </pre>
	 * @param member
	 */
	public void modifyMember(MemberVO member) ;
	
	/**
	 * <b>회원탈퇴처리</b>
	 * <pre>
	 * 회원의 상태정보를 변경합니다.
	 * mem_delete = "Y"
	 * 비번이 틀린경우 BizPasswordNotMatchedException
	 * 변경에 실패한 경우  BizNotEffectedException
	 * </pre>
	 * @param member
	 */
	public void removeMember(MemberVO member) ;
	
	/**
	 * <b>회원정보 조회</b>
	 * <pre>
	 * 해당 아이디에 대한 회원정보를 조회합니다.
	 * 
	 * 존재하지 않는 경우 BizNotFoundException
	 * </pre>
	 * @param memId
	 * @return MemberVO
	 */
	public MemberVO getMember(String memId)throws BizNotFoundException;
	
	/**
	 * <b>회원 목록조회</b>
	 * <pre>
	 * 회원의 목록을 조회합니다.
	 * 검색조건 사용가능
	 * </pre>
	 * @param searchVO TODO
	 * @return List<MemberVO> 
	 */
	public List<MemberVO> getMemberList(MemberSearchVO searchVO);
	
}

 

인터페이스는 모든 기능을 추상화로 정의만 하고 구현은 하지 않은것을 의미합니다.

정처기나 추상화할때 많이 들어보는 애자일 프로세스 완전한 요구사항이 도출되지 않은 상태에서 빠르게

개발하면서 지속적으로 새로운 요구사항,변경사항을 적용하는 방식

 

인터페이스 하위개념인 상속은 모든 유전자를 부모에게 물려받아 원치 않은 메서드까지 물려받기 때문에 버그가 발생 할 수 있다.

 

하지만 인터페이스는 구체 클래스를 사용하지 않기 때문에 유연성이 좋다.

 

주석은 프로젝트할 때 꼭 필요하다. 기능이 무엇인지 무엇을 반환하는지

다른사람도 알아야 하니깐!

 

 

MemberServiceImpl.java

 

 

package com.study.member.service;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;

import com.study.exception.BizNotFoundException;
import com.study.member.dao.IMemberDao;
import com.study.member.dao.MemberDaoOracle;
import com.study.member.vo.MemberSearchVO;
import com.study.member.vo.MemberVO;

public class MemberServiceImpl implements IMemberService{
	
	private IMemberDao memberDao = new MemberDaoOracle();
	private String JDBC_URL = "jdbc:apache:commons:dbcp:study"; //JDBC 드라이버 로드
	
	//뷰단에서 할 수도 있지만 Service에서 해결 하므로써 뷰는 프론트, Service쪽은 백엔드 구분이 명확해지기도 하고
	//수정, 처리 하기도 편함

	//회원가입
	
	@Override
	public void registMember(MemberVO member) {
		Connection conn = null;
		try {
			conn = DriverManager.getConnection(JDBC_URL);
			conn.setAutoCommit(false);
			
			int cnt = memberDao.insertMember(conn, member);
			// cnt가 0 인 경우 BizNotEffectedException 예외 발생
			
			conn.commit();
		} catch (SQLException e) {
			e.printStackTrace();
			try {conn.rollback();} catch (SQLException e2) {}
			throw new RuntimeException(e.getMessage(), e);
		}finally {
			if (conn != null) try {conn.close();} catch (SQLException e) {}
		}
		
	}

	//회원정보 수정
	
	@Override
	public void modifyMember(MemberVO member) {
		Connection conn = null;
		try {
			conn = DriverManager.getConnection(JDBC_URL);
			conn.setAutoCommit(false);
			
			int cnt = memberDao.updateMember(conn, member);
			// TODO cnt가 0 인 경우 BizNotEffectedException 예외 발생
			
			conn.commit();
		} catch (SQLException e) {
			e.printStackTrace();
			try {conn.rollback();} catch (SQLException e2) {}
			throw new RuntimeException(e.getMessage(), e);
		}finally {
			if (conn != null) try {conn.close();} catch (SQLException e) {}
		}		
	}

	//회원 제거
	
	@Override
	public void removeMember(MemberVO member) {
		Connection conn = null;
		try {
			conn = DriverManager.getConnection(JDBC_URL);
			conn.setAutoCommit(false);
			
			int cnt = memberDao.deleteMember(conn, member);
			//cnt가 0 인 경우 BizNotEffectedException 예외 발생
			
			conn.commit();
		} catch (SQLException e) {
			e.printStackTrace();
			try {conn.rollback();} catch (SQLException e2) {}
			throw new RuntimeException(e.getMessage(), e);
		}finally {
			if (conn != null) try {conn.close();} catch (SQLException e) {}
		}		
	}

	//회원목록 조회
	
	@Override
	public MemberVO getMember(String memId) throws BizNotFoundException {
		Connection conn = null;
		try {
			conn = DriverManager.getConnection(JDBC_URL);
			conn.setAutoCommit(false);
			
			MemberVO member = memberDao.getMember(conn, memId);
			//member가 널인 경우 BizNotFoundException 예외발생
			
			conn.commit();
			return member;
		} catch (SQLException e) {
			e.printStackTrace();
			try {conn.rollback();} catch (SQLException e2) {}
			throw new RuntimeException(e.getMessage(), e);
		}finally {
			if (conn != null) try {conn.close();} catch (SQLException e) {}
		}	
	}
	
	//회원목록 리스트
	@Override
	public List<MemberVO> getMemberList(MemberSearchVO searchVO) {
		Connection conn = null;
		try {
			conn = DriverManager.getConnection(JDBC_URL);
			
			//conn.setAutoCommit(false);
			List<MemberVO> list = memberDao.getMemberList(conn,searchVO);
			
			//conn.commit(); // select 는 commit 의미 없음
			return list;
		} catch (SQLException e) {
			e.printStackTrace();
			try {conn.rollback();} catch (SQLException e2) {}
			throw new RuntimeException(e.getMessage(), e);
		}finally {
			if (conn != null) try {conn.close();} catch (SQLException e) {}
		}	
	}

	//회원목록 페이지카운트
	@Override
	public int getMemberCount(MemberSearchVO searchVO) {
		Connection conn = null;
		try {
			conn = DriverManager.getConnection(JDBC_URL);
			
			int tot = memberDao.getMemberCount(conn, searchVO);
			return tot;
		} catch (SQLException e) {
			e.printStackTrace();
			try {conn.rollback();} catch (SQLException e2) {}
			throw new RuntimeException(e.getMessage(), e);
		}finally {
			if (conn != null) try {conn.close();} catch (SQLException e) {}
		}	
	}
}

 

JDBC는 서로 다른 DB를 표준화 된 방법으로 접속 할 수 있도록 만든 API 규격이다.

JDBC 드라이버 로드를 해 연결 할 수 있다.

 

Service에 나눠 처리하면 좀 더 보기도 편하고 수정하기에도 용이하다.

 

 

IMemberDao.java

 

 

package com.study.member.dao;

import java.sql.Connection;
import java.util.List;

import com.study.member.vo.MemberSearchVO;
import com.study.member.vo.MemberVO;

//기본 메소드
//인터페이스

public interface IMemberDao {

	public int insertMember(Connection conn, MemberVO member);
	public int updateMember(Connection conn, MemberVO member);
	public int deleteMember(Connection conn, MemberVO member);
	public MemberVO getMember(Connection conn, String memId );
	public List<MemberVO> getMemberList(Connection conn, MemberSearchVO searchVO);
	public int getMemberCount(Connection conn, MemberSearchVO searchVO);
	
}

 

기존에 사용하고 있는 패키지 클래스에서 다른 패키지의 클래스들로 사용 DAO를 변경할 때마다 DAO를 사용하는 코드를 모두 수정해야 한다.

이 불편함을 해소하기 위해 DAO 클래스에 대한 사용 규칙, 즉 인터페이스를 정의하여 클래스 대신 인터페이스를 사용하도록 한다. 

 

 

MemberDaoOracle.java

 

먼저 알아야둬야 할 것 (이 부분이 난 제일 어려웠다. 한번만 이해하고 넘어가자.)


Connection 객체의 prepareStatement(String query)를 통해 생성된다.

 

PreparedStatement객체를 생성할때 SQL문이 인자로 주어진다.

 

SQL문에 매개변수를 사용하고, 실행전에 값을 지정할수있다.

 

SQL 문을 실행할때 execute(), executeQuery()또는 executeUpdate()를 사용한다.

 

PreparedStatement가 제공하는 메소드는 Statement가 제공하는 메소드와 거의 같다.


 

StringBuilder 는 변경할 수 있는 문자열을 나타냅니다. 이 클래스는 상속될 수 없습니다.

 

ExecuteUpdate 는 수행결과를 Int타입의 값으로 반환합니다. SELECT 구문을 제외한 다른 구문을 수행 할 때 사용되는 함수 (INSERT / DELETE / UPDATE에 사용 SELECT X)

 

바인드 변수 - PL/SQL 또는 SQL 쿼리문에서 WHERE 절에 Value값을 '?' 로 사용하는 변수이다.

 

 


 

 

MemberDaoOracle.java

 

 

package com.study.member.dao;

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 com.study.free.vo.FreeBoardSearchVO;
import com.study.member.vo.MemberSearchVO;
import com.study.member.vo.MemberVO;

public class MemberDaoOracle implements IMemberDao {

	@Override
	public int insertMember(Connection conn, MemberVO member) {
		// 변수 선언
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		StringBuilder sb = new StringBuilder();
		int res = 0;
		// SQL 구문
		sb.append("INSERT INTO member ( ");
		sb.append("	    mem_id         ");
		sb.append("	    , mem_pass     ");
		sb.append("	    , mem_name     ");
		sb.append("     , mem_zip       ");
		sb.append("     , mem_add1      ");
		sb.append("     , mem_add2      ");
		sb.append("	    , mem_bir      ");
		sb.append("	    , mem_hp       ");
		sb.append("	    , mem_mail     ");
		sb.append("	    , mem_job      ");
		sb.append("	    , mem_like     ");
		sb.append("	    , mem_mileage  ");
		sb.append("	    , mem_delete   ");
		sb.append("	) VALUES (         ");
		sb.append("	      ? "); 
		sb.append("	    , ? ");
		sb.append("	    , ? ");
		sb.append("	    , ? ");
		sb.append("	    , ? ");
		sb.append("	    , ? ");
		sb.append("	    , ? ");
		sb.append("	    , ? ");
		sb.append("	    , ? ");
		sb.append("	    , ? ");
		sb.append("	    , ? ");
		sb.append("	    , 0   ");
		sb.append("	    , 'N' ");
		sb.append("	)         ");
		

		try {
			// 3. 구문 객체 생성
			pstmt = conn.prepareStatement(sb.toString());
			
			int idx = 1;
			// 4. 바인드 변수 설정
			pstmt.setString(idx++, member.getMemId());
			pstmt.setString(idx++, member.getMemPass());
			pstmt.setString(idx++, member.getMemName());
			pstmt.setString(idx++, member.getMemZip());
			pstmt.setString(idx++, member.getMemAdd1());
			pstmt.setString(idx++, member.getMemAdd2());
			pstmt.setString(idx++, member.getMemBir());
			pstmt.setString(idx++, member.getMemHp());
			pstmt.setString(idx++, member.getMemMail());
			pstmt.setString(idx++, member.getMemJob());
			pstmt.setString(idx++, member.getMemLike());
			System.out.println(sb.toString());
			// 5. 구문객체 실행
			res = pstmt.executeUpdate();
			
			return res;
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e);
		} finally {
			// 자원종료
			if (rs != null) try {rs.close();} catch (SQLException e) {}
			if (pstmt != null) try {pstmt.close();} catch (SQLException e) {}
		}
		
	}

	@Override
	public int updateMember(Connection conn, MemberVO member) {
		// 변수 선언
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		StringBuilder sb = new StringBuilder();
		int res = 0;
		// SQL 구문
		sb.append("UPDATE member			");
		sb.append("   SET mem_name = ? ");
		sb.append("     , mem_bir  = ? ");
		sb.append("     , mem_zip  = ? ");
		sb.append("     , mem_add1 = ? ");
		sb.append("     , mem_add2 = ? ");
		sb.append("     , mem_hp   = ? ");
		sb.append("     , mem_mail = ? ");
		sb.append("     , mem_job  = ? ");
		sb.append("     , mem_like = ? ");
		sb.append(" where mem_id    =  ? ");
		System.out.println(sb.toString());
		
		try {
			// 3. 구문 객체 생성
			pstmt = conn.prepareStatement(sb.toString());
			int idx = 1;
			// 4. 바인드 변수 설정
			pstmt.setString(idx++, member.getMemName());
			pstmt.setString(idx++, member.getMemBir());
			pstmt.setString(idx++, member.getMemZip());
			pstmt.setString(idx++, member.getMemAdd1());
			pstmt.setString(idx++, member.getMemAdd2());
			pstmt.setString(idx++, member.getMemHp());
			pstmt.setString(idx++, member.getMemMail());
			pstmt.setString(idx++, member.getMemJob());
			pstmt.setString(idx++, member.getMemLike());
			pstmt.setString(idx++, member.getMemId());
			
			// 5. 구문객체 실행
			res = pstmt.executeUpdate();
			return res;
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e);
		} finally {
			// 자원종료
			if (rs != null) try {rs.close();} catch (SQLException e) {}
			if (pstmt != null) try {pstmt.close();} catch (SQLException e) {}
		}
	}

	@Override
	public int deleteMember(Connection conn, MemberVO member) {
		// 변수 선언
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		StringBuilder sb = new StringBuilder();

		
		// SQL 구문
		sb.append(" ");
		System.out.println(sb.toString());

		try {
			// 3. 구문 객체 생성
			pstmt = conn.prepareStatement(sb.toString());
			// 4. 바인드 변수 설정

			// 5. 구문객체 실행

		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e);
		} finally {
			// 자원종료
			if (rs != null) try {rs.close();} catch (SQLException e) {}
			if (pstmt != null) try {pstmt.close();} catch (SQLException e) {}
		}
		return 0;
	}

	@Override
	public MemberVO getMember(Connection conn, String memId) {
		//뷰 조회.
		// 변수 선언
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		StringBuilder sb = new StringBuilder();

		// SQL 구문
		sb.append("SELECT mem_id     ");
		sb.append("     , mem_name    ");
		sb.append("     , mem_pass    ");
		sb.append("     , to_char(mem_bir, 'yyyy-mm-dd') as mem_bir    ");
		sb.append("     , mem_zip     ");
		sb.append("     , mem_add1    ");
		sb.append("     , mem_add2    ");
		sb.append("     , mem_hp      ");
		sb.append("     , mem_mail    ");
		sb.append("     , mem_job     ");
		sb.append("		,(SELECT comm_nm from comm_code WHERE comm_cd = mem_job ) as mem_job_nm ");
		sb.append("     , mem_like    ");
		sb.append("		,(SELECT comm_nm from comm_code WHERE comm_cd = mem_like ) as mem_like_nm ");
		sb.append("     , mem_mileage ");
		sb.append("     , mem_delete  ");
		sb.append("  FROM member          ");
		sb.append(" where mem_id = ? ");

		try {

			// 3. 구문 객체 생성
			pstmt = conn.prepareStatement(sb.toString());
			// 4. 바인드 변수 설정
			pstmt.setString(1,memId);
			// 5. 구문객체 실행
			rs = pstmt.executeQuery();
			MemberVO member = null;
			if(rs.next()) {
				member = new MemberVO();
				member.setMemId(rs.getString("mem_id"));
				member.setMemName(rs.getString("mem_name"));
				member.setMemPass(rs.getString("mem_pass"));
				member.setMemBir(rs.getString("mem_bir"));
				member.setMemZip(rs.getString("mem_zip"));
				member.setMemAdd1(rs.getString("mem_add1"));
				member.setMemAdd2(rs.getString("mem_add2"));
				member.setMemHp(rs.getString("mem_hp"));
				member.setMemMail(rs.getString("mem_mail"));
				member.setMemJob(rs.getString("mem_job"));
				member.setMemJobnm(rs.getString("mem_job_nm"));
				member.setMemLike(rs.getString("mem_like"));
				member.setMemLikenm(rs.getString("mem_like_nm"));
				member.setMemMileage(rs.getInt("mem_mileage"));
			}
			
			return member;
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e);
		} finally {
			// 자원종료
			if (rs != null) try {rs.close();} catch (SQLException e) {}
			if (pstmt != null) try {pstmt.close();} catch (SQLException e) {}
		}
	
	}

	@Override
	public List<MemberVO> getMemberList(Connection conn, MemberSearchVO searchVO) {
		// 변수 선언
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		StringBuilder sb = new StringBuilder();
		List<MemberVO> list = new ArrayList<MemberVO>();

		// SQL 구문
		//페이징 쿼리 추가
		sb.append("SELECT * ");
		sb.append("FROM ( SELECT rownum AS rnum ");
		sb.append("				, a.* ");
		//a.*  : 어느 테이블의 모든 것
		sb.append("					FROM ( ");
		
		
		sb.append("SELECT mem_id      ");
		sb.append("     , mem_name    ");
		sb.append("     , mem_pass    ");
		sb.append("     , mem_zip     ");
		sb.append("     , mem_add1    ");
		sb.append("     , mem_add2    ");
		sb.append("     , mem_hp      ");
		sb.append("     , mem_mail    ");
		sb.append("     , mem_job     ");
		sb.append("     , (SELECT comm_nm from comm_code WHERE mem_job = comm_cd ) as mem_job_nm ");
		sb.append("     , (SELECT comm_nm from comm_code WHERE mem_like = comm_cd ) as mem_like_nm ");
		sb.append("     , mem_mileage ");
		sb.append("     , mem_delete  ");
		sb.append("  FROM member          ");
		sb.append(" ORDER BY mem_id ");
		
		sb.append("  			) a " );
		sb.append("  	where rownum <= ?  ");
		sb.append("  ) b  							");
		sb.append("  where rnum BETWEEN ? AND ?  ");
		//삭제때문에 쓴 append WHERE 삭제여부가 N 인 것만 출력
		//그렇다면 삭제는 'Y'인건 안보이게 하면 된다.
		System.out.println(sb.toString());
		
		
		
		try {
			// 3. 구문 객체 생성
			pstmt = conn.prepareStatement(sb.toString());
			// 4. 바인드 변수 설정
			pstmt.setInt(1, searchVO.getEndRow());
			pstmt.setInt(2, searchVO.getStartRow());
			pstmt.setInt(3, searchVO.getEndRow());
			// 5. 구문객체 실행
			rs = pstmt.executeQuery();
			while(rs.next()) { // ResultSet 은 next밖에 못
				MemberVO member = new MemberVO();
				member.setMemId(rs.getString("mem_id"));
				member.setMemName(rs.getString("mem_name"));
				member.setMemZip(rs.getString("mem_zip"));
				member.setMemAdd1(rs.getString("mem_add1"));
				member.setMemAdd2(rs.getString("mem_add2"));
				member.setMemHp(rs.getString("mem_hp"));
				member.setMemMail(rs.getString("mem_mail"));
				member.setMemJob(rs.getString("mem_job"));
				member.setMemJobnm(rs.getString("mem_job_nm"));
				member.setMemLikenm(rs.getString("mem_like_nm"));
				member.setMemLikenm(rs.getString("mem_mileage"));
				member.setMemLikenm(rs.getString("mem_delete"));
				list.add(member);
			}
			return list;
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e);
		} finally {
			// 자원종료
			if (rs != null) try {rs.close();} catch (SQLException e) {}
			if (pstmt != null) try {pstmt.close();} catch (SQLException e) {}
		}
	}

	@Override
	public int getMemberCount(Connection conn, MemberSearchVO searchVO) {
		// 변수 선언
				PreparedStatement pstmt = null;
				ResultSet rs = null;
				StringBuilder sb = new StringBuilder();

				// SQL 구문
				sb.append(" SELECT COUNT(*) AS tot         ");
				sb.append(" FROM member         		 ");
				//sb.append(" WHERE bo_del_yn ='N'          ");
				
				//검색은 물음표
				//삭제때문에 쓴 append WHERE 삭제여부가 N 인 것만 출력
				//그렇다면 삭제는 'Y'인건 안보이게 하면 된다.
				System.out.println(sb.toString());
				try {
					// 3. 구문 객체 생성
					pstmt = conn.prepareStatement(sb.toString());
					rs = pstmt.executeQuery();
					
					int tot = 0;
					if(rs.next()) {
						
						tot = rs.getInt(1); //레코드 전체 수 int로
					}
					return tot;
				} catch (SQLException e) {
					e.printStackTrace();
					throw new RuntimeException(e.getMessage(), e);
				} finally {
					// 자원종료
					if (rs != null) try {rs.close();} catch (SQLException e) {}
					if (pstmt != null) try {pstmt.close();} catch (SQLException e) {}
				}
			}
}

 

 

 

 

도움받은 블로그(감사합니다!)

https://pinokio0702.tistory.com/54

https://velog.io/@underlier12/%EC%9E%90%EB%B0%94-%EA%B3%B5%EB%B6%80-%EC%9D%BC%EC%A7%80-010

'Back-End > JSP' 카테고리의 다른 글

[JSP] 회원 정보 만들기-3  (0) 2021.07.20
[JSP] 회원 정보 만들기-2  (0) 2021.07.20
[JSP] 회원 정보 만들기 전  (0) 2021.07.16
[JSP] 9. 표준 태그 라이브러리(JSTL)  (0) 2021.06.20
[JSP] 7. 표현 언어(Expression Language)  (1) 2021.06.19
  Comments,     Trackbacks
[Spring] 5. 프로젝트의 구성

 

 

일반적인 웹 프로젝트의 구조는 3-Tier의 구조를 활용

 

 

 

Presentation Tier
(화면 계층)
화면에 보여주는 기술을 사용하는 영역입니다. (즉, Servlet/JSP나 스프링 MVC가 담당하는 영역) Presentation Tier는 프로젝트의 성격에 맞춰 앱으로 제작하거나, CS(Client-Server)로 구성되는 경우도 있습니다. 이전 파트에서 학습한 스프링 MVC와 JSP를 이용한 화면 구성이 이에 속합니다.
Business Tier
(비즈니스 계층)
순수한 비즈니스 로직을 담고 있는 영역입니다. 이 영역이 중요한 이유는 고객이 원하는 요구 사항을 반영하는 계층이기 때문입니다. 이 영역의 설계는 고객의 요구 사항과 정확히 일치해야 합니다. 이 영역은 주로 'xxxService'와 같은 이름으로 구성하고, 메서드의 이름 역시 고객들이 사용하는 용어를 그대로 사용하는 것이 좋습니다.
Persistence Tier
(영속 계층 혹은 데이터 계층)
데이터를 어떤 방식으로 보관하고, 사용하는가에 대한 설계가 들어가는 계층입니다. 일반적인 경우에는 데이터베이스를 많이 이용하지만, 경우에 따라서 네트워크 호출이나 원격 호출 등의 기술이 접목될 수 있습니다. 이 영역은 MyBatis와 mybatis-spring을 이용해서 구성했던 파트 1을 이용합니다.

 

 

스프링 MVC를 이용하는 예제의 구성

 

 

각 영역의 네이밍 규칙

 

 

xxxController: 스프링 MVC에서 동작하는 Controller 클래스

 

xxxSerivce, xxxServiceImpl: 비즈니스 영역을 담당하는 인터페이스는 ‘xxxService’라는 방식을 사용하고, 인터페이스를   구현한 클래스는 ‘xxxServiceImpl’이라는 이름을 사용

 

xxxDAO, xxxRepository: DAO(Data-Access-Object)Repository(저장소)라는 이름으로 영역을 따로 구성하는 것이   보편적. 예제에서는 별도의 DAO를 구성하는 대신에 MyBatisMapper 인터페이스를 활용.

 

VO, DTO: VO의 경우는 주로 Read Only의 목적이 강하고, 데이터 자체도 Immutable(불변)하게 설계. DTO는 주로 데     이터 수집의 용도

 

 

 

기본적인 게시물의 CRUD 흐름

 

 


 

프로젝트 폴더 구성

 

 

1.

src/main/java

.java 파일이 모여 있는 곳. 스프링에서 MVC패턴의 서블릿 구조를 잡아주기 때문에 스프링

구조에 맞춰 클래스 파일들을 작성

 

 

2.

src/main/resources

 

자바 클래스에서 사용하는 리소스를 보관하는 곳. DB 연결을 위한 자원, 의존성 주입(DI)을

위한 xml 파일 등 자바 코드 외 모든 자원은 이곳에 넣어주면 됩니다.

 

 

3.

src/test

테스트. 자바 코드와 리소스를 보관하는 곳

 

 

4.

Maven Dependencies

(너무 길게 찍었네;;)

 

Maven에서 auto로 관리해주는 라이브러리 폴더. "pom.xml"에 작성된 라이브러리들을 자동으로

다운받아 (원하는 버전으로 만들려면 https://mvnrepository.com/) 접속해 원하는 것을 다운

빌드툴을 사용함으로써 개발자가 직접 관리해주지 않아도 되는 영역이 되었음

 

 

5.

 

src

Web에 관련된 자원이 담겨있는 루트 폴더.

 

 

6.

src/main/webapps/resources

 

웹에 필요한 자원들을 보관하는 곳. 사용자가 직접 접근 할 수 있는 공간이다.

컨트롤러가 요청을 가로채지 않고 바로 접근할 수 있도록 따로 설정해서 사용

하는 곳입니다.

 

 

7.

src/main/webapp/WEB-INF

 

웹에 필요한 코드 파일과 컴파일된 파일,환경설정 파일들이 보관되는 곳. (보안이 중요한 곳)

외부 사용자가 직접 접근 할 수 없다. 내부적으로만 접근 가능

 

 

8.

src/main/webapp/WEB-INF/classes

 

 

컴파일 된 파일이 보관되어 있는 곳.

 

 

9.

src/main/webapp/WEB-INF/spring

 

스프링 환경설정 파일(context)가 보관 되는 곳.

 

 

10.

src/main/webapp/WEB-INF/views

 

JSP,HTML이 보관 된 곳이며 이 폴다가 루트(/)의 기준점입니다.

사용자가 입력, 컨트롤러가 받아주는 URL이 이 폴더의 구조를 따라가기 때문에 잘 정리 하기

 

 

  Comments,     Trackbacks
@Annotation 종류 사전

 

계속 수정

 

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

 

@ RunWith :  jUnit 프레임워크의 테스트 실행방법을 확장할 때 사용하는 어노테이션

 

@Autowired : 스프링 DI에서 사용되는 특별한 어노테이션. 해당 변수에 자동으로 빈(Bean)을 매핑

 

@Test : 이 어노테이션에 선언된 메서드는 테스트를 수행하는 메소드가 된다.

 

@BeforeClass : @테스트 메소드보다 먼저 한번만 수행되어야 할 경우에 사용하면 된다.

 

@AfterClass : @테스트 메소드보다 나중에 한번만 수행되어야 할 경우에 사용하면 된다.

 

@ContextConfiguration : 스프링 빈(Bean) 설정 파일의 위치를 지정할 때 사용되는 어노테이션

 

@Log4j : 로그문의 출력을 다양한 대상으로 할 수 있도록 도와주는 어노테이션

 

@Data : Lombok에서 가장 자주 사용되는 어노테이션. ToString, EqualsAndHashCode,Getter,Setter등을

           모두 결합한 형태로 한번에 자주 사용되는 모든 메서드들을 생성 할 수 있다. 짱

 

@Controller : Controller의 역할을 수행 한다고 명시. 추가하게 되면 스프링의 Bean으로 인식

 

@RequestMapping : 요청에 대해 어떤 Controller. 어떤 메서드가 처리할지 맵핑하기 위한 어노테이션

 

@Allargsconstructor : 모든 파라미터를 이용하는 생성자

 

@Service : 계층 구조상 주로 비즈니스 영역을 담당하는 객체임을 표시하기 위해서 사용

 

 

'Back-End > 정의 및 용어' 카테고리의 다른 글

용어 사전 (계속 추가 중)  (0) 2021.07.16
VO, DAO, DTO, CRUD가 무엇일까  (0) 2021.07.15
  Comments,     Trackbacks