[spring] 영속 영역 CRUD 복습

업데이트:


설정

  • 설정 부분은 생략
  • 버전
    • spring : 5.2.8
    • java : 1.8
    • servlet : 3.1.0
    • junit : 4.12
    • Lombok : 1.18.0
    • HikariCP : 4.0.3
    • mybatis : 3.4.6
    • mybatis-spring : 1.3.2
    • log4jdbc-log4j2 : 1.16





VO 생성

package org.example.domain;

import java.util.Date;

import lombok.Data;

@Data 
// Data 어노테이션을 사용하면 getter/setter, toString() 등을 자동으로 만들어준다.
public class BoardVO {
	private long bno;
	private String title;
	private String content;
	private String writer;
	private Date regdate;
	private Date updateDate;
	
}




Mapper 인터페이스, Mapper XML 생성

mapper와 관련된 설정을 하는 곳은 root-context.xml이다.

<mybatis-spring:scan base-package="org.example.mapper" />


Mapper 인터페이스 생성(SELECT)

package org.example.mapper;

import java.util.List;

import org.example.domain.BoardVO;

public interface BoardMapper {
	
	public List<BoardVO> getList();
	
}



Mapper XML 생성(SELECT)

src/main/resources 경로에 org/example/mapper 폴더 경로 생성 후 BoardMapper.xml 파일 생성

mapperxml경로

<?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="org.example.mapper.BoardMapper">

<select id="getList" resultType="org.example.domain.BoardVO">
<![CDATA[select * from tbl_board where bno>0]]>
</select>


</mapper>



테스트 코드 작성

src/test/java에 org.example.mapper.BoardMapperTests 클래스를 생성한다.

package org.example.mapper;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import lombok.Setter;
import lombok.extern.log4j.Log4j;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
@Log4j
public class BoardMapperTests {
	@Setter(onMethod_ = @Autowired)
	private BoardMapper mapper;
	
	@Test
	public void testGetList() {
		mapper.getList().forEach(board -> log.info(board));
	}
}


위의 테스트 코드를 실행해보니까 아래와 같은 오류가 계속 났다.

mybatis에러

root-context.xml, pom.xml을 아무리 살펴봐도 오타가 없길래 아래 테스트 코드를 추가했다.

테스트코드추가

// DataSourceTests.java

package org.zerock.persistence;

import static org.junit.Assert.fail;
import java.sql.Connection;
import javax.sql.DataSource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import lombok.Setter;
import lombok.extern.log4j.Log4j;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
@Log4j
public class DataSourceTests {
	@Setter(onMethod_ = { @Autowired })
	private DataSource dataSource;
	@Test
	public void testConnection() {
		try (Connection conn = dataSource.getConnection()){
			log.info(conn);
		} catch (Exception e) {
			fail(e.getMessage());
		}
	}
}


package org.zerock.persistence;

import static org.junit.Assert.fail;
import java.sql.Connection;
import java.sql.DriverManager;
import org.junit.Test;
import lombok.extern.log4j.Log4j;

