JSP 17강 - 데이터베이스 프로그래밍(JDBC, DBCP)
데이터베이스 프로그래밍 순서
- 연결 : 데이터베이스를 사용하기 위해 먼저 데이터베이스에 연결해야 함
- 데이터베이터에 데이터를 삽입/변경/삭제하는 등의 작업을 수행
- 2~3번 과정을 작업을 완료할 때까지 반복해서 수행
- 원하는 작업 수행 후 연결 종료
DB는 개념이다!
<조건>
1. 공유
2. 통행
3. 저장
4. 운영
JDBC(Java Database Connectivity)
-
자바에서 DB 프로그래밍을 하기 위해 사용되는 API
-
JDBC API 사용 어플리케이션의 기본 구성
-
자바는 DBMS 종류에 상관없이 하나의 JDBC API를 사용해서 데이터베이스 작업을 처리할 수 있다.
JDBC 드라이버
-
DBMS와 통신을 담당하는 자바 클래스
-
DBMS별로 알맞은 JDBC 드라이버 필요
-> 보통 jar파일로 제공 -
JDBC 드라이버 로딩
** 로딩? 하드디스크로부터 메모리에 올리는 것
로딩코드
Class.forName("JDBC드라이버 클래스의 완전한 이름");
주요 DBMS의 JDBC드라이버
- 오라클 : oracle.jdbc.driver.OracleDriver
- MySQL : com.mysql.jdbc.Driver
- MS SQL 서버 : com.microsoft.sqlserver.jdbc.SQLServerDriver
JDBC URL
- DBMS와의 연결을 위한 식별 값
- JDBC 드라이버에 따라 형식 다름
- 일반적인 구성
-> jdbc:[DBMS]:[데이터베이스 식별자] - 주요 DBMS의 JDBC URL 구성
Oracle: jdbc:oracle:thin:@HOST:PORT:SID
MySQL : jdbc:mysql://HOST[:PORT]/DBNAME[?param=value& param1...]
MS SQL : jdbc:sqlserver://HOST[:PORT];databaseName=DB
-> 오라클 드라이버는 thin 드라이버와 OCI 드라이버가 있는데, thin 드라이버는 자바 언어로만 구현된 JDBC 드라이버로서 JDK만 설치되어 있으면 어디서는 사용할 수 있다.
JDBC 프로그래밍 코딩 순서
-
JDBC 드라이버 로딩
Class.forName("oracle.jdbc.driver.OracleDriver");
-> 외우는 방법 : 오라클 JDBC 드라이버는 오라클꺼다~ -
데이터베이스 커넥션(연결 객체) 생성
-> 순서 : 1)jdbcDriver 2)계정아이디 3)비밀번호String jdbcDriver = "jdbc:oracle:thin:@localhost:1521:xe";
String dbUser = "사용자계정명";
String dbPass = "비밀번호";
-> 커넥션 객체에 이 세개를 담는다.
conn = DriverManager.getConnection(jdbcDriver,dbUser,dbPass);
-
Statement 생성
stmt = conn.createStatement();
-
쿼리 실행
rs = stmt.excuteQuery(query);
-
쿼리 실행 결과 출력
-> while(rs.next()) 사용 -
사용한 Statement객체 종료
-> 중요! 닫지 않으면 메모리가 꽉차서 Connection 객체와 연결이 끊어진다.if(rs!=null)try{rs.close();}catch(SQLException ex){} if(stmt!=null)try{stmt.close();}catch(SQLException ex){}
-
커넥션 객체 종료
if(conn!=null)try{conn.close();}catch(SQLException ex){}
viewMemberList.jsp
<%@page import="java.sql.SQLException"%>
<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.Statement"%>
<%@page import="java.sql.Connection"%>
<%@page import="java.sql.DriverManager"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<title>회원 목록</title>
</head>
<body>
MEMBER 테이블의 내용<br>
<table width="100%" border="1">
<tr>
<th>이름</th><th>아이디</th><th>이메일</th>
</tr>
<%
//1.JDBC 드라이버 로딩
Class.forName("oracle.jdbc.driver.OracleDriver");
//-->오라클 JDBC 드라이버는 오라클꺼다~~
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try{
//2.데이터베이스 커넥션(연결 객체) 생성
//jdbcDriver? 2)계정아이디? 3)비밀번호?
String jdbcDriver = "jdbc:oracle:thin:@localhost:1521:xe";
String dbUser = "jspexam";
String dbPass = "java";
String query = "SELECT MEMBERID,PASSWORD,NAME,EMAIL FROM MEMBER";
conn = DriverManager.getConnection(jdbcDriver,dbUser,dbPass);
//Connection 객체에 위에서 만든 세개 담기
//3.Statement 생성
stmt = conn.createStatement();
//4.쿼리 실행
rs = stmt.executeQuery(query);
//5.쿼리 실행 결과 출력
while(rs.next()){
out.print("<tr>");
out.print("<td><a href='viewMember_pool.jsp?memberId="+rs.getString("MEMBERID")+"'>"+rs.getString("NAME")+"</td>");
out.print("<td>"+rs.getString("MEMBERID")+"</td>");
out.print("<td>"+rs.getString("EMAIL")+"</td>");
out.print("</tr>");
}
}catch(SQLException ex){
out.print(ex.getMessage());
ex.printStackTrace();
}finally{
//6.사용한 Statement객체 종료 (중요!!! 닫지않으면 메모리 꽉차서 Connection객체와 연결 끊어짐)
if(rs!=null)try{rs.close();}catch(SQLException ex){}
if(stmt!=null)try{stmt.close();}catch(SQLException ex){}
//7.커넥션 객체 종료
if(conn!=null)try{conn.close();}catch(SQLException ex){}
}
%>
</table>
</body>
</html>
updateForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<title>이름 변경 폼</title>
</head>
<body>
<form method="post" action="update.jsp">
<table border="1">
<tr>
<td>아이디</td><td><input type="text" name="memberId" size="10" /></td>
<td>이름</td>
<td><input type="text" name="name" size="10" /></td>
</tr>
<tr>
<td colspan="4"><input type="submit" value="변경" /></td>
</tr>
</table>
</form>
</body>
</html>
Statement 객체를 이용한 쿼리 실행
- Connection객체를 생성한 후에는 Connection 객체로부터 Connection.createStatement() 메서드를 사용하여 Statement를 생성하고 Query를 실행할 수 있다.
- Statement 객체가 제공하는 메서드로 쿼리를 실행한다.
-> insert,update,delete문 실행 시 int excuteUpdate(String query) 메서드 사용
===>실행 결과 변경된 레코드의 개수를 리턴!
-> select문 실행 시 ResultSet executeQuery(String query) 메서드 사용
===> ResultSet을 결과값으로 리턴!
ResultSet에서 값 조회
-
next()메서드로 데이터 조회 여부 확인(커서가 이동됨)
-
데이터 조회를 위한 주요 메서드
-> ResultSet은 현재 커서 위치에 있는 행으로부터 데이터를 읽어오기 위해 get~~()형태의 메서드를 제공한다.
ex) getString(), getInt(),getLong()...
ResultSet에서 데이터 조회하는 코드
- 1개 행 처리(if문 사용)
- 복수 행 처리 시 (whie문 사용)
PreparedStatement를 이용한 처리
- SQL의 틀을 미리 정해놓고, 나중에 값을 지정한다.
stmt = conn.prepareStatement(
"insert into MEMBER (MEMBERID, NAME, EMAIL) values (?, ?, ?)");
pstmt.setString(1, “a001”); // 첫번째 물음표의 값 지정
Pstmt.setString(2, “김은대"); // 두번째 물음표의 값 지정
pstmt.executeUpdate()
PreparedStatement의 사용 이유
- 반복해서 실행되는 동일 쿼리의 속도를 향상시킴
update.jsp
<%@page import="java.sql.DriverManager"%>
<%@page import="java.sql.SQLException"%>
<%@page import="java.sql.Statement"%>
<%@page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
request.setCharacterEncoding("UTF-8");
//파라미터 목록 중 memberId 및 name을 get함
String memberId = request.getParameter("memberId");
String name = request.getParameter("name");
out.print("memberId : "+ memberId + ", name : " + name + "<br>");
//jdbc 드라이버 로딩(메모리에 올림)
Class.forName("oracle.jdbc.driver.OracleDriver");
//커넥션 객체 선언
Connection conn = null;
//Statement 객체 선언
Statement stmt = null;
String query = "UPDATE MEMBER SET NAME = '"+name+"' WHERE MEMBERID = '"+memberId+"'";
int updateCount = 0;
try{
String jdbcDriver = "jdbc:oracle:thin:@localhost:1521:xe";
String dbUser = "jspexam";
String dbPass = "java";
//커넥션 객체 생성
conn = DriverManager.getConnection(jdbcDriver,dbUser,dbPass);
//Statement 객체 생성
stmt = conn.createStatement();
//insert,update,delete --> executeUpdate()
//select --> executeQuery()
updateCount = stmt.executeUpdate(query);
}catch(SQLException ex){
out.print(ex.getMessage());
}finally{
if(stmt!=null)try{stmt.close();}catch(SQLException ex){}
if(conn!=null)try{conn.close();}catch(SQLException ex){}
}
if(updateCount>0){
out.print(memberId + "의 이름을 " + name + "(으)로 변경");
}else{
out.print(memberId + " 아이디가 없음");
}
%>
insertForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<title>MEMBER 테이블에 레코드 입력</title>
</head>
<body>
<form method="post" action="insert.jsp">
<table border="1">
<tr>
<th>아이디</th>
<td><input type="text" name="memberid" size="10"></td>
<th>비밀번호</th>
<td><input type="password" name="password" size="10"></td>
</tr>
<tr>
<th>이름</th>
<td><input type="text" name="name" size="10"></td>
<th>이메일</th>
<td><input type="text" name="email" size="10"></td>
</tr>
<tr>
<td colspan="4"><input type="submit" value="입력" /></td>
</tr>
</table>
</form>
</body>
</html>
insert.jsp
<%@page import="java.sql.PreparedStatement"%>
<%@page import="java.sql.SQLException"%>
<%@page import="java.sql.DriverManager"%>
<%@page import="java.sql.Statement"%>
<%@page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
request.setCharacterEncoding("UTF-8");
String memberid = request.getParameter("memberid");
String password = request.getParameter("password");
String name = request.getParameter("name");
String email = request.getParameter("email");
out.print(memberid + ", " + password + ", " + name + ", " + email);
Class.forName("oracle.jdbc.driver.OracleDriver");
//커넥션 객체 선언
Connection conn = null;
//Statement 객체 선언
PreparedStatement pstmt = null;
String query = "INSERT INTO MEMBER(MEMBERID,PASSWORD,NAME,EMAIL) "
+ " VALUES(?,?,?,?)";
try{
String jdbcDriver = "jdbc:oracle:thin:@localhost:1521:xe";
String dbUser = "jspexam";
String dbPass = "java";
//커넥션 객체 생성
conn = DriverManager.getConnection(jdbcDriver,dbUser,dbPass);
//Statement 객체 생성
pstmt = conn.prepareStatement(query);
pstmt.setString(1, memberid);
pstmt.setString(2, password);
pstmt.setString(3, name);
pstmt.setString(4, email);
//insert,update,delete --> executeUpdate()
//select --> executeQuery()
pstmt.executeUpdate();
}catch(SQLException ex){
out.print(ex.getMessage());
}finally{
if(pstmt!=null)try{pstmt.close();}catch(SQLException ex){}
if(conn!=null)try{conn.close();}catch(SQLException ex){}
}
%>
<!DOCTYPE html>
<html>
<head>
<title>입력</title>
</head>
<body>
MEMBER 테이블에 새로운 레코드를 입력했습니다.
</body>
</html>
- 자바빈 클래스 생성
Mem.java
package dto;
//자바빈 클래스
public class Mem {
private String memberid;
private String password;
private String name;
private String email;
//기본생성자
public Mem() {
super();
}
public String getMemberid() {
return memberid;
}
public void setMemberid(String memberid) {
this.memberid = memberid;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
커넥션 풀
-
데이터베이스와 연결된 커넥션을 미리 만들어서 풀(pool)속에 저장해두고 있다가 필요할 때에 커넥션을 풀에서 가져다 쓰고, 사용이 끝나면 다시 풀에 반환하는 기법
-
특징
-
커넥션을 미리 생성해두기 때문에 사용자가 DB를 사용할 때마다 매번 생성하는 것보다 더 빠른 속도를 보장한다.
-
커넥션의 최대 생성 개수도 제어해주기 때문에 많은 사용자가 몰려도 과부하를 방지할 수 있다.
- 커넥션 풀의 오픈소스에는 대표적으로 DBCP와 C3P0이 있는데 여기선 DBCP를 사용했다. DBCP는 Apache 사이트에서 받을 수 있다.
- 그 외에 DBCP에서 사용한 Pool인 Commons Pool이 필요하다.
- 부가적으로 로그 기록에 사용되는 Commons Logging도 필요하다.
DBCP API를 이용한 커넥션 풀 사용
1. 필요 라이브러리
설치 방법
https://mvnrepository.com/ 에서
commons-dbcp검색
Apache Commons DBCP클릭 - 2.9.0 클릭
jar 클릭해서 다운로드
commons-pool검색
Apache Commons Pool클릭 - 2.9.0
jar 클릭해서 다운로드
commons-logging검색
Apache Commons Logging 클릭 - 1.2
jar 클릭해서 다운로드
다운로드 받은 파일들 복사해서 WEB-INF\lib에 붙여넣기
2.데이터 베이스 세팅
1)계정 생성 및 권한 부여
2)테이블 생성
- DBCP 설정 클래스
DBCPInit.java
package jdbc;
import java.sql.DriverManager;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import org.apache.commons.dbcp2.ConnectionFactory;
import org.apache.commons.dbcp2.DriverManagerConnectionFactory;
import org.apache.commons.dbcp2.PoolableConnection;
import org.apache.commons.dbcp2.PoolableConnectionFactory;
import org.apache.commons.dbcp2.PoolingDriver;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
//서블릿 클래스
public class DBCPInit extends HttpServlet {
@Override
public void init() throws ServletException{
//JDBC Driver를 로딩
loadJDBCDriver();
//커넥션풀을 초기화
initConnectionPool();
}
//JDBC Driver를 로딩
private void loadJDBCDriver() {
try {
//커넥션풀이 내부에서 사용할 JDBC Driver를 로딩함
Class.forName("oracle.jdbc.driver.OracleDriver");
}catch(ClassNotFoundException ex){
throw new RuntimeException("fail to load JDBC Driver", ex);
}
}
//커넥션풀을 초기화
private void initConnectionPool() {
try {
//의국에서 새로운 외과 의사를 생성할 때 필요한 외과가 있어야 함
//커넥션풀에서 새로운 커넥션을 생성할 때 사용할 커넥션 팩토리를 생성
ConnectionFactory connFactory =
new DriverManagerConnectionFactory(
"jdbc:oracle:thin:@localhost:1521:xe"
,"jspexam"
,"java"
);
//DBCP는 커넥션풀에 커넥션을 보관할 때 PoolableConnection을 사용
//이 Class는 내부적으로 실제 Connection을 담고 있음
//커넥션풀을 관리
PoolableConnectionFactory poolableConnFactory =
new PoolableConnectionFactory(connFactory, null);
//커넥션이 유효한지 여부 검사 시 사용할 쿼리
poolableConnFactory.setValidationQuery("select 1");
//커넥션 풀의 설정 정보 생성
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
//유휴 커넥션 검사 주기(1/1000초)
//놀고 있는 커넥션을 풀에서 제거하는 시간 기준 (5분)
poolConfig.setTimeBetweenEvictionRunsMillis(1000L * 60L * 5L);
//풀에 보관중인 커넥션이 유효한지 검사할지 여부
poolConfig.setTestWhileIdle(true);
//커넥션 최소 개수
poolConfig.setMinIdle(4);
//커넥션 최대 개수
poolConfig.setMaxTotal(50);
//커넥션풀의 설정 정보를 생성. 팩토리와 커넥션풀 설정을 파라미터로 받음
GenericObjectPool<PoolableConnection> connectionPool =
new GenericObjectPool<>(poolableConnFactory, poolConfig);
//풀러블커넥션팩토리에도 생성이 된 커넥션 풀을 연결
poolableConnFactory.setPool(connectionPool);
//커넥션풀을 제공하는 JDBC 드라이버를 등록함
Class.forName("org.apache.commons.dbcp2.PoolingDriver");
PoolingDriver driver = (PoolingDriver)DriverManager.getDriver("jdbc:apache:commons:dbcp:");
//커넥션 풀 드라이버에 생성된 커넥션풀을 등록
//jdbc:apache:commons:dbcp:ddit
driver.registerPool("ddit", connectionPool);
}catch(Exception e) {
throw new RuntimeException(e);
}//end try
}//end initConnectionPool();
}
- 커넥션을 제공하는 클래스
ConnectionProvider.java
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
//커넥션을 제공해주는 클래스
public class ConnectionProvider {
public static Connection getConnection() throws SQLException{
return DriverManager.getConnection("jdbc:apache:commons:dbcp:ddit");
}
}
- JDBCUtil 클래스 생성해서 사용한 객체 종료 쉽게하기
JDBCUtil.java
package jdbc;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
//하나의 클래스에 같은 이름의 메소드를 여러번 사용 가능?
//오버로딩
public class JdbcUtil {
public static void close(ResultSet rs) {
if(rs!=null) try {rs.close();}catch(SQLException ex) {}
}
public static void close(Statement stmt) {
if(stmt!=null) try {stmt.close();}catch(SQLException ex) {}
}
public static void close(Connection conn) {
if(conn!=null) try {conn.close();}catch(SQLException ex) {}
}
public static void close(PreparedStatement pstmt) {
if(pstmt!=null) try {pstmt.close();}catch(SQLException ex) {}
}
public static void rollback(Connection conn) {
if(conn!=null) try {conn.close();}catch(SQLException ex) {}
}
}
JSP 서블릿(Servlet)
- 동적 웹 어플리케이션 컴포넌트
- .java 확장자
- 클라이언트의 요청에 동적으로 작동하고, 응답은 html을 이용
- 자바 thread를 이용하여 동작 -> 서버에 부하가 적게 걸리는 장점이 있음
- MVC 패턴에서 controller로 이용됨(JSP는 뷰로 이용됨)
DBCP 이용한 방법으로 list 출력하기
viewMemberUsingPool.jsp
<%@page import="jdbc.ConnectionProvider"%>
<%@page import="jdbc.JdbcUtil"%>
<%@page import="java.sql.SQLException"%>
<%@page import="java.sql.DriverManager"%>
<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.Statement"%>
<%@page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<title>Insert title here</title>
</head>
<body>
MEMBER 테이블의 내용<br>
<table width="100%" border="1">
<tr>
<th>이름</th><th>아이디</th><th>이메일</th>
</tr>
<%
//1.JDBC 드라이버 로딩
Class.forName("oracle.jdbc.driver.OracleDriver");
//-->오라클 JDBC 드라이버는 오라클꺼다~~
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try{
//2.데이터베이스 커넥션(연결 객체) 생성
//1)jdbcDriver? 2)계정아이디? 3)비밀번호?
String jdbcDriver = "jdbc:apache:commons:dbcp:ddit";
String query = "SELECT MEMBERID,PASSWORD,NAME,EMAIL FROM MEMBER";
// conn = DriverManager.getConnection(jdbcDriver); 이제 이거 안씀
conn = ConnectionProvider.getConnection();
//3.Statement 생성
stmt = conn.createStatement();
//4.쿼리 실행
rs = stmt.executeQuery(query);
//5.쿼리 실행 결과 출력
while(rs.next()){
out.print("<tr>");
out.print("<td><a href='viewMember.jsp?memberId="+rs.getString("MEMBERID")+"'>"+rs.getString("NAME")+"</td>");
out.print("<td>"+rs.getString("MEMBERID")+"</td>");
out.print("<td>"+rs.getString("EMAIL")+"</td>");
out.print("</tr>");
}
}catch(SQLException ex){
out.print(ex.getMessage());
ex.printStackTrace();
}finally{
//6.사용한 Statement객체 종료
JdbcUtil.close(rs);
JdbcUtil.close(stmt);
//7.커넥션 객체 종료 -> dbcp이니까 커넥션 객체를 커넥션 풀로 반환
JdbcUtil.close(conn);
}
%>
</table>
</body>
</html>
위 리스트에서 a태그(memberid)클릭 시 상세화면 이동
viewMember.jsp
<%@page import="dto.Mem"%>
<%@page import="jdbc.ConnectionProvider"%>
<%@page import="jdbc.JdbcUtil"%>
<%@page import="java.sql.DriverManager"%>
<%@page import="java.sql.SQLException"%>
<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.Statement"%>
<%@page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String memberId = request.getParameter("memberId");
%>
<!DOCTYPE html>
<html>
<head>
<title>회원 정보</title>
</head>
<body>
<%
//jdbc 드라이버 로딩(메모리에 올림)
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
Mem memVO = new Mem();
String query = "SELECT MEMBERID,PASSWORD,NAME,EMAIL FROM MEMBER "
+ " WHERE MEMBERID = '"+memberId+"'";
try{
// conn = DriverManager.getConnection(
// "jdbc:oracle:thin:@localhost:1521:xe",
// "jspexam",
// "java");
conn = ConnectionProvider.getConnection();
stmt = conn.createStatement();
rs = stmt.executeQuery(query);
if(rs.next()){
memVO.setMemberid(rs.getString("MEMBERID"));
memVO.setName(rs.getString("NAME"));
memVO.setPassword(rs.getString("PASSWORD"));
memVO.setEmail(rs.getString("EMAIL"));
}
out.print("memVO : " + memVO.toString());
}catch(SQLException ex){
out.print(ex.getMessage());
}finally{
//6.사용한 Statement객체 종료
JdbcUtil.close(rs);
JdbcUtil.close(stmt);
//7.커넥션 객체 종료 -> dbcp이니까 커넥션 객체를 커넥션 풀로 반환
JdbcUtil.close(conn);
}
%>
<c:set var="memVO" value="<%=memVO%>" scope="request" />
<!-- scope="request" 면 하나의 객체를 공유해서 쓸수있다 -->
<table border="1">
<tr>
<th>아이디 </th><td>${memVO.memberid}</td>
</tr>
<tr>
<th>비밀번호 </th><td>${memVO.password}</td>
</tr>
<tr>
<th>이름</th><td>${memVO.name}</td>
</tr>
<tr>
<th>이메일</th><td>${memVO.email}</td>
</tr>
</table>
</body>
</html>
Author And Source
이 문제에 관하여(JSP 17강 - 데이터베이스 프로그래밍(JDBC, DBCP)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@hazel_jo/JSP-스프링-17강-데이터베이스-프로그래밍JDBC-DBCP-방명록-만들기1저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)