DTO와 VO는 같은 개념으로 쓰이고 있지만 자세하게는 역할이 다르다

 

DTO는 DB에서 검색할 조건을 넣는 Bean이고

VO는 DB로부터 반환해서 받아오는 Bean이다

 

하나의 Bean에 반환데이터와 검색조건을 넣고 처리하면

검색조건이 반환값에 덮어써져버려서 결과가 변하기 때문

 

또 다른 이유는

DTO는 DB의 검색조건을 관리하는 Bean이기 때문에

DB의 컬럼명과 일치해야하지만

 

Bean은 반환값을 보관하기 때문에

DB명과 일치하지 않는 경우도 있다

예를들면 DB는 슈퍼_아이스크림 인데 

꺼내서 쓸땐 슈퍼_를 제외한 아이스크림이라는 이름으로 관리하는 경우가 생긴다

 

SELECT
	SUPER_ICECREAM AS ICECREAM
FROM
	TABLE
WHERE
	SUPER_ICECREAM = ?

이럴 경우 조건문과 반환값을 받는 Bean을 한개의 Bean으로 관리하면

아이스크림이라는 목록이 2개가 존재하게 되므로 관리가 복잡해진다

 

 

#설명

스프링으로 설명을 하나 스트러츠에서도 동일하다

 

로직은 컨트롤러>서비스>매퍼>QUERY 순이다

 

컨트롤러

아래는 boardId가 자유게시판, 검색키워드가 "안녕" 이라는 조건에 부합하는 리스트를 가져오는 구조

DTO는 DB에 접속해 데이터를 가져오는 쓰는 조건변수가 들어 있는 Bean이다

LIst<BoardVO> boardList 의 boardVO는 DB의 결과를 받아오는 Bean

@Controller
public class BoardController {
	
	@Autowired//객체생성을 스프링이 해줌
	BoardService boardService;
	
	@RequestMapping(value = "/boardList", method = RequestMethod.GET)//method가 GET이면서 url이 boardList
	public String boardList(BoardDTO boardDTO,//인수에 Bean을 작성하면 넘어오는 데이터들이 Bean에 있는 멤버필드에 있는 변수이름에 맞게 자동으로 들어감
							Model model) {
		String url = "/board/board_list";
        		
		boardDTO.setBoardId("FREEBOARD");
		boardDTO.setKeyword("안녕");
		
		List<BoardVO> boardList = boardService.selectBoardList(boardDTO);//서비스에서 리스트를 받아옴
		model.addAttribute("boardList", boardList);//boardList 객체를 boardList라는 이름으로 프론트에 보냄

		return url;
	}
 }

 

서비스

public interface BoardService {
	public List<BoardVO> selectBoardList(BoardDTO boardDTO);
}
@Service
public class BoardServiceImpl implements BoardService{
	
	BoardMapper boardMapper;

	@Override
	public List<BoardVO> selectBoardList(BoardDTO boardDTO) {
		return boardMapper.selectBoardList(boardDTO);
	}

}

 

매퍼

@Mapper//mybatis or ibatis가 추가되야 사용가능
public interface BoardMapper {
	public List<BoardVO> selectBoardList(BoardDTO boardDTO);
}

매퍼.xml

아래의 boardId에는 컨트롤러에서 입력한 FREEBOARD가 있고

keyword에는 "안녕" 이 있다

 

즉 boardId가 자유게시판이고 자유게시판 글 중에서 제목이나 본문에 안녕이 있는 글을 출력하는 쿼리다

그리고 resultType에서 지정한 BoardVO로 반환을 한다