@Log4j
public class JDBCTests {
	static {
		try {
			Class.forName("oracle.jdbc.driver.OracleDriver");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Test
	public void testConnection() {
		
		try(Connection conn = DriverManager.getConnection(
				"jdbc:oracle:thin:@localhost:1521:XE",
				"book_ex",
				"book_ex")){
			log.info(conn);
		} catch (Exception e) {
			fail(e.getMessage());
		}
	}
}


이 두 개의 테스트 코드에서도 에러가 나길래 아예 JDBC 연결이 안 되고 있음을 알았다. 그래서 혹시나 ojdbc 라이브러리가 추가가 안되어있나 봤더니 역시나 안 되어 있었다. 아까 추가한 것 같았는데 두 번째 맹그는 프로젝트였어서 이번에는 추가를 까먹었었나보다. 그래서 ojdbc8.jar 파일을 추가했다.
ojdbc추가

ojdbc8.jar 추가 후 테스트 코드를 실행했는데 에러 없이 게시글 리스트를 잘 받아왔다.





CREATE(INSERT) 구현

CREATE(INSERT) 처리는 아래 두 상황을 고려해야한다.

  • INSERT만 처리되고 생성된 PK 값을 알 필요없는 경우
  • INSERT문이 실행되고 생성된 PK 값을 알아야 하는 경우

BoardMapper 인터페이스

// 추가
public void insert(BoardVO board);

public void insertSelectKey(BoardVO board);


BoardMapper.xml

<insert id="insert">
	INSERT INTO tbl_board (bno, title, content, writer)
	values (seq_board.nextval, #{title}, #{content}, #{writer})
</insert>

<insert id="insertSelectKey">
	<selectKey keyProperty="bno" order="BEFORE"
		resultType="long">
		select seq_board.nextval from dual
		</selectKey>
		
		insert into tbl_board(bno, title, content, writer)
		values(#{bno}, #{title}, #{content}, #{writer})
</insert>


테스트 코드 작성

@Test
public void testInsert() {
	BoardVO board = new BoardVO();
	board.setTitle("새로작성하는그을");
	board.setContent("새로작성하는내요옹");
	board.setWriter("나");
	
	mapper.insert(board);
	
	log.info(board);
}

insert테스트로그

insertSelectKey로그





테스트용 테이블 생성

기존 tbl_board 테이블에 데이터가 너무 많아서 로그를 확인하기 힘들어 새로운 테이블을 하나 더 생성했다.

CREATE SEQUENCE seq_board2;

CREATE TABLE tbl_board2 (
    bno number(10, 0),
    title varchar2(200) not null,
    content varchar2(2000) not null,
    writer varchar2(50) not null,
    regdate date default sysdate,
    updatedate date default sysdate
);

ALTER  TABLE  tbl_board2 ADD CONSTRAINT pk_board2 PRIMARY KEY (bno);


INSERT INTO tbl_board2 (bno, title, content, writer) VALUES (seq_board2.NEXTVAL, '테스트 제목', '테스트 내용', 'user00');
commit;

테이블과 데이터 하나를 넣은 후, Mapper에 변경된 테이블 이름, 시퀀스 이름으로 수정해주면 된다.





READ(SELECT) 처리

BoardMapper 인터페이스

// READ(select)
public BoardVO read(Long bno);



BoardMapper.xml

<select id="read"	resultType="org.example.domain.BoardVO">
	SELECT * FROM tbl_board2 WHERE BNO = #{bno}
</select>



테스트 코드

@Test
public void testRead() {
	BoardVO board = mapper.read(1L);
	log.info(board);
}


위의 테스트 코드를 실행하면 아래와 같이 로그가 찍히면 에러 없이 잘 실행된 것이다.

read로그





delete 처리

BoardMapper 인터페이스

// delete
public int delete(Long bno);



BoardMapper.xml

<delete id="delete">
	DELETE FROM tbl_board2 WHERE BNO = #{bno}
</delete>



테스트 코드 작성

@Test
public void testDelete() {
	log.info("Delete : " + mapper.delete(5L));
}


위의 코드를 실행하면 아래와 같이 로그가 출력된다.

delete로그

출력되는 Delete : 1은 정상적으로 게시글 삭제가 완료되었다는 의미이다. 만약 게시글이 없거나, 오류로 인해 게시글이 삭제가 되지 않았다면 0을 반환한다.





update 처리

BoardMapper 인터페이스

// update
public int update(BoardVO board);



BoardMapper.xml

<update id="update">
	UPDATE tbl_board2 SET
	title = #{title},
	content = #{content},
	writer = #{writer},
	updateDate = sysdate
	WHERE BNO = #{bno}
</update>



테스트 코드 작성

@Test
public void testUpdate() {
	BoardVO board = new BoardVO();
	
	board.setBno(1L);
	board.setTitle("수정한 그을");
	board.setContent("수정한 내요옹");
	board.setWriter("수정한 작성자");
	
	int count = mapper.update(board);
	log.info("Update : " + count);
}


위 테스트 코드를 실행하면 아래와 같이 로그가 출력된다.
update 로그



영속 영역 CRUD 구현 끝!

태그:

카테고리:

업데이트:

댓글남기기