[Spring To-do] domain- mapper-Service설정

Jeskey·2024년 1월 24일

[Spring Legacy] To-do

목록 보기
8/9

✅ 테이블 생성

우선 SQL Delevoper로 todo 테이블을 생성한다.

create table tbl_todo(
    tno Number generated always as identity primary key,
    content VARCHAR(255) Not Null,
    finished CHAR default '0'
);

generated always as identity
오라클 12c부터 새로 생긴 기능이다. 기존에는 sequence를 이용하여 데이터 삽입 시 자동으로 숫자가 증가하도록 해야 했지만 저 구문을 이용하면 자동으로 처리된다(내부처리는 시퀀스로 이루어진다).
default 구문을 사용해 finished 컬럼의 기본값을 '0'(false)로 설정했다.


✅ 자바 클래스 생성

프로젝트에 domain 패키지를 만든 후 TodoVO 클래스를 생성한다.

📂 TodoVO.java

@Getter
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class TodoVO {
	
	private Long tno;
	private String content;
	private char finished;
}

@AllArgsConstructor : 인스턴스 변수로 선언된 모든 것을 파라미터로 받는 생성자를 가진다(public 클래스이름 메소드 따로 만들필요 없어짐).

@NoArgsConstructor : 파라미터가 없는 기본 생성자 생성

자바에서는 파라미터가 존재하는 생성자를 만들 경우 반드시 파라미터가 없는 기본 생성자를 만들어야 한다. 그럴 때 이 어노테이션을 이용하여 편리하게 생성자를 작성할 수 있다.


그 다음 TodoMapper에서 insert 기능을 담당하는 메서드를 만든다.

📂 TodoMapper.java

public interface TodoMapper {
	
	void insert(TodoVO todoVO);
}

파라미터는 TodoVO 객체다.

그 후 resources/mapper/TodoMapper.xml 파일에 sql문을 입력한다.

