주제
오라클 db를 자바 프로젝트에 연결하기 위해 JDBC를 세팅한다.
JDBC의 문제점을 파악하고 대안으로서 JDBCTemlate을 사용한다.
Database 세팅
jdbc를 사용하기 위해서 오라클 db 설치 및 계정 세팅, sql developer 세팅을 하였다.
https://chartist1206.tistory.com/141
SQL 기본(SQL developer 사용하기)
테이블테이블이란 데이터베이스의 구조를 정의하는 방식을 의미한다. sql에서 테이블은 열과 행으로 이뤄진 표를 생각하면 된다. 각 열은 하위 데이터 종류를 나타내고 행은 각 열의 데이터를
chartist1206.tistory.com
사용할 프로젝트에서 오라클 db에 유저 정보를 저장해볼 것이므로 user 테이블을 다음 같이 생성하였다.
CREATE TABLE users (
id VARCHAR2(10) CONSTRAINT memid_pk PRIMARY KEY,
password VARCHAR2(10),
username VARCHAR2(15)
);
JDBC 세팅
pom.xml - 의존성 세팅
먼저 pom.xml 파일에 오라클 db용 JDBC를 추가해준다.
참고. 왜 dependency 태그로 의존성을 추가하지 않는걸까.
스프링 프로젝트에서 maven으로 의존성을 관리할 때는 기본적으로 denpendcy 태그를 이용하지만 Oracle db는 Oracle의 라이센스 정책 때문에 직접적으로 Maven Central Repository에 올려져 있지 않다. 따라서 repositories> 태그를 사용하여 Oracle JDBC 드라이버가 있는 외부 저장소를 등록한다.
그런 다음, dependency 태그로 해당 저장소에서 Oracle JDBC 드라이버를 의존성으로 추가한다.
<!-- 저장소 명시 -->
<repositories>
<repository>
<id>oracle</id>
<name>ORACLE JDBC Repository</name>
<url>http://maven.jahia.org/maven2</url>
</repository>
</repositories>
<dependencies>
<!-- 다른 의존성 추가 -->
<!-- jdbc 드라이버 의존성-->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>12.1.0.2</version>
</dependency>
</dependencies>
jdbc 드라이버 로딩 및 쿼리
dao에서 드라이버를 로딩하고 쿼리문을 다음같이 작성한다.
@Repository
public class userDao {
public Map<String, User> DB;
private String driver = "oracle.jdbc.driver.OracleDriver";
private String url = "jdbc:oracle:thin:@localhost:1521:xe";
private String userId = "c##taey";
private String userpw = "sa1234";
private Connection conn = null;
private PreparedStatement pstmt = null;
private ResultSet rs = null;
public userDao() {
}
public boolean insertDao(User user) {
int result = 0;
try {
Class.forName(driver);
conn = DriverManager.getConnection(url, userId, userpw);
String sql = "INSERT INTO USERS(id, password, username) VALUES (?,?,?)";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, user.getId());
pstmt.setString(2, user.getPassword());
pstmt.setString(3, user.getUsername());
result = pstmt.executeUpdate();
System.out.println("결과: "+result);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
return false;
} finally {
try {
if (pstmt != null)
pstmt.close();
if (conn != null)
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
}
return true;
}
}
이 방식의 문제
쿼리를 위해서 매 메소드 마다 보일러 플레이트(드라이버 로딩, 연결 생성, 스테이트먼트 생성, 사용 후 자원 해제) 등을 반복적으로 해야 한다. 이런 반복 작성을 해결해주는 것이 바로 jdbcTemplate 이다.
jdbcTemplate
jdbc의 역할은 다음과 같다.
- SQL 쿼리 실행: SELECT, INSERT, UPDATE, DELETE 등 다양한 SQL 작업을 단순화
- 자원 관리 및 단순화: JDBC 연결, 문서, 결과 집합 등의 자원을 자동으로 관리, 자원 누수 방지
- 예외 처리: Spring의 DataAccessException 계층을 통해 표준화된 예외 처리를 제공
- 결과 매핑: 쿼리 결과를 다양한 형태로 매핑(exL 단일 값, 객체, 객체 목록)
방법
DataSource 설정
dataSource는 jbbc template 세팅을 위해 데이터 베이스 연결 정보 (url, 아이디, 비밀번호) 를 저장 및 관리하는 클래스이다. 이는 두가지 클래스 중 하나를 선택하여 사용한다.
- 스프링 | org.springframework.jdbc.datasource.DriverManagerDataSource
- c3p0 | com.mchange.v2.c3p0. DriverManagerDataSource
pom.xml 에서 c3p0를 세팅
<repositories>
<repository>
<id>oracle</id>
<name>ORACLE JDBC Repository</name>
<url>http://maven.jahia.org/maven2</url>
</repository>
</repositories>
<dependencies>
<!-- DB -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>12.1.0.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<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>
</dependencies>
class에서 사용 예시1
생성자에서 dataSource와 JdbcTemplate를 세팅하면 이후 메소드에서는 별도의 세팅없이 바로 사용가능하다.
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import com.bs.user.service.entity.User;
import com.mchange.v2.c3p0.DriverManagerDataSource;
@Repository
public class userDao {
private String driver = "oracle.jdbc.driver.OracleDriver";
private String url = "jdbc:oracle:thin:@localhost:1521:xe";
private String userId = "c##taey";
private String userpw = "sa1234";
private JdbcTemplate template;
private DriverManagerDataSource dataSource;
public userDao() {
dataSource = new DriverManagerDataSource();
dataSource.setDriverClass(driver);
dataSource.setJdbcUrl(url);
dataSource.setUser(userId);
dataSource.setPassword(userpw);
template = new JdbcTemplate();
template.setDataSource(dataSource);
}
public boolean insertDao(User user) {
int result = 0;
final String sql = "INSERT INTO USERS (id,password,username) VALUES (?,?,?)";
result = template.update(sql, user.getId(), user.getPassword(), user.getUsername());
System.out.println("result: " + result);
return true;
}
}
class에서 사용 예시2
select처럼 결과를 조회하는 경우, 특정한 형식으로 매핑 가능하다.
template.query에서 사용된 기능을 살펴보면 다음과 같다.
- PreparedStatementSetter | 인터페이스의 구현물. 파라미터 값 설정
- RowMapper | 인터페이스의 구현물. ResultSet의 각 행을 순회 및 참조하여 매핑한다.
public User selectDao(String id, String password) {
List<User> users = null;
final String sql ="SELECT * FROM users WHERE id = ? AND password = ?";
users = template.query(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement pstmt) throws SQLException {
// TODO Auto-generated method stub
pstmt.setString(1, id);
pstmt.setString(2, password);
}
}, new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
// TODO Auto-generated method stub
User user = new User();
user.setId(rs.getString("id"));
user.setPassword(rs.getString("password"));
return user;
}
});
System.out.println(users.get(0));
if(users.isEmpty()) return null;
return users.get(0);
}
Connection pool
커넥션 풀이란, 사전에 커넥션을 미리 만들어 놓고 유저의 요청 시 빌려 사용하는 것이다. 이는 유저의 요청 시점에 만드는 것에 비해서 요청이 많을 시에 서버 부하를 막을 수 있다.
세팅 방법1: new 연산자
public userDao() {
dataSource =new ComboPooledDataSource();
try {
dataSource.setDriverClass(driver);
dataSource.setJdbcUrl(url);
dataSource.setUser(userId);
dataSource.setPassword(userpw);
// 커넥션 풀 세팅
dataSource.setMinPoolSize(5);
dataSource.setAcquireIncrement(5);
dataSource.setMaxPoolSize(20);
dataSource.setMaxStatements(5);
} catch (PropertyVetoException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
세팅은 순서대로, 최소 커넥션 풀 개수, 한번에 생성되는 커넥션 풀 개수, 최대 커넥션 풀 개수, 캐싱하는 statment 객체 수를 의미한다.
세팅 방법2: 스프링 설정 파일.xml
xml로 세팅하고 autowired로 가져오면 된다.
<beans:bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<beans:property name="driverClass" value="oracle.jdbc.driver.OracleDriver" />
<beans:property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:xe" />
<beans:property name="user" value="$계정 아이디" />
<beans:property name="password" value="$ 계정 비밀번호" />
<beans:property name="maxPoolSize" value="200" />
<beans:property name="checkoutTimeout" value="60000" />
<beans:property name="maxIdleTime" value="1800" />
<beans:property name="idleConnectionTestPeriod" value="600" />
</beans:bean
세팅 방법3: 자바 configure 어노테이션 기반 세팅
사용할 때는 autowired를 사용
package com.bs.user.config;
import java.beans.PropertyVetoException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.mchange.v2.c3p0.ComboPooledDataSource;
@Configuration
public class DBconfig {
@Bean
public ComboPooledDataSource dataSource() throws PropertyVetoException {
ComboPooledDataSource dataSource =new ComboPooledDataSource();
dataSource.setDriverClass("oracle.jdbc.driver.OracleDriver");
dataSource.setJdbcUrl("jdbc:oracle:thin:@localhost:1521:xe");
dataSource.setUser("유저 아이디");
dataSource.setPassword("비밀번호");
dataSource.setMaxPoolSize(200);
dataSource.setCheckoutTimeout(60000);
dataSource.setMaxIdleTime(1800);
dataSource.setIdleConnectionTestPeriod(600);
return dataSource;
}
}
@Autowired
public userDao(ComboPooledDataSource dataSource) {
this.template =new JdbcTemplate(dataSource);
}
'java > spring' 카테고리의 다른 글
[spring] 쿠키, 세션, 리다이렉트, 인터셉트 (0) | 2024.06.09 |
---|---|
[spring] 스프링 mvc웹 서비스 만들기 (sts없이 수동 설정) (0) | 2024.06.09 |
[spring] 웹 프로그래밍 설계 모델 (0) | 2024.06.09 |
[spring] 어노테이션을 이용한 스프링 설정 (0) | 2024.06.09 |
[spring] 스프링 컨테이너의 생명주기 (0) | 2024.06.05 |