"코드 복사하기"를 했다면,
"더 줄일수는 없을까?" (모듈화, 캡슐화,...)를 고민 해봐야 한다
1) 기존 JDBC 코드 작업중...
JDBC로직이 반복되네? (DAO의 selectAll,selectOne,insert,update,delete)
더 줄일수는 없을까?
=> 유사하거나 반복되는 알고리즘을 캡슐화하여 재사용하는 패턴
Template 패턴
코딩 순서가 정해져있는(정형화된) 기술에서 특히 유용하게 활용됨
JDBC, 트랜잭션, Mybatis, JPA, ...(db류에서 활용)
db랑 관련되어있는 애들이 하는 행동이 똑같음
※ 패턴
: MVC, 팩토리(객체생성코드를 캡슐화 하는거; new를 숨겨두는거==결합도가 낮아짐),
싱글톤 (메모리성능향상; 동일한 타입 객체 1개만 남김)
<!-- Spring JDBC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- DBCP -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
2) "JDBCTemplate" 클래스를 적용하여 DAO 구성하기
- jar파일 필요
라이브러리 2개 추가
-> 라이브러리 관리는 pom.xml이 함
3) pom.xml에 jar파일을 2개 추가 DBCP (database connection pool)
= connection들을 대신 관리해주는 주체(객체)
커넥션들을 더이상 직접 관리 안함
4) conn을 DB로부터 확보하는것에서부터 시작
5) JDBCTemplate 클래스는 DataSource 객체를 통해 conn을 확보 및 관리함
6) DataSource 객체를 생성해야함
스프링 컨테이너가 생성하도록 해야함
<bean> 등록을 해야함 (new를 bean을 통해서 함)
이거 꺼내쓰려고 jar넣은거임
\<bean class="org.apache.commons.dbcp.BasicDataSource"></bean>
커넥션 너무 많이 하면 톰캣기반이라 (apache라고 써있음) 연결해제가 제대로 되지 않으면 서버실행이 동작 안할수도있다
꺼냈으면 닫아 :
\<bean class="org.apache.commons.dbcp.BasicDataSource" id="dataSource" destroy-method="close"></bean\>
7) DataSource 객체 <bean> 등록시,
setter DI을 함께 설정해야함
\<property name = "driverClassName" value ="oracle,jdbc.driver.OracleDriver"/>
String이라서 여기 value라는 속성이 들어감 (reference대신)
\<property name="url" value="jdbc:oracle:thin:@localhost:1521:xe"/>
\<property name="username" value="KIM"/>
\<property name="password" value="1234"/>
CUD는 update (executeUpdate같은거)
R에서는 VO를 받아내야 함
jdbcTemplate.queryForObject를 써야함
객체를 받겠다
public boolean insert(BoardVO bVO) {
System.out.println("BoardDAO2 로그 insert() 메서드");
//쿼리문 ??? 데로 인자를 나열
int rs=jdbcTemplate.update(insert,bVO.getTitle(),bVO.getContent(),bVO.getWriter()); //update의 반환타입이 int임
if(rs<=0) {
return false;
}
return true;
}
public boolean update(BoardVO bVO) {
System.out.println("BoardDAO2 로그 update() 메서드");
int rs=0;
if(bVO.getSearchCondition()!=null && bVO.getSearchCondition().equals("CNT")) {
rs=jdbcTemplate.update(update_CNT,bVO.getBid());
}
else {
rs=jdbcTemplate.update(update,bVO.getTitle(),bVO.getContent(),bVO.getBid());
}
if(rs<=0) {
return false;
}
return true;
}
public boolean delete(BoardVO bVO) {
System.out.println("BoardDAO2 로그 update() 메서드");
int rs=jdbcTemplate.update(delete,bVO.getBid());
if(rs<=0) {
return false;
}
return true;
}
update 에서는 인자개수가 정해져있지 않았기때문에 그냥 나열 하면 됬음
queryForObject()는 update와 달리 메서드시그니쳐가정해져있음. 인자가 3개로 고정되어있음
SQL을 실행할때에 필요한 INPUT과, << 이때 input은 배열의 형태로
SQL을 실행완료한후의 OUTPUT을 각각 지정해야함 << output은 객체의 형태로 지정 해 줄것임
public BoardVO selectOne(BoardVO bVO) {
System.out.println("BoardDAO2 로그 selectOne() 메서드");
//jdbcTemplate.queryForObject(selectOne,INPUT,OUTPUT);
Object[] args= { bVO.getBid() };
//sql sql에 들어갈거 sql수행결과
//jdbcTemplate.queryForObject(selectOne,args, new BoardRowMapper());
//이게 bVO기때문에
return jdbcTemplate.queryForObject(selectOne,args, new BoardRowMapper());
}
public List<BoardVO> selectAll(BoardVO bVO) {
System.out.println("BoardDAO 로그 selectAll() 메서드");
//jdbcTemplate.query(selectAll, INPUT, OUTPUT);
//?물음표가 없으니 input은 생략 (들어갈게 없다)
//ouput: BoardVO를 만들어야 한다
//jdbcTemplate.query(selectAll, new BoardRowMapper()); 아웃풋이 list기때문에 return으로
if(bVO.getSearchCondition()==null || bVO.getSearchCondition().isEmpty()) {
return jdbcTemplate.query(selectAll, new BoardRowMapper());
}
else if(bVO.getSearchCondition().equals("TITLE")) {
Object[] args= { bVO.getTitle() };
return jdbcTemplate.query(selectAll_TITLE, args, new BoardRowMapper());
}
else if(bVO.getSearchCondition().equals("WRITER")) {
Object[] args= { bVO.getWriter() };
return jdbcTemplate.query(selectAll_WRITER, args, new BoardRowMapper());
}
return null;
}
selectOne을 수행할때 int,String,등등 뭐가 들어갈지 모르는데 배열을 만들어야함
그래서 최상위클래스 Object[]로 되어있는 배열을 만들거임
객체로 반환 해야해:
new BoardRowMapper << 이 이름을 가진 클래스가 있어야 함
제네릭을 반드시 함께 사용
class BoardRowMapper implements RowMapper<BoardVO> {
@Override
public BoardVO mapRow(ResultSet rs, int rowNum) throws SQLException {
BoardVO data=new BoardVO();
data.setBid(rs.getInt("BID"));
data.setCnt(rs.getInt("CNT"));
data.setContent(rs.getString("CONTENT"));
data.setTitle(rs.getString("TITLE"));
data.setWriter(rs.getString("WRITER"));
return data;
}
}
RowMapper 인터페이스는
selectAll은 그냥 query() 여러개를 봐야하니까
jdbcTemplate.query(selectAll, new BoardRowMapper());
Q)이거 어떻게 여러개 나올줄 알아요?
A) int rowNum이 내부적으로 암
rowNum 출력 해보면 됨
8) DAO의 클래스의 멤버변수로 JdbcTemplate을 등록
->DI(의존주입)
무언갈 멤버변수로 삼았으면 의존주입 해줘야함
9) DI할 객체가 없음... jdbcTemplate을 new를 안했음 아직
new를 해줘야함; 등록해야함 : applicationContext.xml(루트컨테이너)
이때 dataSource 객체를 setter주입함
<!-- JdbcTemplate에 DI할 객체 생성 -->
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<aop:aspectj-autoproxy />
10) DAO2를 사용해보자!
DAO는 Service가 씀
@Autowired
//private BoardDAO boardDAO;
private BoardDAO2 boardDAO;
service 레이어를 사용해주고 있기때문에 BoardDAO명만 바꾸면 됨
그리고 이제 BoardDAO2가 서비스레이어를 사용함
Service의 멤버변수 변경
@Repository로 Service에 의존주입할 객체 생성
인제 이거 제거 해도 됨
private final String selectAll="SELECT * FROM BOARD ORDER BY BID DESC";
public class BoardDAO2 { //이름 1,2,3,4 라고 붙이는 일은 실무에서 없음
@Autowired
private JdbcTemplate jdbcTemplate; //더이상 Conn이나 preparedStatement를 직접 받지 않음
private final String insert="INSERT INTO BOARD (BID,TITLE,CONTENT,WRITER) VALUES((SELECT NVL(MAX(BID),0)+1 FROM BOARD),?,?,?)";
private final String selectOne="SELECT * FROM BOARD WHERE BID=?"; // getOne
private final String selectAll_TITLE="SELECT * FROM BOARD WHERE TITLE LIKE '%'||?||'%' ORDER BY BID DESC";
private final String selectAll_WRITER="SELECT * FROM BOARD WHERE WRITER LIKE '%'||?||'%' ORDER BY BID DESC";
private final String update="UPDATE BOARD SET TITLE=?,CONTENT=? WHERE BID=?";
private final String update_CNT="UPDATE BOARD SET CNT=CNT+1 WHERE BID=?";
private final String delete="DELETE FROM BOARD WHERE BID=?";
selectAll = SELECT * FROM BOARD ORDER BY BID DESC;
selectAll_TITLE = SELECT * FROM BOARD WHERE TITLE LIKE '%%' ORDER BY BID DESC;
%%사이의 "">>> 아무것도없는 것
이 값을 다 갖고있어서용
public List<BoardVO> selectAll(BoardVO bVO) {
System.out.println("BoardDAO2 로그 selectAll() 메서드");
Object[] args= { bVO.getSearchContent() };
if(bVO.getSearchCondition().equals("TITLE")) {
return jdbcTemplate.query(selectAll_TITLE, args , new BoardRowMapper());
}
else { // else if(bVO.getSearchCondition().equals("WRITER"))
return jdbcTemplate.query(selectAll_WRITER, args , new BoardRowMapper());
}
}