이전에 했던 프로젝트를 Delete와 getCount를 구현한 후 예외처리와 Spring TDD를 통해 리팩토링 해보겠다.
이전 프로젝트 : https://velog.io/@qowl880/Java-Java%EC%97%90%EC%84%9C-Query%EB%AC%B8-%EB%A6%AC%ED%8C%A9%ED%86%A0%EB%A7%813
public void deleteAll() throws SQLException, ClassNotFoundException { // DB 모든값 삭제
Connection conn = null;
PreparedStatement ps = null;
try { // 예외처리
conn = connectionMaker.makeConnection();
ps = conn.prepareStatement("delete from user ");
ps.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
}finally { // error 발생해도 실행함
if(ps != null){
try {
ps.close();
} catch (SQLException e) {
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
}
}
}
}
public int getCount() throws SQLException, ClassNotFoundException { // user테이블의 레코드 개수를 구하기
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = connectionMaker.makeConnection();
ps = conn.prepareStatement("select count(*) from users ");
rs = ps.executeQuery();
rs.next();
return rs.getInt(1);
} catch (SQLException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} finally {
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
}
}
if(ps != null){
try {
ps.close();
} catch (SQLException e) {
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
}
}
}
}
Try, Catch, Finally
- Try : 실행할 코드 영역, 예외 발생이 가능한 부분 예외 발생시 catch로
- Catch : 예외 처리 코드 영역
- finally : 예외와 상관없이 마지막에 필수적으로 실행되는 코드 영역
이를 토대로 모든 동작하는 메서드에 try-catch문을 통해 예외처리를 해보겠다.
DAO 클래스
public class UserDao {
private ConnectionMaker connectionMaker; // interface의 makeConnection()를 가져옴
public UserDao(){ // 생성자를 통해 AWS DB의 makeConnection()을 오버라이딩하여 사용
this.connectionMaker = new AWSConnectionMaker();
}
public UserDao(ConnectionMaker connectionMaker){
this.connectionMaker = connectionMaker;
}
public void deleteAll() throws SQLException, ClassNotFoundException { // DB 모든값 삭제
Connection conn = null;
PreparedStatement ps = null;
try { // 예외처리
conn = connectionMaker.makeConnection();
ps = conn.prepareStatement("delete from user ");
ps.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
}finally { // error 발생해도 실행함
if(ps != null){
try {
ps.close();
} catch (SQLException e) {
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
}
}
}
}
public int getCount() throws SQLException, ClassNotFoundException { // user테이블의 레코드 개수를 구하기
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = connectionMaker.makeConnection();
ps = conn.prepareStatement("select count(*) from users ");
rs = ps.executeQuery();
rs.next();
return rs.getInt(1);
} catch (SQLException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} finally {
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
}
}
if(ps != null){
try {
ps.close();
} catch (SQLException e) {
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
}
}
}
}
public void add(User user) throws ClassNotFoundException, SQLException {
// db 연결(호스트,이름,비밀번호)
Connection conn = null; // 설정들을 모아둔 메서드 호출
PreparedStatement ps = null;
try {
conn = connectionMaker.makeConnection();
ps = conn.prepareStatement("INSERT INTO users(id,name,password) VALUES(?,?,?)");
ps.setString(1,user.getId()); // mysql 테이블로 값 insert
ps.setString(2,user.getName());
ps.setString(3,user.getPassword());
ps.executeUpdate(); // ctrl + enter 즉, mysql에서 번개모양을 눌러 최신화 한다는 느낌
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
if(ps != null){
try {
ps.close();
} catch (SQLException e) {
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
}
}
System.out.println("데이터가 insert 됬습니다.");
}
}
public User select(String id) throws SQLException, ClassNotFoundException {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null; // 쿼리문을 저장함 insert문과 달리 excuteQuery() 사용
User user = null;
try {
conn = connectionMaker.makeConnection();
ps = conn.prepareStatement("SELECT id,name,password FROM users WHERE id = ?");
ps.setString(1, id); // id는 get(String id)로 받은 id
rs = ps.executeQuery();
// rs에는 쿼리 실행 결과가 담겨져 있다. (select * from users where id = 1;)
rs.next();
// User 생성자를 통해 쿼리문에 id값을 넣어 찾은 id, name,password 값을 저장한다.
return new User(rs.getString("id"), rs.getString("name"), rs.getString("password"));
}
catch (SQLException e) {
throw new RuntimeException(e);
}
finally {
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
}
}
if(ps != null){
try {
ps.close();
} catch (SQLException e) {
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
}
}
}
}
}
Spring Test에 관한 내용은 다음 블로그에 정리가 되어 있으니 참고해주길 바란다.
https://velog.io/@qowl880/test
TDD
@ExtendWith(SpringExtension.class) // spring에서 테스트 하기 위한 설정
@ContextConfiguration(classes = UserDaoFactory.class)
class UserDaoFactoryTest {
// 싱글톤을 위해 Autowired 사용
@Autowired // 새로운 객체를 사용하지 않고 이전에 사용했던 객체의 주소를 그대로 사용한다는 설정
// new 객체 생성을 한번만 사용함(고정값)
ApplicationContext context; // Spring ApplicationContext를 사용하기 위해서는
// @ExtendWith 과 @ContextConfiguration를 추가해줘야 한다.
UserDao userDao;
User user1;
User user2;
User user3;
@BeforeEach
void setUp(){ // 각각의 테스트 시작전 필수로 동작하는 부분
userDao = context.getBean("awsUserDao", UserDao.class);
user1 = new User("1","홍길동","1234");
user2 = new User("2","이순신","4567");
user3 = new User("3","세종","7896");
}
@Test
void addAndSelect() throws ClassNotFoundException, SQLException {
// .deleteAll() 오류 검증
userDao.deleteAll();
Assertions.assertThat(0).isEqualTo(userDao.getCount());
String id = "3";
userDao.add(user3);
Assertions.assertThat(1).isEqualTo(userDao.getCount());
User user = userDao.select(id);
Assertions.assertThat("세종").isEqualTo(user.getName());
// assertEquals("Spring",user.getName());
}
@Test
//.count test만들기
void count() throws SQLException, ClassNotFoundException {
UserDao userDao = context.getBean("awsUserDao", UserDao.class);
//.deleteAll() 오류 검증
userDao.deleteAll();
assertEquals(0, userDao.getCount());
userDao.add(user1);
assertEquals(1, userDao.getCount());
userDao.add(user2);
assertEquals(2, userDao.getCount());
userDao.add(user3);
assertEquals(3, userDao.getCount());
}
}
※ 코드 정리 : https://github.com/Bae-Ji-Won/Spring-Study/tree/main/git/Toby-spring-jdbc/src/main/java/dao/Factory