이전에 작업한 방법의 문제는 필요할 때마다 연동해서 작업하는 경우 연결에 시간이 많이 걸린다는 문제가 있다.
이를 위해 웹 어플리케이션이 실행됨과 함께 연동할 데이터베이스와의 연결을 미리 설정하여 필요에 따라 연결해 놓은 상태를 이용해 빠르게 DB와 연동하여 작업하는 방법이 있다. 이 방법을 '커넥션풀' 이라한다.
아래 그림을 보며 커넥션풀의 동작 과정을 보며 이해해보자.
구현을 위해서는 Java SE에서 제공하는 javax.sql.DataSource 클래스가 필요하다. 그리고 웹 어플리케이션 실행 시 Tomcat이 만들어 놓은 커넥션풀 객체제 접근할 때 JNDI를 사용할 것이다.
JNDI란 필요한 자원을 key/value 쌍으로 저장 후, 필요할 떄 키를 이용해 값을 얻는 방법이다.
Tomcat 컨테이너가 커넥션풀 객체를 생성하면 이 객체에 대한 JNDI key를 미리 설정하고 웹과 DB과 연동 작업을 할 때 이 JNDI key로 접근하여 작업한다.
DataSource 설정
아래 그림과 같이 설정한다.
Tomcat-jdbc...jar은 톰캣 폴더의 lib/ 의 경로에 존재한다. Program Files\Tomcat9.0\lib
그리고 톰캣의 context.xml을 아래와 같이 추가한다.
<Resource> 태그를 통해 톰캣 실행 시 연결할 데이터베이스를 설정할 수 있다.
usename과 password는 DB 설정할때의 이름과 비밀번호이다.
위의 사진에서 driverclassname, url, username, password 4가지가 데이터 베이스를 연결하는데 필요한 기본 설정값이며 이 속성을 이용해 DataSource에 접근한다.
회원 정보 조회하기 및 추가하기
조회는 이전시간에 했으니 이전에 사용한 코드를 사용하면 된다. 그 중, 조회에는 MemberDao.java 클래스를 수정하여 커넥션풀을 이용해 DB와 연동한다.
새로운 패키지를 생성하여 이전에 사용한 3개의 클래스를 복사하고 servlet 클래스의 매핑이름을 자유롭게 변경한다. 그리고 수정된 코드는 아래와 같다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
package sec02.ex02;
import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
public class MemberDAO {
private Connection con;
private PreparedStatement pstmt;
private DataSource dataFactory;
public MemberDAO() {
try {
Context ctx = new InitialContext();
//JNDI에 접급하기 위한 기본 경로 지정, 톰캣 context.xml에 설정한 name값인 jdbc/oracle을 이용해
//톰캣이 미리 연결한 DataSource를 받아온다.
} catch (Exception e) {
e.printStackTrace();
}
}
public List<MemberVO> listMembers() {
List<MemberVO> list = new ArrayList<MemberVO>();
try {
// connDB();
con = dataFactory.getConnection();
String query = "select * from t_member ";
System.out.println("prepareStatememt: " + query);
pstmt = con.prepareStatement(query);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
String id = rs.getString("id");
String pwd = rs.getString("pwd");
String name = rs.getString("name");
String email = rs.getString("email");
Date joinDate = rs.getDate("joinDate");
//조회한 레코드의 각 컬럼 값을 받아 옴
MemberVO vo = new MemberVO();
vo.setName(name);
vo.setEmail(email);
vo.setJoinDate(joinDate); //각 컬럼 값을 다시 MemberVO객체의 속성에 설정
list.add(vo); //설정된 MemberVO객체를 다시 ArrayList에 저장
}
} catch (Exception e) {
e.printStackTrace();
}
return list; //조회한 레코드의 개수만큼 MemberVo 객체를 저장한 ArrayList를 반환
}
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
|
이제 변경한 이름으로 새로 접속하면 이전시간과 동일한 조회결과를 얻을 수 있다. 커넥션풀을 이용해 DB와 연동하여 조회하였다.
이번에는 회원을 등록하는 과정이다.
회원가입 Form이 필요하기에 새로운 html파일을 작성한다. html파일은 webcontent에 생성한다.
Form.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 가입창</title>
<script type="text/javascript">
function fn_sendMember(){
var frmMember=document.frmMember;
var name=frmMember.name.value;
if(id.length==0 ||id==""){
alert("아이디는 필수입니다.");
}else if(pwd.length==0 ||pwd==""){
alert("비밀번호는 필수입니다.");
}
else if(name.length==0 ||name==""){
alert("이름은 필수입니다.");
}else if(email.length==0 ||email==""){
alert("이메일은 필수입니다.");
}else{
//전송 방법은 post이고 매핑이름은 Member3, 그리고 서블릿으로 전송한다.
}
}
</script>
</head>
<body>
<form name="frmMember">
<table>
<th>회원 가입</th>
<tr>
<td>ID</td>
<td><input type="text" name="id"></td>
</tr>
<tr>
<td>Password</td>
<td><input type="password" name="pwd"></td>
</tr>
<tr>
<td>이름</td>
<td><input type="text" name="name"></td>
</tr>
<tr>
<td>이메일</td>
<td><input type="text" name="email"></td>
</tr>
<!-- 위의 input태그는 서블릿으로 데이터를 전송한다. -->
</table>
<input type="button" value="가입하기" onclick="fn_sendMember()">
<input type="reset" value="다시입력">
<input type="hidden" name="command" value="addMember" />
<!-- hidden 태그를 사용하여 서블릿에게 회원 등록임을 알림 -->
</form>
</body>
</html>
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
|
html파일을 작성하여 회원 가입 양식을 만들고 이것은 servlet에 전송하는 역할을 한다.
이제 전송받은 servlet 클래스를 수정해야한다. 먼저 html이 'command' 를 전송했기에 이 값이 addMember이면 전송된 회원 정보를 받아온다. 회원 정보를 MemberVO 객체에 설정한 후 MemberDAO의 메서드로 전달해 SQL문을 이용하여 데이터를 DB에 추가한다.
MemberServlet.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
package sec02.ex02;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
/**
* Servlet implementation class MemberServlet
*/
@WebServlet("/Member3")
public class MemberServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doHandle(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doHandle(request, response);
}
private void doHandle(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
MemberDAO dao=new MemberDAO();
PrintWriter out=response.getWriter();
String command=request.getParameter("command");
//command값을 받음
if(command!= null && command.equals("addMember")){
//회원 가입창에서 전송된 command가 addMember이면 전송값을 받음 -> Form.html을 확인
String _id=request.getParameter("id");
String _pwd=request.getParameter("pwd");
String _name=request.getParameter("name");
String _email=request.getParameter("email");
MemberVO vo=new MemberVO();
vo.setName(_name);
vo.setEmail(_email);
dao.addMember(vo);
//회원 가입창에서 전송된 값들을 얻어 MemberVO객체제 저장한 후 SQL문을 이용해 전달
}else if(command!= null && command.equals("delMember")) {
String id = request.getParameter("id");
dao.delMember(id);
}
List list=dao.listMembers();
out.print("<html><body>");
out.print("<table border=1><tr align='center' bgcolor='lightgreen'>");
out.print("<td>아이디</td><td>비밀번호</td><td>이름</td><td>이메일</td><td>가입일</td><td >삭제</td></tr>");
MemberVO memberVO=(MemberVO) list.get(i);
String name = memberVO.getName();
String email =memberVO.getEmail();
Date joinDate = memberVO.getJoinDate();
out.print("<tr><td>"+id+"</td><td>"
+pwd+"</td><td>"
+name+"</td><td>"
+email+"</td><td>"
+joinDate+"</td><td>"
+"<a href='/JSP_DB/member3?command=delMember&id="+id+"'>삭제 </a></td></tr>");
}
out.print("</table></body></html>");
//클릭하면 다시 회원 가입창으로 이동
}
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
|
그리고 MemberDAO 클래스에 아래 내용을 추가한다. 이전의 코드에서 아래 내용만 추가한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
public void addMember(MemberVO memberVO) {
try {
con = dataFactory.getConnection(); //DataSource를 이용해 데이터 베이스와 연결
String name = memberVO.getName();
String email = memberVO.getEmail();
//테이블에 저장할 회원 정보를 받음
String query = "insert into t_member";
query += " (id,pwd,name,email)";
query += " values(?,?,?,?)";
//insert문을 문자열로 만듬
System.out.println("prepareStatememt: " + query);
pstmt = con.prepareStatement(query);
pstmt.setString(1, id);
pstmt.setString(2, pwd);
pstmt.setString(3, name);
pstmt.setString(4, email);
//insert문의 각 ?에 순서대로 회원정보를 세팅
pstmt.executeUpdate(); //회원 정보를 테이블에 추가
} catch (Exception e) {
e.printStackTrace();
}
/*PrepareStatement에서 insert문은 회원 정보를 사용하기 위해 ?를 사용 이것은
* id, pwd, name, age 순으로 대응하며 대응값을 저장하기 위해 setter()메서드 사용
* insert,delete,update문은 executeUpdate() 메서드를 호출함 */
}
public void delMember(String id) {
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
|
결과는 아래와 같다. Form.html을 통해 회원 정보를 입력하고 가입하기를 클릭하면 회원 정보가 추가됨을 볼 수 있다.
회원 정보 삭제하기
회원 정보를 추가했으면 이제 그 정보를 삭제해보자
우리는 이제 MemberServlet 클래스와 DAO클래스를 수정해야 함을 알 수있다. 그 클래스들을 수정할 것이다. 그런데 이미 위의 sevlet클래스 코드 에는 삭제하는 코드도 지금 같이 포함되어 있다. (50, 66번 라인)
else if(command!= null && command.equals("delMember")) {
String id = request.getParameter("id");
dao.delMember(id);
}
....
out.print("<tr><td>"+id+"</td><td>"
+pwd+"</td><td>"
+name+"</td><td>"
+email+"</td><td>"
+joinDate+"</td><td>"
+"<a href='/pro07/member3?command=delMember&id="+id+"'>삭제 </a></td></tr>");
위 코드들이 포함되어 있기 때문에 위 결과에 '삭제' 문구를 확인할 수 있을 것이다. 그래서 servlet코드에는 수정할 내용이 없다. 위 코드를 설명하면 command값이 delmember인 경우 ID를 가져와 SQL문으로 전달하여 삭제를 진행한다.
이제 DAO클래스를 수정해보자. 위의 DAO클래스 코드를 보면 delMember()가 비워져있다. 여기를 수정해서 DB의 내용을 삭제해보자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public void delMember(String id) {
try {
Connection con = dataFactory.getConnection();
String query = "delete from t_member" + "where id = ?";
//delete문을 문자열로 만듬
System.out.println("prepareStatement: "+query);
pstmt = con.prepareStatement(query);
pstmt.setString(1, id);//첫번째 '?'에 전달된 ID를 인자로 넣음
pstmt.execute(); // delete문을 실행하여 해당 ID의 정보 삭제
}catch(Exception e) {
e.printStackTrace();
}
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
|
이제 /Member3의 DB테이블에 '삭제'버튼을 누르면 해당 ID가 삭제되는것을 볼 수 있다.
URL이 <a>태그의 내용으로 바뀌면서 내용이 삭제되고 남은 DB테이블을 확인할 수 있다.
Refernce
자바 웹을 다루는 기술<길벗>
'Servlet JSP MVC Spring' 카테고리의 다른 글
[Servlet] 포워드(dispatch), 바인딩 (0) | 2020.03.03 |
---|---|
[MVC] MVC 모델, 테이블 조회 및 생성 (0) | 2020.03.03 |
[Servlet] 서블릿과 데이터베이스 연동 조회: PrepareStatement (0) | 2020.02.21 |
[Servlet] 웹 브라우저에서 서블릿 전송 및 예제들 (0) | 2020.02.12 |
[Servlet] 서블릿에서의 요청 얻기와 응답 (0) | 2020.02.08 |