<?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.example.demo.mapper.BoardMapper"><!-- mapper의 위치를 지정 -->

	<select id="selectBoard" resultType="com.example.demo.entity.BoardVO"><!-- 리턴 타입은 BoardVO -->
		SELECT 
			* 
		FROM 
			EXAMSITE
		WHERE	
			BOARDID = #{boardID} <!-- boardId가 DTO의 boardID이면서 -->
			AND (BOARDTITLE = '%'||#{keyword}||'%' OR BOARDCONTENT = '%'||#{keyword}||'%') <!-- 제목이나 본문에 DTO의 keyword가 있다면 -->
	</select>
	
</mapper>

 

그럼 컨트롤러에 있는 List<BoardVO>에 들어가게 되는 로직

List<BoardVO> boardList = boardService.selectBoardList(boardDTO);//서비스에서 리스트를 받아옴

 

전체적인 설명글이지만

DTO는 프론트나 컨트롤러에서 입력된 DB에서 조건 검색을 하기위한 Bean

VO는 DB에서 쿼리를 돌리고 나온 결과를 담는 Bean이라고 이해하면 된다

 

 

아래는 스트러츠 프레임워크로 위 조건이 몇개 검색 됐는지 Count를 구하는 로직

package Study;

import java.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.List;

public class DAOStudy {
	public static int selectListCount(DBConection DBCon, boardDTO boardDTO) throws SQLException, Exception {

		/* SQL */
		StringBuffer buf = new StringBuffer();
		buf.append(" SELECT  ");
		buf.append(" 	COUNT(*)  ");
		buf.append(" FROM  ");
		buf.append(" 	EXAMSITE ");
		buf.append(" WHERE	 ");
		buf.append(" 	BOARDID = #{boardID} ");
		buf.append(" 	AND (BOARDTITLE = '%'||?||'%' OR BOARDCONTENT = '%'||?||'%') ");
		  

                /* 파라메터 */
                List<Object> param = new ArrayList<Object>();
                param.add(boardDTO.getBoardId());
		param.add(boardDTO.getKeyword());

		
		int resultCount = 0;
        
		try(PreparedStatement preState = DBCon.getPrepareStatement(buf.toString());){
			DBCon.setPrepareParameter(param, preState);
            
			String logSQL = StringConvertUtil.getPreparedSQL(buf.toString(), param);
			resultCount += preState.executeUpdate();

		}

		return resultCount;
	}
}

'Programming > JAVA' 카테고리의 다른 글

[JAVA] 문자열 비교  (0) 2020.11.19
[JAVA] 대소문자 변환  (0) 2020.11.19
[JAVA] WrapperClass(래퍼 클래스)  (0) 2020.10.04
[JAVA] 정규표현식  (0) 2020.10.01
[JAVA] JUnit  (0) 2020.09.25

#WrapperClass(래퍼 클래스)

자바 자료형은 기본타입(int, char, boolean..)과 참조타입(class, interface)와 같은 객체 구분된다

기본타입을 객체처럼 다루기 위해서 사용하는 것이 래퍼 클래스 이다

 

기본자료형 : 변수가 다르더라도 값이 같으면 같은 주소를 가르킨다

참조형(래퍼클래스) : 값이 같더라도 다른 주소를 가르킨다

 

#기본 자료형 특징

  • 변수명이 다르더라도 값이 같으면 주소가 같다
  • NULL을 사용할 수 없다
  • 기본 자료형 끼리 비교할 때는 ==를 사용(주소 비교)

 

#래퍼클래스 특징

  • 기본자료형은 NULL이 허용되지 않지만 래퍼 클래스는 NULL이 허용된다
  • 래퍼클래스는 특정 기능을 하는 메서드를 사용할 수 있다
  • 래퍼클래스끼리는 객체이므로 .equals()를(값 비교) 사용해서 비교한다
  • 기본자료형과 다르게 값이 같더라도 주소가 다름
  • NULL이 허용되지 때문의 NullPointExcetion에 주의해야 한다
package Study;

public class WrapperClassStudy {

	public static void main(String[] args) {
		int a = null;//에러
		Integer aa = null;//정상

		Integer i = 10;
		int ii = 10;
		
		System.out.println(i.hashCode());
		System.out.println(i.byteValue());
		System.out.println(i.floatValue());
		
		Boolean b = true;
		System.out.println(b.booleanValue());
		System.out.println(b.compareTo(b));
		
		Character c = 'a';
		char cc = 'a';
		System.out.println("CCCCCCCCC");
		System.out.println(c.charValue());
		System.out.println(c.toString());
	}

}

 

#래퍼 클래스 종류

기본타입(primitive type) 래퍼 클래스(wrapper class)
byte Byte
char Character
int Integer
float Float
double Double
boolean Boolean
long Long
short Short
String String()

 

 

#래퍼클래스를 사용해야 할 때

래퍼클래스는 NULL이 허용된다

 

기본형 int 타입으로 null을 받게되면 0이 저장되어서 설계의도와 달라질 수도 있다

 

프론트에서 서버로 데이터를 넘길때 프론트 쪽에 null이 있는데 Bean의 데이터 타입을 기본형으로 작성하면

0이 받아지게되어 설계의도와 달라진다

또한, DB에 액세스 해서 데이터를 가져올때 DB에 null이 있는데 데이터 타입이 기본형인 Bean으로 받게되면

0이 들어가서 이 또한 설계의도와 달라진다

(로직은 null검사를 하는데  0이 들어 있어서 오류가 통과되버림)

 

#예시

DB값은 null이지만 Bean에서 int로 받아버리니 자동으로 0이 들어가버려서 DB와 달라진다

 

Bean에서 Integer로 받으니 DB값 그대로 null이 출력되는 것을 알 수 있다

 

그렇기 때문에 현업에서는 현장에 따라 다르지만

DB에 액세스할 때 사용하는 Bean, model Request(받기), Response(보내기)을 할때는 래퍼클래스로 작성을 한다

 

#사용 예제

package Study;

public class WrapperBean {
	private Integer boardNumber; //게시글 번호
	private String boardId;  //게시글 id
	private String boardTitle; //게시글 제목
	private String content; //내용
	private Integer upCount; //추천 카운트
	private Integer downCount; //비추천 카운트
	private Integer reportCount; //신고 카운트
}
package Study;

public class WrapperBean {
	private int boardNumber; //게시글 번호,  기본형인 int는 null처리를 못함
	private String boardId;  //게시글 id
	private String boardTitle; //게시글 제목
	private String content; //내용
	private int upCount; //추천 카운트
	private int downCount; //비추천 카운트
	private int reportCount; //신고 카운트
}
	@GetMapping("/viewBoard")
	public String boardInsert(@RequestParam("boardNumber")Integer boardNumber) {
		String url = "";//이동할 페이지
		
		return url;
	}

 

#박싱, 언박싱

  • 박싱 : 기본타입을 래퍼 클래스로 변환하는 작업
  • 언박싱 : 래퍼 클래스를 기본타입으로 변환하는 작업
Integer num = 10;
int count = num;//언박싱, Integer > int
Integer num2 = count;//박싱, int > Integer

 

#기본타입과 래퍼클래스의 비교

//래퍼클래스
Integer I = new Integer(10);
Integer II = new Integer(10);
//기본타입
int i = 10;
int ii = 10;
		
System.out.println("기본 == 기본" + (i == ii));
System.out.println("래퍼 == 래퍼" + (I == II));
System.out.println("래퍼 == 기본" + (I == i));
System.out.println("래퍼.equals(기본)" + I.equals(i));
System.out.println("래퍼.equals(래퍼)" + I.equals(II));

'Programming > JAVA' 카테고리의 다른 글

[JAVA] 대소문자 변환  (0) 2020.11.19
[SPRING] Spring 구조 및 DTO, VO 개념  (0) 2020.10.07
[JAVA] 정규표현식  (0) 2020.10.01
[JAVA] JUnit  (0) 2020.09.25
[lombok] 롬복 설치 방법  (0) 2020.09.23

#정규표현식이란

문자열에 정해진 문자열만 포함되어 있는가 검사해서 True, False로 결과를 반환하는 것

 

 

#정규표현식 작성 방법

문자 인코딩에 따라 조금씩 다르다

 ^

 문자열의 시작

 문자열의 종료

 .

 임의의 한 문자 (문자의 종류 가리지 않음)

 단, \ 는 넣을 수 없음

 *

 앞 문자가 없을 수도 무한정 많을 수도 있음

 앞 문자가 하나 이상

 앞 문자가 없거나 하나있음

 []

 문자의 집합이나 범위를 나타내며 두 문자 사이는 - 기호로 범위를 나타낸다. []내에서 ^가 선행하여 존재하면 not 을 나타낸다.

 {}

 횟수 또는 범위를 나타낸다.

 ()

 소괄호 안의 문자를 하나의 문자로 인식 

 |

 패턴 안에서 or 연산을 수행할 때 사용

 \s

 공백 문자

 \S

 공백 문자가 아닌 나머지 문자

 \w

 알파벳이나 숫자

\W 

 알파벳이나 숫자를 제외한 문자

\d 

 숫자 [0-9]와 동일

\D 

 숫자를 제외한 모든 문자

 정규표현식 역슬래시(\)는 확장 문자
 역슬래시 다음에 일반 문자가 오면 특수문자로 취급하고 역슬래시 다음에 특수문자가 오면 그 문자 자체를 의미

(?i) 

 앞 부분에 (?i) 라는 옵션을 넣어주면 대소문자를 구분하지 않음

 

#정규표현식 예제

1) 숫자만 : ^[0-9]+$

