[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 파일 생성
<?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));
}
}
위의 테스트 코드를 실행해보니까 아래와 같은 오류가 계속 났다.
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 파일을 추가했다.
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);
}
테스트용 테이블 생성
기존 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);
}
위의 테스트 코드를 실행하면 아래와 같이 로그가 찍히면 에러 없이 잘 실행된 것이다.
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 : 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);
}
위 테스트 코드를 실행하면 아래와 같이 로그가 출력된다.
영속 영역 CRUD 구현 끝!
댓글남기기