두번째 필수강의 ch3 13강 요약
Spring DI 강의를 듣고 한동안 멈춰두었던 스프링 강의를 다시 집어들었다. 스프링 부트를 먼저 듣고 와서 조금은 낯이 익었다.
먼저 JDBC api를 사용해 mysql DB에 접근해본다.
MavenRepository에서 mysql 드라이버 의존성을 받아 추가해주어야 한다.
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
다음으로는 아래와 같은 DBConnectionTest 클래스를 만들어 실행한다.
import java.sql.*;
public class DBConnectionTest {
public static void main(String[] args) throws Exception {
// 스키마의 이름(springbasic)이 다른 경우 알맞게 변경해야 함
String DB_URL = "jdbc:mysql://localhost:3306/springbasic?useUnicode=true&characterEncoding=utf8";
// DB의 userid와 pwd를 알맞게 변경해야 함
String DB_USER = "아이디";
String DB_PASSWORD = "비밀번호";
Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD); // 데이터베이스의 연결을 얻는다.
Statement stmt = conn.createStatement(); // Statement를 생성한다.
String query = "SELECT now()"; // 시스템의 현재 날짜시간을 출력하는 쿼리(query)
ResultSet rs = stmt.executeQuery(query); // query를 실행한 결과를 rs에 담는다.
// 실행결과가 담긴 rs에서 한 줄씩 읽어서 출력
while (rs.next()) {
String curDate = rs.getString(1); // 읽어온 행의 첫번째 컬럼의 값을 String으로 읽어서 curDate에 저장
System.out.println(curDate); // yyyy-MM-dd HH:mm:ss
}
} // main()
}
ResultSet은 2차원의 테이블 형태를 하고 있다. rs에서 한줄씩 읽어와서 출력하는데, spring basic 스키마에 아무것도 등록된 게 없다면 날짜와 시간이 찍힌다. 성공적으로 연결된 것을 확인할 수 있었다.
Spring JDBC를 활용하려면 다음 의존성을 추가해준다.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>6.1.2</version>
</dependency>
강의에서는 SpringFramework와 같은 버전으로 받아 사용하였다.
Spring JDBC는 DriverManager를 사용하지 않고 DriverManagerDataSource를 사용한다.
public class DBConnectionTest2 {
public static void main(String[] args) throws Exception {
// // 스키마의 이름(springbasic)이 다른 경우 알맞게 변경
// String DB_URL = "jdbc:mysql://localhost:3306/springbasic?useUnicode=true&characterEncoding=utf8";
//
// // DB의 userid와 pwd를 알맞게 변경
// String DB_USER = "아이디";
// String DB_PASSWORD = "비밀번호";
// String DB_DRIVER = "com.mysql.jdbc.Driver";
//
// DriverManagerDataSource ds = new DriverManagerDataSource();
// ds.setDriverClassName(DB_DRIVER);
// ds.setUrl(DB_URL);
// ds.setUsername(DB_USER);
// ds.setPassword(DB_PASSWORD);
ApplicationContext ac = new GenericXmlApplicationContext("file:src/main/webapp/WEB-INF/spring/**/root-context.xml");
DataSource ds = ac.getBean(DataSource.class);
Connection conn = ds.getConnection(); // 데이터베이스의 연결을 얻는다.
System.out.println("conn = " + conn);
// assertTrue(conn!=null);
}
}
주석처리된 부분은 직접 DriverManagerDataSource를 생성하는 것으로, 위나 아래 두 줄이나 둘 다 DB에 연결하는 데에는 문제가 없다. 하지만 이렇게 직접 생성할 때는 변경사항이 생길 때마다 코드를 고쳐야 하기 때문에 불편하다. 따라서 그 아래처럼 root-context.xml에 정보를 주고 getBean으로 얻어오는 것이 훨씬 더 바람직하다.
그렇게 하려면 DriverManagerDataSource에 set 메서드들로 설정했던 값들을 root-context.xml에 등록해두어야 한다.
root-context.xml의 위치는 webapp - WEB-INF - spring 이다. Shift 키를 2번 연속으로 눌러 파일 위치를 검색하는 것이 더 편하다.
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/springbasic?useUnicode=true&characterEncoding=utf8"></property>
<property name="username" value="아이디"></property>
<property name="password" value="비밀번호"></property>
</bean>
bean을 등록하고 DBConnectionTest2를 실행해본다. null이 나오지 않으면 성공한 것이다.
TDD(Test Driven Development)는 테스트를 자동화하여 어디서 실패하고 어디서 성공하는지를 보는 개발 방식이다.
테스트를 실행할 클래스에 대고 우클릭하면 Go to... 옵션이뜬다. 여기서 Test를 누르면 새로 테스트를 생성하는 창이 뜨는데, 현재 위치한 클래스 이름 뒤에 Test가 자동으로 붙는다.
DBConnectionTest2의 메인함수를 그대로 가져온다.
public class DBConnectionTest2Test extends TestCase {
@Test
public void main() throws Exception{
ApplicationContext ac = new GenericXmlApplicationContext("file:src/main/webapp/WEB-INF/spring/**/root-context.xml");
DataSource ds = ac.getBean(DataSource.class);
Connection conn = ds.getConnection(); // 데이터베이스의 연결을 얻는다.
System.out.println("conn = " + conn);
assertTrue(conn!=null);
}
}
테스트 클래스여도 그 내부에 전부 테스트와 관련된 코드만 있는 것이 아니기 때문에 @Test 애너테이션을 붙여주어야 한다.
또, 테스트가 제대로 실행되었는지를 확인하기 위해서 assert문이 포함되어야 한다. 위에서는 connection 객체가 null이 아니면 true로 통과한다.
...
그런데 나는 오류가 발생했다.
오류: junit.framework.AssertionFailedError: No tests found in com.fastcampus.ch3.DBConnectionTest2Test
다행히 스택오버플로우를 뒤져 해결했다. 스택오버플로우 링크 테스트하는 메서드의 이름 앞에 test를 붙여주었더니 테스트를 찾지 못하던 문제가 해결되었다.
public void testMain() throws Exception {
추가로, 이미 bean이 등록되어 있으므로 DataSource로 생성할 필요 없이 @Autowired를 사용해 빈을 생성해줄 수 있다. 다만 이 경우에는 Spring Test 의존성을 추가해주고, 클래스에 @RunWith 애너테이션을 붙여주어야 한다.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.15</version>
<scope>test</scope>
</dependency>
애너테이션도 추가해준다.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/**/root-context.xml"})
public class DBConnectionTest2Test extends TestCase {
@Autowired
DataSource ds;
@Test
public void testMain() throws Exception {
Connection conn = ds.getConnection();
System.out.println("conn = " + conn);
assertTrue(conn != null);
}
}
다만 이 경우에는 JUnit 버전이 맞지 않는다고 오류가 뜬다.
SpringJUnit4ClassRunner requires JUnit 4.12 or higher.
pom.xml에 가보면 JUnit이 4.7로 되어 있었다. 이걸 4.12로 바꿔주면 오류가 해결된다.
(나는 사실 여태 그냥 일반적인 소수점처럼 생각해서 4.7이 4.12보다 큰데 왜 오류가 나지? 하고 있었다. 아니었나보다..)
또 추가로 IntelliJ에서 DB를 Workbench처럼 다룰 수 있는 기능이 있었는데, 아무래도 이 부분도 Ultimate에만 있는 부분인 것 같다.