<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
import java.sql.*;
DriverManager를 통해 Connection객체 생성
-> Connection객체를 통해 Statement객체 생성
-> Statement객체를 통해 ResultSet객체 생성
닫을 때는 역순이다.
ResultSet객체 해제
-> Statement객체 해제
-> Connection객체 해제
import java.sql.*
Class.forName("com.mysql.jdbc.Driver")
;String dburl = "jdbc:mysql://localhost/dbName";
Connection con = DriverManager.getConnection(dburl,ID,PWD);
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("select no from user");
ResultSet으로 결과 받기
ResultSet rs = stmt.executeQuery("select no from user");
while(rs.next())
System.out.println(rs.getInt("no"));
ResultSet객체인 rs에 저장되는 것은 쿼리 수행 결과값이 아니다. 결과값은 DB가 가지고 있고, ResultSet객체에 저장되는 것은 해당 결과를 가리키는 레퍼런스이다. 왜냐하면 쿼리결과가 10,000건이 넘는 경우, 이를 서버에 바로 전달하면 서버에 무리가 가기 때문에, 서버에서 필요한 값을 꺼내오는 형식으로 진행된다. 이떄 사용하는 메소드가 next()이다. next()는 처음에 쿼리 결과의 첫번째 레코드를 가리키며, 실행 이후에는 다음 레코드를 가리키게 된다.
Close
rs.close();
stmt.close();
con.close();
전체 소스코드
import java.sql.*;
public class Main {
public static void main(String[] args) throws Exception {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
conn = getConnection();
stmt = conn.createStatement();
rs = stmt.executeQuery("select id from guestbook;");
while(rs.next()) System.out.println(rs.getInt("id"));
} catch (Exception e) {
e.printStackTrace();
}finally {
if(rs != null) {
rs.close();
}
if(stmt != null) {
stmt.close();
}
if(conn != null) {
conn.close();
}
}
}
public static Connection getConnection() throws Exception{
Class.forName("com.mysql.jdbc.Driver");
String dburl = "jdbc:mysql://localhost:3306/connectdb?useSSL=false";
String ID = "root";
String PWD = "1111";
Connection conn = DriverManager.getConnection(dburl,ID,PWD);
return conn;
}
}
public class Main {
public static void main(String[] args) {
try {
Class.forName("com.mysql.jdbc.Driver");
String dburl = "jdbc:mysql://localhost:3306/connectdb?useSSL=false";
String ID = "root";
String PWD = "1111";
Connection conn = DriverManager.getConnection(dburl,ID,PWD);
System.out.println(conn.getClass());
} catch (Exception e) {
e.printStackTrace();
}
}
}
위 코드에서 Class.forName
의 역할은 무엇일까? 객체를 넘겨받지도 않기 때문에, 왜 필요한 코드인지 의문이 갔다.
Class.forName
위 메소드는 static
메소드이다. 메소드를 호출하면, 먼저 클래스로더가 해당 클래스의 클래스파일을 찾는다. 발견되면 클래스파일을 보고 Class<?>
의 인스턴스(특정 클래스의 메타 데이터)를 생성하여 JVM의 Method Area(Static Area)에 업로드 하게 된다. 만약 Method Area 영역에 메타 데이터가 존재한다면 추가로 Class<?>
의 인스턴스 생성하지 않을 것이다.
jdbc Driver를 사용하려면 해당 드라이버가 JVM에 로드되어 있어야 한다. 자바는 lazy loading을 지원하므로 jdbc Driver가 JVM에 로드되있지 않을 수 있다. 이를 대비하여 명시적으로 드라이버를 로드하는 것이다.
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
//
// Register ourselves with the DriverManager
//
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
/**
* Construct a new driver and register it with DriverManager
*
* @throws SQLException
* if a database error occurs.
*/
public Driver() throws SQLException {
// Required for Class.forName().newInstance()
}
}
위 코드는 com.mysql.Driver 클래스의 코드이다. 위 클래스가 로드되면 static블럭이 실행되고 java.sql.DriverManager에 해당 클래스의 인스턴스가 등록된다.
Class.forName("com.mysql.jdbc.Driver");
String dburl = "jdbc:mysql://localhost:3306/connectdb?useSSL=false";
String ID = "root";
String PWD = "1111";
Connection conn = DriverManager.getConnection(dburl,ID,PWD);
이 때문에, DriverManager에서 connection을 가져올 수 있는 것이다.