2) 영문자만 : ^[a-zA-Z]+$

3) 한글만 : ^[가-힣]+$

4) 영어 & 숫자만 : ^[a-zA-Z0-9]+$

5) E-Mail : ^[a-zA-Z0-9]+@[a-zA-Z0-9]+$

6) 휴대폰 : ^01(?:0|1|[6-9]) - (?:\d{3}|\d{4}) - \d{4}$

7) 일반전화 : ^\d{2,3} - \d{3,4} - \d{4}$

8) 주민등록번호 : \d{6} \- [1-4]\d{6}

9) IP 주소 : ([0-9]{1,3}) \. ([0-9]{1,3}) \. ([0-9]{1,3}) \. ([0-9]{1,3})

10) URL : "^(https?|ftp)(:\\/\\/[-_.!~*\\'()a-zA-Z0-9;\\/?:\\@&=+\\$,%#]+)$"

 

#일본 기준

1) 숫자만 : ^[0-9]+$

2) 영문자만 : ^[a-zA-Z]+$

3) 히라가나 : ^[\\u3040-\\u309F]+$  or  ^[ぁ-ん]+$

4) 가타카나 : ^[\\u30A0-\\u30FF]+$  or  ^[ァ-ヶ]+$

5) 반각 가타카나 : ^[\\uFF65-\\uFF9F]+$

