persistence 계층에서는 DB에 접근하여 SQL문을 실행하고, 데이터를 VO형태로 읽고 쓸 수 있는 DAO(Data Acess Object)을 구현하는 작업을 수행 합니다.
Mybatis 초기설정
DAO를 구현하기 위해 최초 1회 설정해야하는 DB와의 연동 작업을 수행합니다.
- DataSource 등록
mysql 서버에 연결할 때 필요한 정보를 가지고 있는 DataSource를 root_context.xml에 추가 합니다.
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/blog?serverTimezone=UTC"></property>
<property name="username" value="root"></property>
<property name="password" value="1234"></property>
</bean>
- DataSource Test
DataSource 객체가 제대로 생성이 되었는지 테스트 합니다.
package kr.co.web;
import java.sql.Connection;
import javax.inject.Inject;
import javax.sql.DataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
//Runner 클래스(테스트 메소드를 실행하는 클래스) 를 SpringJUnit4ClassRunner로 함
@RunWith(SpringJUnit4ClassRunner.class)
//location 속성 경로에 있는 xml 파일을 이용해서 스프링이 로딩됨
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/**/root-context.xml")
public class DataSourceTest {
//DataSource의 객체를 new를 사용해 따로 생성해줄 필요없이 스프링이 생성해서 주입해줌
@Inject
private DataSource ds;
@Test
public void testConnection() throws Exception{
try(Connection con = ds.getConnection()){
System.out.println(con);
}catch(Exception e) {
e.printStackTrace();
}
}
}
- XML 네임스페이스 추가
root-context.xml의 NameSpaces를 다른 확장자도 사용할 수 있도록 추가합니다.
- mybatis-config.xml 추가
mybatis의 별도 설정을 담당하기 위한 파일로 mybatis-config.xml 파일을 src/main/resource에 추가
<?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>
</configuration>
- root-context.xml에 SqlSessionFactory, SqlSessionTemplate 추가
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="classpath:/mybatis-config.xml"></property>
<property name="mapperLocations" value="classpath:mappers/**/*Mapper.xml"></property>
</bean>
<!-- sqlSessionTemplate -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"
destroy-method="clearCache">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
</bean>
<!-- kr.co.web.persistence 패키지를 자동으로 인식 -->
<context:component-scan base-package="kr.co.web.persistence">
</context:component-scan>
- MyBatis Test
MyBatis와 Mysql이 제대로 연결 되었는지 테스트
package kr.co.web;
import javax.inject.Inject;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
//Runner 클래스(테스트 메소드를 실행하는 클래스) 를 SpringJUnit4ClassRunner로 함
@RunWith(SpringJUnit4ClassRunner.class)
//location 속성 경로에 있는 xml 파일을 이용해서 스프링이 로딩됨
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/**/root-context.xml")
public class MyBatisTest {
//SqlSessionFactory 객체를 자동으로 생성
@Inject
private SqlSessionFactory sqlFactory;
//SqlSessionFactory 객체가 제대로 만들어졌는지 Test
@Test
public void testFactory() {
System.out.println(sqlFactory);
}
//MyBatis와 Mysql 서버가 제대로 연결되었는지 Test
@Test
public void testSession() throws Exception{
try(SqlSession session = sqlFactory.openSession()){
System.out.println(session);
}catch(Exception e) {
e.printStackTrace();
}
}
}
Board 테이블 생성
워크벤치에 board 테이블을 생성(워크벤츠 사용법은 어렵지 않기 떄문에 검색!)
CREATE TABLE board (
board_number int NOT NULL AUTO_INCREMENT,
title varchar(200) NOT NULL,
contents text,
name VARCHAR(30) NOT NULL,
create_date timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
view_count int DEFAULT 0,
PRIMARY KEY (board_number)
);
정상적으로 테이블이 생성되었습니다.
이제 SQL을 실행할 boardMapper.xml을 추가합니다.
<!-- /resource/mappers/boardMapper.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<!-- DTD 선언 -->
<!DOCTYPE mapper
PUBLIC "-//mybatis.org/DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="BoardMapper">
<!-- 데이터 삽입 -->
<insert id="create">
insert into board (title, contents, name)
values( #{title}, #{contents}, #{name})
</insert>
<!-- 행 검색 -->
<select id="read" resultType="kr.co.web.domain.BoardVO">
select *
from board
where board_number = #{board_number}
</select>
<!-- 행 수정 -->
<update id="update">
update board
set title = #{title}, contents = #{contents}
where board_number = #{board_number}
</update>
<!-- 행 삭제 -->
<delete id="delete">
delete from board where board_number = #{board_number}
</delete>
<!-- board 전체 행 조회 -->
<select id="listAll" resultType="kr.co.web.domain.BoardVO">
select *
from board
order by board_number desc, regdate desc
</select>
<!-- bno 최대 구하기 -->
<select id="getMaxBno" resultType="Integer">
select max(board_number) from board
</select>
</mapper>
resultType
- resultType을 사용하게 되면 결과 값을 BoardVO의 setter에 값을 넣어주고, 이용자는 getter를 통해 해당 데이터를 이용할 수 있다.
BoardVO 구현
DB를 이용할 때 데이터를 넣고 데이터를 가져와서 사용하기 위해 데이터를 담을 공간인 BoardVO를 작성합니다.
package kr.co.web.domain;
import java.util.Date;
public class BoardVO {
private Integer board_number;
private String title;
private String contents;
private String name;
private Date create_date;
private int view_count;
public Integer getBoard_number() {
return board_number;
}
public void setBoard_number(Integer board_number) {
this.board_number = board_number;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContents() {
return contents;
}
public void setContents(String contents) {
this.contents = contents;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreate_date() {
return create_date;
}
public void setCreate_date(Date create_date) {
this.create_date = create_date;
}
public int getView_count() {
return view_count;
}
public void setView_count(int view_count) {
this.view_count = view_count;
}
@Override
public String toString() {
return "BoardVO [board_number=" + board_number + ", title=" + title + ", contents=" + contents + ", name=" + name + ", create_date="
+ create_date + ", view_count=" + view_count + "]";
}
}
DAO 인터페이스 작성
좀전에 만들었던 BoardMapper.xml에 SQL문을 실제로 실행하기 위해
BoardDAO.java 인터페이스를 kr.co.web.persistence에 작성합니다.
package kr.co.web.persistence;
import java.util.List;
import kr.co.web.domain.BoardVO;
public interface BoardDAO {
public void create(BoardVO board) throws Exception;
public BoardVO read(Integer board_number) throws Exception;
public void update(BoardVO board) throws Exception;
public void delete(Integer board_number) throws Exception;
public List<BoardVO> listAll() throws Exception;
public Integer getMaxBoard_number() throws Exception;
}
이제 BoardDAO 인터페이스의 메소드를 구현합니다.
package kr.co.web.persistence;
import java.util.List;
import javax.inject.Inject;
import org.apache.ibatis.session.SqlSession;
import kr.co.web.domain.BoardVO;
@Repository
public class BoardDAOImpl implements BoardDAO{
// SQL문을 실행하는 메소드를 가지고 있는 SqlSession을 구현한 SqlSessionTemplate을 찾아서 객체를 자동으로 생성
@Inject
private SqlSession session;
private static String NS = "BoardMapper";
private static String CREATE = NS + ".create";
private static String READ = NS + ".read";
private static String UPDATE = NS + ".update";
private static String DELETE = NS + ".delete";
private static String LISTALL = NS + ".listAll";
private static String GETMAXBOARD_NUMBER = NS + ".getMaxBno";
@Override
public void create(BoardVO board) throws Exception {
session.insert(CREATE, board);
// 글을 작성할 때 입력한 값을 boardVO에 넣어주기 위해 파라미터값을 board로 함
}
@Override
public BoardVO read(Integer board_number) throws Exception {
return session.selectOne(READ, board_number);
// 글을 읽기 위해 mapper에 where절에 게시글번호가 필요하기 때문에 board_number로 설정하고 boardVO를 리턴값으로 설정
}
@Override
public void update(BoardVO board) throws Exception {
session.update(UPDATE, board);
}
@Override
public void delete(Integer board_number) throws Exception {
session.delete(DELETE, board_number);
}
@Override
public List<BoardVO> listAll() throws Exception {
return session.selectList(LISTALL);
}
@Override
public Integer getMaxBoard_number() throws Exception {
return session.selectOne(GETMAXBOARD_NUMBER);
}
}
typeAliases 적용
BoardMapper.xml에 있는 쿼리문에서 resultType을 패키지명과 같이 작성하였는데
MyBatis의 설정 파일인 mybatis-config.xml을 이용하여 typeAliases를 사용하면
resultType에 패키지명을 붙이지 않아도 됩니다.
<?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>
<typeAliases>
<package name="kr.co.web.domain" />
</typeAliases>
</configuration>
'JAVA > blog' 카테고리의 다른 글
controller를 작성하기 전에 알아야 할 사항 (0) | 2020.07.08 |
---|---|
비즈니스 계층(service) (0) | 2020.07.08 |
게시판 project 초기설정 (0) | 2020.07.08 |
프로젝트 생성 후 character encoding setting (0) | 2020.07.06 |
게시판 목록페이지와 정보 유지 (0) | 2020.02.20 |