학습하며 정리한 내용을 올리는 것이니, 참고용으로만 봐 주시길 바랍니다.
자바 스프링 프레임워크(renew ver.) - 신입 프로그래머를 위한 강좌
데이터베이스
: (시스템계정) system / root
: sqlplus
: create user root idientified by root;
: grant connect, resource to root;
: exit
: show user
: drop user root cascade; (system 계정에서 실행)
CREATE TABLE member (
memId VARCHAR2(10) CONSTRAINT memId_pk PRIMARY KEY,
memPw VARCHAR2(10),
memMail VARCHAR2(15),
memPurcNum NUMBER(3) DEFAULT 0 CONSTRAINT memPurNum_ck CHECK (memPurcNum < 3)
);
INSERT INTO member (memId, memPw, memMail) values ('b', 'bb', 'bbb@gamil.com');
SELECT * FROM member;
DELETE FROM member WHERE memId = 'b';
DROP TABLE member;
commit;
JDBC
: 드라이버 로딩 -> DB 연결 -> SQL 작성 및 전송 -> 자원 해제
// MemberDao.java
private String driver = "oracle.jdbc.driver.OracleDriver";
private String url = "jdbc:oracle:thin:@localhost:1521:xe";
private String userid = "root";
private String userpw = "root";
private Connection conn = null;
private PreparedStatement pstmt = null;
private ResultSet rs = null;
public int memberInsert(Member member) {
int result = 0;
try {
// Driver 로딩
Class.forName(driver);
// DB 연결
conn = DriverManager.getConnection(url, userid, userpw);
// Query 전송
String sql = "INSERT INTO member (memId, memPw, memMail) values (?, ?, ?)";
pstmt = conn.preparedStatement(sql);
pstmt.setString(1, member.getMemId());
pstmt.setString(2, member.getMemPw());
pstmt.setString(3, member.getMemMail());
result = pstmt.executeUpdate();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally { // 자원 해제
try {
if (pstmt != null) pstmt.close();
if (conn != null) conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return result;
}
public Member memberSelect(Member member) {
Member mem = null;
try {
// Driver 로딩
Class.forName(driver);
// DB 연결
conn = DriverManager.getConnection(url, userid, userpw);
// Query 전송
String sql = "SELECT * FROM member WHERE memId = ? AND memPw = ?";
pstmt = conn.preparedStatement(sql);
pstmt.setString(1, member.getMemId());
pstmt.setString(2, member.getMemPw());
rs = pstmt.executeUpdate();
while (rs.netx()) {
String memId = rs.getString("memid);
String memPw = rs.getString("mempw);
...
mem = new Member();
mem.setMemId(memId);
...
}
} catch (Exception e) {
...
} finally { // 자원해제
try {
if (rs != null) rs.close();
if (pstmt != null) pstmt.close();
if (conn != null) conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return mem;
}
: 매번 Driver 로딩, DB 연결, 자원 해제를 해 주어야 한다는 단점 존재한다. 이를 간편하게 하기위해 JdbcTemplate을 사용한다.
JDBC Template 사용
: JDBC 사용시 Driver 로딩, DB 연결, 자원 해제를 JDBC Template에서 자동으로 해 주고, 각각의 함수에서는 SQL Query문만 작성해서 실행해주면 된다.
// pom.xml
<!-- DB -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>12.1.0.2</version>
</dependency>
<dependency> // 스프링 JDBC 추가
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<dependency> // 추가
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5</version>
</dependency>
// MemberDao.java
public class MemberDao implements IMemberDao {
private DriverManagerDataSource dataSource;
private JdbcTemplate template;
/*
private Connection conn = null;
private PreparedStatement pstmt = null;
private ResultSet rs = null;
*/
public MemberDao() {
/* c3p0 의 DriverManagerDataSource 사용 */
dataSource = new DriverManagerDataSource();
dataSource.setDriverClass(dirver); // 드라이버 로딩
dataSource.setJdbcUrl(url); // DB 연결
dataSource.setUser(userid);
dataSource.setPassowrd(iserpw);
/* spring의 DriverManagerDataSource 사용
dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(dirver);
dataSource.setUrl(url);
dataSource.setUsername(userid);
dataSource.setPassowrd(iserpw);
*/
template = new JdbcTemplate(); // JDBC Template 사용
template.setDataSource(dataSource);
}
}
public int memberInsert(Member member) {
int result = 0;
String sql = "INSET INTO member (memId, memPw, memMail) values (?, ?, ?)";
// 1st 방법
result = template.update(sql, member.getMemId(), ...);
/*
// 2nd 방법 (이 때에는, sql문이 외부에서 사용될 수 있으므로 final로 선언해야한다 > final String sql)
result = template.update(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, member.getMemId());
...
return pstmt;
}
});
// 3rd 방법 (이 때에는, sql문이 외부에서 사용될 수 있으므로 final로 선언해야한다 > final String sql)
result = template.update(sql, new PreparedStatementSetter()) {
@Override
public void setValues(PreparedStatement pstmt) throws SQLException {
pstmt.setString(1, member.getMemId());
...
}
});
*/
return result;
}
public Member memberSelect(Member memeber) {
List<Member> members = null;
String sql = "SELECT * FROM member WHERE memId = ? AND memPw = ?";
// 1st
members = template.query(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement pstmt) throws SQLException {
pstmt.setString(1, member.getMemId());
pstmt.setString(2, member.getMemPw());
}
}, new RowMapper<Member>() {
@Override
public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
Member mem = new Member();
mem.setMemId(rs.getString("memId"));
...
return mem;
}
});
if (member.isEmpty()) return null;
/*
// 2nd
members = template.query(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection conn)
throws SQLException {
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, member.getMemId());
pstmt.setString(2, member.getMemPw());
return pstmt;
}
}, new RowMapper<Member>() {
@Override
public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
Member mem = new Member();
mem.setMemId(rs.getString("memId"));
mem.setMemPw(rs.getString("memPw"));
mem.setMemMail(rs.getString("memMail"));
mem.setMemPurcNum(rs.getInt("memPurcNum"));
return mem;
}
});
// 3rd
members = template.query(sql, new RowMapper<Member>() {
@Override
public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
Member mem = new Member();
mem.setMemId(rs.getString("memId"));
mem.setMemPw(rs.getString("memPw"));
mem.setMemMail(rs.getString("memMail"));
mem.setMemPurcNum(rs.getInt("memPurcNum"));
return mem;
}
}, member.getMemId(), member.getMemPw());
// 4th
members = template.query(sql, new Object[]{member.getMemId(), member.getMemPw()}, new RowMapper<Member>() {
@Override
public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
Member mem = new Member();
mem.setMemId(rs.getString("memId"));
mem.setMemPw(rs.getString("memPw"));
mem.setMemMail(rs.getString("memMail"));
mem.setMemPurcNum(rs.getInt("memPurcNum"));
return mem;
}
});
*/
return members.get(0);
}
커넥션풀
: 다수의 사용자가 DB 접속 시 드라이버를 로딩하고, 커넥션을 만드는 작업은 메모리를 상당히 많이 차지하고 이는 서버에 상당한 부하를 줄 수 있다. 따라서 사용자 요청이 들어오지 않아도 미리 커넥션을 만들어 놓고 요청 있을 때 미리 만들어 놓은 것을 이용하는 방법.
: c3p0모듈의 ComboPooledDataSource를 사용
: 사용방법은 이전(public MemberDao() { ... }
)과 동일. 하지만,
dataSource = new ComboPooledDataSource();
try {
dataSource.setDriverClass(driver);
...
} catch (PropertyVetoException e) {
e.printStackTrace();
}
와 같이 try-catch 문을 사용해 주어야 한다.