6) 전각문자만 : ^[\\u3040-\\u30FF]+$

7) 한자 : ^[亜-熙]+$

 

 


#정규표현식 사용 예제

검사 방법은 3가지 방법이 있다

package Study;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PatternStudy {
	public static void main(String[] args) {
		String reg = "^[0-9]*$";//정규표현식
		String strValue = "ABC";//검사할 문자열
		
		// 결과를 true, false로 반환함
		System.out.println(Pattern.matches(reg, strValue));//Pattern클래스의 matches 메서드, 대상 문자열이 패턴과 일치하는지 검사
		System.out.println(reg.matches(strValue));//String클래스의 matches 메서드, 대상 문자열이 패턴과 일치하는지 검사
		
		// 결과를 true, false로 반환함
		Pattern pattern = Pattern.compile("^[0-9]*$");//주어진 정규표현식으로 패턴을 작성함
		Matcher matcher = pattern.matcher(strValue);//대상 문자열이 패턴과 일치하는지 검사
		System.out.println(matcher.find());
		
		//일본어
		String reg2 = "^[\\u3040-\\u309F]+$";
		String str = "あい";
		System.out.println(str.matches(reg2));
	}
}

 

 

#정규표현식을 조합해서 쓰는 방법도 존재한다

 

package Study;

public class PatternStudy2 {
	
	static final String ENGLISH_CODES = "a-zA-Z"; //영문자
	static final String KOREA_CODES = "가-힣"; //한글
	static final String NUMBER_CODES = "0-9"; //숫자
	static final String HIRAGANA_CODES = "\\u3040-\\u309F"; //히라가나
	static final String KATAKANA_CODES = "\\u30A0-\\u30FF"; //가타카나
	
	//지정한 문자만 허용하는 정규표현을 반환함
	public static String toMatchRegex(String codes) {
		return "^[" + codes + "]+$";
	}
	