<mapper namespace="org.jeskey.todo.mapper.TodoMapper">'
		<insert id="insert">
			insert into tbl_todo (content) values (#{content})
		</insert>
</mapper>

반환타입이 void이므로 resultType은 작성할 필요가 없다.

테스트 메서드를 작성해 정상적으로 데이터가 입력되는 것을 확인한다.

	@Test
	public void insert() {
		TodoVO todoVO = TodoVO.builder()
				.content("투두 테스트")
				.build();
		
		todoMapper.insert(todoVO);
	}


컨트롤러와 VO의 중간 계층인 TodoDTOTodoService 클래스를 작성한다.

📂 TodoDTO

@ToString
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class TodoDTO {
	private Long tno;
	private String content;
	private boolean finished;
}

TodoVO와 다른 점이 있다면 finished 컬럼이 boolean이라는 점이다.
기능의 명확성을 위해 화면에선 boolean 타입으로 값을 받고(TodoDTO 타입으로 값을 받고) Service 계층에서 DTO를 VO로 적절히 변환할 예정이다. (register 기능에선 변환이 필요없으므로 작성하지 않았다)

@Setter 어노테이션을 사용하는 이유
스프링의 특징은 컨트롤러에서 jsp에서 보내는 변수를 파라미터로 자동 수집해준다는 점이다.
이 때, 객체의 경우 set 메소드를 통해 각 파라미터 값을 DTO 변수 값에 할당하므로, @Setter 어노테이션이 필요하다.

📂 TodoService.java

public interface TodoService {
	void register(TodoDTO todoDTO);
}

📂 TodoServiceImpl.java

@RequiredArgsConstructor
public class TodoServiceImpl implements TodoService{
	
	private final TodoMapper todoMapper;
	
	@Override
	public void register(TodoDTO todoDTO) {
		
		TodoVO todoVO = TodoVO.builder()
		.content(todoDTO.getContent()).build();
		
		todoMapper.insert(todoVO);
	}
	
}

Builder를 이용해 dto 객체를 vo 객체로 변환한 뒤 mapper를 통해 입력하는 코드이다.


테스트 코드를 이용해 제대로 데이터가 삽입되는 것을 확인한다.

📂 TodoServiceTests.java

@Log4j
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
public class TodoServiceTests {

	@Autowired
	private TodoService todoService;
	
	@Test
	public void insert() {
		
		TodoDTO dto = TodoDTO.builder()
				.content("서비스 테스트").build();
		
		todoService.register(dto);
	}
	
}

  • 전체 Todo 리스트를 가져오는 getList() 메서드
  • 체크박스를 눌러 완료 상태면 미완료, 미완료 상태면 완료로 상태를 변경하는 finish() 메서드
  • 작업을 삭제하는 remove() 메서드

    를 추가로 작성한다.

✅ 전체 코드

📂 TodoMapper.xml

<mapper namespace="org.jeskey.todo.mapper.TodoMapper">
		
		<insert id="insert">
			insert into tbl_todo (content) values (#{content})
		</insert>
		
		<select id="getList" resultType="org.jeskey.todo.domain.TodoVO">
			select * from tbl_todo
		</select>
		
		<delete id="delete">
			delete from tbl_todo
			where tno = #{tno}
		</delete>
		
		<update id="finish">
			update tbl_todo
			set finished = #{finished}
			where tno = #{tno}
		</update>
		
</mapper>

📂 TodoMapper.java


public interface TodoMapper {
	
	void insert(TodoVO todoVO);
	
	List<TodoVO> getList();
	
	void finish(TodoVO todoVO);
	
	void delete(Long tno);
}

📂 TodoService.java

public interface TodoService {
	void register(TodoDTO todoDTO);
	
	List<TodoDTO> getList();
	
	void finish(TodoDTO todoDTO);
	
	void remove(Long tno);
}

📂 TodoServiceImpl.java

@Service
@RequiredArgsConstructor
@Log4j
public class TodoServiceImpl implements TodoService{
	
	private final TodoMapper todoMapper;
	
	@Override
	public void register(TodoDTO todoDTO) {

		TodoVO todoVO = TodoVO.builder()
		.content(todoDTO.getContent()).build();
		
		todoMapper.insert(todoVO);
	}

	@Override
	public List<TodoDTO> getList() {
		
		List<TodoDTO> dtoList = todoMapper.getList().stream().map(vo -> 
		TodoDTO.builder()
		.tno(vo.getTno())
		.content(vo.getContent())
		.finished(vo.getFinished()=='0'?false:true).build())
				.collect(Collectors.toList());
		
		return dtoList;
	}	
	
	@Override
	public void finish(TodoDTO todoDTO) {
		TodoVO vo = null;
		
		if(!todoDTO.isFinished()) {
			vo = TodoVO.builder()
			.tno(todoDTO.getTno())
			.finished('1').build();
		}else{
			vo = TodoVO.builder()
			.tno(todoDTO.getTno())
			.finished('0').build();
		}
		
		todoMapper.finish(vo);
	}

	@Override
	public void remove(Long tno) {
    
		todoMapper.delete(tno);
	}
}

📂 TodoServiceTests.java

@Log4j
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
public class TodoServiceTests {

	@Autowired
	private TodoService todoService;
	
	@Test
	public void insert() {
		
		TodoDTO dto = TodoDTO.builder()
				.content("서비스 테스트").build();
		
		todoService.register(dto);
	}
	
	@Test
	public void getList() {
		
		todoService.getList().stream().forEach(dto -> 
				log.info(dto));
	}
	
	@Test
	public void finish() {
		
		TodoDTO dto = TodoDTO.builder()
		.tno(2L)
		.finished(false)
		.build();
		
		todoService.finish(dto);
	}
	
	@Test
	public void remove() {
		
		todoService.remove(65L);
	}
}

0개의 댓글