create table board (
bno int auto_increment primary key,
title varchar(45) not null,
content text not null,
writer varchar(30) not null,
view_cnt int default 0 null,
comment_cnt int default 0 null,
reg_date datetime null
);
<mapper namespace="com.fastcampus.ch4.dao.BoardMapper">
<select id="select" parameterType="int" resultType="BoardDto">
SELECT bno, title, content, writer, view_cnt, comment_cnt, reg_date
FROM board
WHERE bno = #{bno}
</select>
public interfae BoardDao {
BoardDto select(Integer bno) throws Exception;
int delete(Integer bno) throws Exception;
int insert(BoardDto dto) throws Exception;
int update(BoardDto dto) throws Exception;
int increaseViewCnt(Integer bno) throws Exception;
}
@Repository
public class BoardDaoImpl implements BoardDao {
@Autowired private SqlSession session;
private static String namespace
= "com.fastcampus.ch4.dao.BoardMapper.";
public BoardDto select(Integer bno) throws Exception {
return session.selectOne(namespace + "select", bno);
}
계층간의 데이터를 주고받기 위해 사용되는 객체
//DB
create table board (
bno int auto_increment primary key,
title varchar(45) not null,
content text not null,
writer varchar(30) not null,
view_cnt int default 0 null,
commnet_cnt int default 0 null,
reg_date datetime null
);
public class BoardDto {
//null --> int (변환에러)
//null --> Integer (에러X)
private Integer bno;
private String title;
private String content;
private String writer;
private int view_cnt;
private int comment_cnt;
private Date reg_date;
//생성자, getter, setter, toString()
}
@Repository
public class BoardDaoImpl implements BoardDao {
@Autowired private SqlSession session;
private static String namespace
= "com.fastcampus.ch4.dao.BoardMapper.";
public BoardDto select(Integer bno) throws Exception {
return session.selectOne(namespace + "select", bno);
} //T selectOne(String statement, Object parameter)
관심사, 역할에 따라 계층을 분리
@Controller
요청과 응답을 처리
데이터 유효성 검증
실행 흐름을 제어
@Service
비지니스 로직 담당
트랜잭션 처리
예외를 try-catch로 직접 처리하거나 컨트롤러로 넘김.
@Repository
순수 Data Access 기능
조회, 등록, 수정, 삭제
DAO에서 예외처리를 하면,
Tx에서 commit, rollback을 결정할 수 없으므로
예외를 무조건 서비스계층으로 넘김
//#{} SQL Injection공격 방지, 타입을 알아서 ?에 넣어줌
<insert id="insert" parameterType="BoardDto">
INSERT INTO board (title, content, writer)
VALUES (#{title}, #{content}, #{writer})
</insert>
//이렇게 변환
String sql = "INSERT INTO board "
+ " (title, content, writer) "
+ "VALUES "
+ " (?, ?, ?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
int result = pstmt.executeUpdate();
//${} 위와 달리 유연한 코드
<insert id="insert" parameterType="BoardDto">
INSERT INTO board
(title, content, writer)
VALUES
('${title}', '${content}', '${writer}')
</insert>
//변환
String sql = "INSERT INTO board "
+ " (title, content, writer) "
+ "VALUES "
+ " ('"+title+"', '"+content+"', '"+writer+"')";
Statement stmt = conn.createStatement();
int result = stmt.executeUpdate(sql);
태그와 구분을 위해 xml내의 특수문자(<,>,&,...)는 < >로 변환 필요.
또는 특수문자가 포함된 쿼리를 <![CDATE[ ]]>
로 감싼다.
//<, >
<update id="update" parameterType="BoardDto">
UPDATE board
SET title = #{title}
, content = #{content}
, up_date = now()
WHERE bno = #{bno} and bno < > -
</update>
//<![CDATA[ ]]>
<update id="update" parameterType="BoardDto">
<![CDATA[
UPDATE board
SET title = #{title},
content = #{content},
up_date = now()
WHERE bno = #{bno} and bno <> 0
]]>
</update>