	//지정 문자 이외만 허용하는 정규표현을 반환함
	public static String toNotMatchRegex(String codes) {
		return ".*[^" + codes + "].*";
	}
	
	public static void main(String[] args) {
		String str1 = "안녕하세요123";
		String str2 = "あいうえABC123";
		
		//지정한 문자만 허용하는 정규표현을 반환함
		System.out.println(str1.matches(toMatchRegex(KOREA_CODES + NUMBER_CODES)));
		System.out.println(str2.matches(toMatchRegex(HIRAGANA_CODES + ENGLISH_CODES + NUMBER_CODES)));
		
		//지정 문자 이외만 허용하는 정규표현을 반환함
		System.out.println(str1.matches(toNotMatchRegex(KOREA_CODES + NUMBER_CODES)));
		System.out.println(str2.matches(toNotMatchRegex(HIRAGANA_CODES + ENGLISH_CODES + NUMBER_CODES)));
	}

}

'Programming > JAVA' 카테고리의 다른 글

[SPRING] Spring 구조 및 DTO, VO 개념  (0) 2020.10.07
[JAVA] WrapperClass(래퍼 클래스)  (0) 2020.10.04
[JAVA] JUnit  (0) 2020.09.25
[lombok] 롬복 설치 방법  (0) 2020.09.23
[JAVA] String, StringBuffer, StringBuilder  (0) 2020.09.23

JUnit이란 자바 단위 테스트 도구이다

 

JUnit API : junit.org/junit4/javadoc/4.12/org/junit/experimental/categories/Categories.html

버전별 링크 : mvnrepository.com/artifact/junit/junit

 

Maven Repository: junit » junit

JUnit is a unit testing framework for Java, created by Erich Gamma and Kent Beck. VersionRepositoryUsagesDate4.13.x4.13Central5,037Jan, 20204.13-rc-2Central56Dec, 20194.13-rc-1Central54Oct, 20194.13-beta-3Central298May, 20194.13-beta-2Central118Feb, 20194.

mvnrepository.com

BuildPath를 통한 추가방법(추천)

프로젝트>Build Path>Configure Build Path

Add Library>JUnit 클릭

 

#Maven프로젝트 pom.xml에 추가

<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

#Gradle프로젝트 Build.gradle의 dependencies에 추가

dependencies {
	// https://mvnrepository.com/artifact/junit/junit
	testCompile group: 'junit', name: 'junit', version: '4.12'
}

 

#테스트 방법

테스트할 클래스 오른쪽마우스>New>Other 클릭

 

 

 

Java>JUnit>JUnit Test Case 선택후 다음

 

테스트할 JUnit버전 선택

테스트 패키지 이름은 테스트 대상 패키지와 동일하며 바꿔도 되고 안바꿔도 됩니다

 

테스트할 메서드 선택후 완료

 

 

test/java폴더 안에 패키지와 클래스 메서드가 자동 생성된 모습

 

 

테스트를 실행 할 클래스>Run As>JUnit Test 실행 (클래스내 @Test 어노테이션이 존재해야 보인다)

 

문제가 없다면 초록색, 문제가 있다면 빨간색 결과창을 보여줍니다

테스트할 클래스와 테스트를 하는 클래스는 패키지가 달라도 상관없지만

일반적으로는 개발환경과 동일 조건에서 테스트하기 위해 같은 위치에 작성해서 테스트합니다(사진은 다른위치)

 

#JUnit이 제공하는 메서드가 있는데 이것을 단정(assert Method) 메서드라고 합니다

단정 메서드 리스트 : junit.sourceforge.net/javadoc/org/junit/Assert.html

assertEquals(A, B);//객체 A와 B의 값이 일치하는가
assertSame(A, B);//객체 A와 B가 일치하는가
assertArrayEquals(A, B);//배열 A,B가 일치하는가
assertNotNull(A);//객체 A가 null인가 아닌가
assertTrue(A);//객체가 true인지 확인

JUnit은 해당 메서드를 통과하지 못하면 에러를 던집니다

 

#JUnit 어노테이션 종류

