Spring DI, AOP

13. Spring으로 DB다루기/TDD - 패스트캠퍼스 백엔드 부트캠프 3기

gkss2tpt 2025. 2. 26. 16:22

1. 데이터베이스에 저장하고 읽어오기

  • User 클래스
@ToString
@Getter
@Setter
@EqualsAndHashCode
public class User {
    private String id;
    private String pwd;
    private String name;
    private String email;
    private Date birth;
    private String sns;
    private Date reg_date;
    
    public User(){}

    public User(String id, String pwd, String name, String email, Date birth, String sns, Date reg_date) {
        this.id = id;
        this.pwd = pwd;
        this.name = name;
        this.email = email;
        this.birth = birth;
        this.sns = sns;
        this.reg_date = reg_date;
    }
}
  • DBConnectionTest3 클래스
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"file:src/main/webapp/WEB-INF/root-context.xml"})
public class DBConnectionTest3 {
    @Autowired
    DataSource ds;

    @Test
    public void insertUserTest() throws Exception {
        User user = new User("asdf","1234","abc", "aaa@aaa.com", new Date(), "fb",new Date());
        int rowCnt = insertUser(user);
        assertTrue(rowCnt==1);
    }

    // 사용자 정보를 user_Info 테이블에 저장하는 메서드
    public int insertUser(User user) throws Exception{

        // DB연결
        Connection conn = ds.getConnection();

        //insert into user_info (id, pwd, name, email, birth, sns, reg_date)
        //values ('asdf2', '1234', 'smith', 'aaa@aaa.com', '2021-01-01', 'facebook', now());

        // 실행할 sql문 작성
        // 컬럼에 다 넣어 줄 때는 컬럼명을 써 줄 필요가 없다.
        String sql = "insert into user_info values (?,?,?,?,?,?,now())";

        // SQL Injection 공격방어, 성능향상(sql문을 여러번 재사용가능-캐싱)
        PreparedStatement ps = conn.prepareStatement(sql);
        // ? 대신 들어갈 값들을 채워준다.
        ps.setString(1, user.getId());
        ps.setString(2, user.getPwd());
        ps.setString(3, user.getName());
        ps.setString(4, user.getEmail());
        // setDate가 java.sql.Date 라서 java.util.Date 를 형변환 해줘야한다.
        ps.setDate(5, new java.sql.Date(user.getBirth().getTime()));
        ps.setString(6, user.getSns());

        // 쿼리실행
        // sql문을 실행한결과 몇개의 행이 영향을 받았는가 insert는 대부분 1개라서 1(성공) 0(실패)
        // insert, update, delete에만 사용가능
        int rowCnt = ps.executeUpdate();

        return rowCnt;
    }

    @Test
    public void jdbcConnectionTest() throws Exception {

        Connection conn = ds.getConnection(); // 데이터베이스의 연결을 얻는다.

        System.out.println("conn = " + conn);
        assertTrue(conn!=null);
    }
}
  • insertUserTest를 컴파일해보면... 

  • 성공

  • 아무것도 없던 row에 값이 저장되었다.

  • 한번 더 실행해보면?

  • id가 기본 키로 등록되어있어서 중복 id값이 들어갈 수 없다.
@Test
public void insertUserTest() throws Exception {
    User user = new User("asdf2","1234","abc", "aaa@aaa.com", new Date(), "fb",new Date());
    int rowCnt = insertUser(user);
    assertTrue(rowCnt==1);
}
  • id값을 변경해서 넣어주면 코드를 실행하면...

  • 성공
  • 테스트를 항상 성공시키기위해 deleteAll() 메서드를 생성해준다
@Test
public void insertUserTest() throws Exception {
    User user = new User("asdf2","1234","abc", "aaa@aaa.com", new Date(), "fb",new Date());
    // 항상 테스트가 성공하기 위함
    deleteAll();
    int rowCnt = insertUser(user);
    assertTrue(rowCnt==1);
}

private void deleteAll() throws Exception{
    Connection conn = ds.getConnection();

    String sql = "delete from user_Info";

    PreparedStatement ps = conn.prepareStatement(sql);

    ps.executeUpdate();
}
  • 사용자 정보를 가져오는 selectUser메서드를 생성
@Test
public void selectUserTest() throws Exception{
    User user = selectUser("asdf2");

    assertTrue(user.getId().equals ("asdf2"));
}

public User selectUser(String id) throws Exception {
    Connection conn = ds.getConnection();

    String sql = "select * from user_Info where id = ?";

    PreparedStatement ps = conn.prepareStatement(sql);

    ps.setString(1, id);

    // select는 executeQuery메서드를 사용
    ResultSet rs = ps.executeQuery();

    // 쿼리 결과가 있으면 객체를 새로 만들어서 값을 채워 반환
    if(rs.next()){
        User user = new User();
        user.setId(rs.getString(1));
        user.setPwd(rs.getString(2));
        user.setName(rs.getString(3));
        user.setEmail(rs.getString(4));
        user.setBirth(new Date(rs.getDate(5).getTime()));
        user.setSns(rs.getString(6));
        user.setReg_date(new Date(rs.getDate(7).getTime()));

        return user;
    }

    return null;
}
  • 테스트 성공

  • 항상 테스트가 성공하기 위해서 코드를 변경
@Test
public void selectUserTest() throws Exception{
    // 항상 테스트가 성공하기 위함
    deleteAll();
    User user = new User("asdf2","1234","abc", "aaa@aaa.com", new Date(), "fb",new Date());
    int rowCnt = insertUser(user);
    User user2 = selectUser("asdf2");

    assertTrue(user.getId().equals ("asdf2"));
}
  • 각 테스트는 다른 테스트에게서 독립적이고 항상 성공해야한다.
  • 각 Test가 DataSource ds 인스턴스 변수를 공유하지 않는다.
  • deleteUser메서드 - id를 주면 id에 해당하는 유저를 삭제
@Test
public void deleteUserTest() throws Exception{
    deleteAll();
    int rowCnt = deleteUser("asdf");
    assertTrue(rowCnt==0);

    User user = new User("asdf2","1234","abc", "aaa@aaa.com", new Date(), "fb",new Date());
    rowCnt = insertUser(user);
    assertTrue(rowCnt==1);

    rowCnt = deleteUser(user.getId());
    assertTrue(rowCnt==1);

    assertTrue(selectUser(user.getId())==null);
}

// id를 주면 id에 해당하는 유저를 삭제
public int deleteUser(String id) throws Exception {
    Connection conn = ds.getConnection();

    String sql = "delete from user_Info where id = ?";

    PreparedStatement ps = conn.prepareStatement(sql);

    ps.setString(1, id);
    int rowCnt = ps.executeUpdate();
    return rowCnt;
}
  • 여러번 테스트를 진행... 모두 성공

 

  • Update
@Test
public void updateUserTest() throws Exception{
    deleteAll();
    User user = new User("asdf2","1234","abc", "aaa@aaa.com", new Date(), "fb",new Date());
    insertUser(user);

    int rowCnt = updateUser(user);
    assertTrue(rowCnt==1);
}

public int updateUser(User user) throws Exception{
    Connection conn = ds.getConnection();
    if (!(user.getId().equals("asdf2")))
        return 0;

    String sql = "UPDATE user_Info SET pwd = ? where id = ?";

    PreparedStatement ps = conn.prepareStatement(sql);

    Field f = User.class.getDeclaredField("pwd");

    // user.getPwd()의 이름을 얻어야한다
    ps.setString(1,"asdfasdf");
    ps.setString(2, user.getId());

    int rowCnt = ps.executeUpdate();
    return rowCnt;
}