JUnit4/JUnit5 순서

  • @Test()/@Test : Test할 대상
  • @BeforeClass/@BeforeAll : 테스트 클래스가 실행될 때 실행 됨
  • @AfterClass/@AfterAll : 테스트 클래스가 종료될 때 실행 됨
  • @Before/@BeforeEach : @Test메서드가 실행될때 실행 됨
  • @After/@AfterEach : @Test메서드가 종료될때 실행 됨
  • @lgnore/@Disabled : 해당 테스트 메서드는 실행하지 않음

 

package com.example.demo;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import com.example.demo.controller.Calcurator;

public class JUnitTest2 {
	@BeforeClass//테스트 클래스가 실행 될때 실행 됨
	public static void beforeClassTest() {
		System.out.println("BeforeClass");
	}
	@Before//@Test메서드가 실행될 때 실행 됨
	public void beforeTest() {
		System.out.println("Before");
	}
	@After//@Test 메서드가 종료될 때 실행 됨
	public void afterTest() {
		System.out.println("after");
	}

	@AfterClass//테스트 클래스가 종료 될때 실행됨
	public static void afterClassTest() {
		System.out.println("AfterClass");
	}
	
	@Test
	public void calcuratorTest() {
		Calcurator calcurator = new Calcurator();
		double plus = calcurator.plus(10, 20);
		System.out.println("plus : " + plus);
	}
	@Test
	public void calcuratorTest1() {
		Calcurator calcurator = new Calcurator();
		double minus = calcurator.minus(10, 20);
		System.out.println("minus : " + minus);
	}	
}

 

@Test() 어노테이션은 여러 조건을 설정할 수 있다(JUnit5부터는 사용이 불가능 하다)

  • @Test(timeout = 1000) : 해당 테스트 메서드는 1000밀리초를 넘으면 에러를 던짐(시간은 임의설정 가능)
  • @Test(expected = RuntimeException.class) : 해당 테스트 메서드는 RuntimeException이 발생해야 통과

'Programming > JAVA' 카테고리의 다른 글

[JAVA] WrapperClass(래퍼 클래스)  (0) 2020.10.04
[JAVA] 정규표현식  (0) 2020.10.01
[lombok] 롬복 설치 방법  (0) 2020.09.23
[JAVA] String, StringBuffer, StringBuilder  (0) 2020.09.23
[JAVA] 프로그래밍 네이밍 규칙  (0) 2020.09.17

롬복의 기능은 자바 Bean의 getter setter의 자동생성이다

현업에서도 자주 사용된다

 

다운로드 링크 : projectlombok.org/download

 

실행시킬 위치에 lombok.jar파일 이동시키기

명령 프롬프트(CMD) 실행

 

jar 파일 실행 방법은 다음과 같다

java - jar 파일명.jar

 

아래 코드 복사해서 실행

java -jar lombok.jar

 

실행 후 스캔이 끝나면 이클립스가 설치된 위치가 나오며 install/update를 눌러주면 설치가 끝난다

 

 

이클립스 폴더를 가면 lombok.jar가 있는걸보아 반드시 명령프롬프트가 아닌

직접 jar파일을 넣어도 될듯하다

 

@Data 어노테이션을 클래스 위에 작성하는 것으로 끝이다

@Data
public class BoardVO {
	private String goodsNumber; //상품코드
	private String goodsName; //상품명
	private String goodsId; //상품 아이디(구분)
	private int goodsPrice;  //단가
	private int goodsCost;//원가
	private String fileName; //파일이름
	private Timestamp insertDate; //등록일자
	private Timestamp updateDate; //갱신일자
	
}

 

 

 

설치가 됐음에도 적용되지 않을때는

 

아래의 작업을 수행한다

 

#프로젝트 클린

 

#메이븐 업데이트

'Programming > JAVA' 카테고리의 다른 글

[JAVA] 정규표현식  (0) 2020.10.01
[JAVA] JUnit  (0) 2020.09.25
[JAVA] String, StringBuffer, StringBuilder  (0) 2020.09.23
[JAVA] 프로그래밍 네이밍 규칙  (0) 2020.09.17
[Spring] JSON  (0) 2020.09.16

+ Recent posts