자바 팀 프로젝트

JAVA-DBConnection(JDBC)

● JDBC는 MySQL로 하는것이 아니라 이클립스로 작성
● JAVA에서 db에 접근할 수 있도록 해주는 API를 JDBC라고 한다.
● Java DataBase Connectivity
     ○ 자바에서 데이터베이스에 접속할 수 있도록 해주는 자바 API
● 자바 프로그램이 데이터베이스와 연결되어 데이터를 주고 받을 수 있게 해주는 
  프로그래밍 인터페이스다.
● JDBC의 역할
	○ 통역자 역할 : 응용프로그램과 DBMS간의 통신을 중간에 번역해주는 역할
● java.sql Package 필요하다.
	○ java.sql.Driver
    	■ DB와 연결하는 Driver class를 만들 때 반드시 implements해야 하는
          interface로 JDBC 드라이버의 중심이 되는 interface다.
          
   	○ java.sql.Connection
    	■ 특정 데이터베이스와 연결정보를 가지는 interface입니다.
        ■ DriverManager로 부터 Connection 객체를 가져옵니다.
        
    ○ java.sql.ResultSet
    	■ SELECT구문 실행 결과를 조회할 수 있는 방법을 정의한 interface
        
    ○ java.sql.PreparedStatement
    	■ Statement의 하위 interface입니다.
        ■ SQL문을 미리 컴파일 하여 실행 속도를 높입니다.
        
    ○ java.sql.CallableStatement
    	■ PreparedStatement의 하위 interface입니다.
        ■ DBMS의 Stored procedure을 호출합니다.
        

  1. Java에서 SQL문을 문자열 타입으로 작성
  2. 설치된 Driver를 이용해서 Connection 객체 생성
  3. Connection 객체를 통해 PreparedStatement 객체 생성(SQL문을 넘겨주며)
  4. 만들어진 PreparedStatement 객체를 통해 SQL문 수행
  5. SELECT문이라면 검색 결과가 있으므로 ResultSet 객체로 받기
  6. 적절한 횟수의 rs.next()를 통해 받아오고자 하는 데이터가 위치한 행 선택
  7. rs.get~~~()로 각 컬럼의 데이터 받아오기

JDBC API

 ● Java DataBase Connectivity의 약자로 JDBC는 자바 언어로 데이터베이스 프로그래밍을 하기 위한 라이브러리이다.
 
 ● JDBC는 DBMS에 종속되지 않는 관련 API를 제공한다. JDBC API는 JDK에서 제공하며 JDBC 프로그래밍을 
   위해서는 JDBC드라이버가 필요하다! JDBC 드라이버는 각 DBMS 회사에서 제공하는 라이브러리 압축파일이다. 
   우리는 MySQL 데이터베이스관리시스템을 사용하지만 오라클을 사용한다면 오라클용 JDBC 드라이버가 필요하다.

*라이브러리 위치	
	● C:\Program Files (x86)\MySQL\Connector J 8.0 
    

세팅

먼저 자바와 mysql은 서로 다른 프로그램이다.
Java에서 sql에 접근하고 싶으면 java build path를 만들어야 한다.
외부의 jar파일을 이용하여 java의 api에 연결하는 것이다.
보통의 jar파일은 다음과 같은 경로에 있다.

C:\Program Files (x86)\MySQL\Connector J 8.0
mysql-connector-java-8.0.27.jar파일을 import
해당 파일을 참조하고 싶으면 프로젝트 > 우측마우스 클릭 > properties > java build path > add external JARs > jar 파일선택, apply and close

위와같은 절차를 마치면 우리의 프로젝트 안에 referenced libraries가 생성되고 그안에 우리가 넣은 jar파일이 존재한다.

세팅코드 작성

dbconnection을 할때마다 연결하는 코드를 작성하고 연결시킨다음 쿼리문을 통해 데이터를 crud하는 작업은 매번하기에는 번거롭고 우리의 프로젝트가 만약 데이터베이스가 필요한 프로젝트라면 한번만 연결하는 프로젝트일 가능성은 매우 낮다.
따라서 객체로써 클래스로 만들어 활용하면 필요할 때마다 객체화하여 가져오는 것이 더욱 효율적일 것이다.

따라서 클래스로 만들어서 다른 클래스나 패키지에서 참조될 수 있도록 하자
필요와 사용성에 따라 클래스의 타입을 결정한다.
여기서는 먼저 public으로 class를 생성할 것이다.

public class DBconn{
	
}

다음 자바의 sql내장 타입인 Connection을 이용하여 변수를 만든다.
다음 객체를 다른 클래스에서 이용하지 못하게 private으로 만들고 메소드를 별도로 만들어 메소드를 이용하여 접근할 수 있도록 할 것이다.

다른 패키지와 다른 클래스에서 이용할 수 있도록 public과 전역에서 사용하는 static으로 만들자

public class DBconn{
	private static Connection conn;
    public static Connection getConnection(){
    	
    }
}

다음은 Class.forName()을 호출하여 Driver가 자기자신을 초기화 하여 DriverManager에 등록하게 한다. 즉, 개발자과 관리하지 않는 static객체들이 알아서 DriverManager에 등록되게 하는 것이다.
어떤 인자로도 전달하지 않고 그냥 호출만 하지만 여기서는 해당되는 jdbc의 Driver를 문자열로 작성해준다.
또한 작성된 드라이브는 객체를 참조하지 못했을 때 오류를 리턴해야 함으로 trycatch문으로 만들어야 한다.
자동완성 시키면 편하다.
cntl + shift + z

public class DBconn{
	private static Connection conn;
    public static Connection getConnection(){
    	try{
        	Class.forName("com.mysql.cj.jdbc.Driver");
            System.out.println("드라이버 로딩성공!");
        }catch(ClassNotFoundException e){
        	System.out.println("실패");
        }
    }
}

이제 드라이브가 로딩성공하였다면 이제는 우리의 Mysql과 sql의 아이디 비밀번호를 통해 dbms에 접근하는 코드를 작성한다.
driverManager의 내장 함수인 getConnection을 이용하여 dbms의 경로, 아이디, 비밀번호를 넘기면 데이터베이스에 접근 할 수 있다.
또한 연결이 실패 될 수 있음으로 trycatch문으로 만드는데 catch문은 연결이되니 연결시켜서 SQLException 에러를 리턴한다.
그리고 getConnection함수를 이전에 만든 Connection 객체에 넣을 것인다.
이 객체가 null인지의 여부를 판단하여 연결문을 실행 할 지 아니면 그냥 데이터베이스 연결을 담은 conn을 리턴할지 결정한다.

import java.sql.Connection;

public class DBconn {
// DB관련 jar 파일을 build하여 import 시킨 다음
//	DB와 연결해야 한다ㅣ. 
//	connection 관련 객체를 담는 static 변수를 private로 담는다. 
	private static Connection conn;
//	해당 변수를 실행 시 dbconnection이 되도록 한다.
	public static Connection getConnection() {
		if(conn == null) {
//			conn 객체에 접근하지 않는 경우 아래의 코드를 실행한다.
			try {
//				데이터베이스에 접근하는 드라이브를 실행
				Class.forName("com.mysql.cj.jdbc.Driver");
				System.out.println("드라이버 로딩성공!");
				
				String url = "jdbc:mysql://localhost:3306/web0315";
				String user = "아이디";
				String password = "비밀번호";
// 드라이브메니저의 내장메소드를 이용해 우리가 사용할 dbms정보를 넘겨주고 있다.
				conn = DriverManager.getConnection(url, user, password);
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}catch(SQLException sqle) {
				System.out.println("실패");
			}
		}
		return conn;
	}
}

여기까지 왔다면 이제 데이터베이스를 사용할 준비가 끝난것이다.
사용하는 방법은 다음과 같다.
sql문은 담는 변수, Connection객체 초기화, PreparedStatement 초기화
준비.

사용할 sql문 작성, conn에 우리가 만든 DB클래스의 메소드 담기,
PreparedStatement에 Connection 객체명인 conn에 prepareStatement메소드 사용하여 sql문 담기
여기까지 하면 준비가 완료된 것이다.
이제 어떻게 사용하는가에 따라 달라진다.
우리는 select를 사용하기에 executeQuery메소드를 이용하고 만약 그외의 sql문을 사용한다면 executeUpdate메소드를 사용하는 것이다.
이 메소드를 사용했다면 resultSet에 변수로 담아주어 가져온 정보를 출력해주면 끝이다.

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DBTest {
	public static void main(String[] args) {
		String sql = "";
		Connection conn;
		PreparedStatement ps;
		
		try {
			sql = "select * from user";
			conn = DBconn.getConnection();
			ps = conn.prepareStatement(sql);
			
			ResultSet rs = ps.executeQuery();
			String [] getdata = {"useridx", "userid",
					"userpw","username","userage","userphone","useraddr"};
			while(rs.next()) {
				String result = "";
				for (int i = 0; i < getdata.length; i++) {
					result += rs.getString(i+1) + " / ";					
				}
				System.out.println(result);
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

추가적으로 쿼리문에 변수를 이용한다면 ?를 작성한다.
?에 문자열 연결로 변수명을 작성하던가 혹은 곧바로 sql문안에 ""가 들어간 변수가 필요하다면 setString을 이용한다. excute를 사용하는 것처럼 prepareStatement메소드가 있는 ps객체명에 붙여서 사용한다.

// 첫번째 ? 에 strdata 넣어줘
ps.setString(1, strdata);
ps.executeUpdate();        

JDBC를 이용한 데이터베이스 연동과정

① JDBC 드라이버 로드
		
Class.forName("com.mysql.Jdbc.Driver"); 
→ Class.forName() 메서드를 호출하여, mysql에서 제공하는 Driver 클래스를 
  JVM method area에 로딩시킨다. 


② 데이터베이스 연결
String jdbc_url = "jdbc:mysql://localhost:3306/datebase?serverTimezone=UTC";
Connection con = DriverManager.getConnection(URL, "user", "password");
→ 두 번째 줄의 의미는 localhost:3306 (로컬 환경에서 MySQL의 포트번호가 3306이기 때문이다) 
  그리고 database는 스키마 이름을 지정하면 된다. 이제 Connection 객체를 만들어 사용하게 되는데 
  방법은 DriverManager 클래스의 static 메서드인 getConnection() 메서드를 호출해서, 
  mysql에 연결하기 위한 커넥션 정보(url, user, password)를 입력한다.
  getConnection() 메서드 수행 결과로 Connection 객체를 반환하는데, 이 객체를 통해 쿼리를 
  날리는 statement를 작성할 수 있다. SELECT 쿼리에서는 createStatement() , 
  INSERT에서는 prepareStatement()를 호출한다.
  

  ※ 스키마란 - 데이터베이스의 구조와 제약조건에 관해 전반적인 명세를 기술한 것

③ SQL을 위한 객체생성
	Statement stmt = con.createStatement();
④ SQL 문장 실행
	String sql = "select * from student";
	ResultSet result = stmt.executeQuery(sql); 
→ select 문장은 테이블 형태의 결과를 반환한다. 그러므로 select 문장을 
  실행하기 위해 Statement의 메소드 executeQuery()를 사용한다. 
  메소드 executeQuery()는 질의 결과로 테이블 형태의 결과를 반환하는데, 
  이 반환형이 인터페이스 ResultSet이다. 객체 Statement의 메소드 executeUpdate()는 create 
  또는 drop, insert, delete, update와 같이 테이블의 내용을 변경하는 문장에 사용한다.

⑤ 질의결과 처리

	while(result .next()){       
    String name = result .getString(1);
    String owner = result .getString(2);
    String date = result .getString(3);
}
→ ResultSet 인터페이스에는 질의 결과의 현재 행(row)을 가리키는 커서(cursor)라는 개념이 있으며, 
  이 커서를 다음 행으로 이동시키는 메소드가 next()이다. 
  

▲ 예를들어 위와 같이 결과가 나온 테이블의 구조가 있다고 가정하면 처음에는 첫번 째 행을 가리킬거고 그 행이 존재한다면 true, 존재하지 않는다면 false를 리턴한다.

● ResultSet의 메소드 getString()과 getInt() 
	○ ResultSet의 커서가 있는 행에서 컬럼 자료를 참조하기 위해 ResultSet이 
      제공하는 메소드 getString()을 이용한다. 
    ○ getString()의 인자는 컬럼 이름을 문자열로 쓰거나 또는 컬럼 번호를 이용할 수 있다.
      컬럼 값의 자료유형에 따라 메소드 getString()뿐만 아니라 
      getInt(), getDouble(), getDate() 등 다양한 컬럼 반환 메소드를 제공한다.
      

● SELECT 쿼리 예제

	import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
 
public class Example1 {
 
   public static void main(String[] args) {
      // TODO Auto-generated method stub
      
      String jdbc_driver = "com.mysql.cj.jdbc.Driver";
      String jdbc_url = "jdbc:mysql://localhost:3306/board?serverTimezone=UTC";
      try {
          
         Class.forName(jdbc_driver).newInstance();
         Connection con = DriverManager.getConnection(jdbc_url, "root", "root");
         Statement st = con.createStatement();
         
         String sql = "SELECT * FROM member";
         ResultSet rs = st.executeQuery(sql);
 
         while(rs.next()){       
             String name = rs.getString(1);
             String owner = rs.getString(2);
             String date = rs.getString(3);
 
             System.out.println(name + " " + owner + " " + date);
         }
 
      
         rs.close();
         st.close();
         con.close();    
         
      } catch (Exception e) {
         e.printStackTrace();
      } 
   }
}
 ● INSERT 쿼리 예제
	import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
 
public class InsertTest {
    public static void main(String[] args) {
        // pet 테이블에는 이름/소유자/종/성별/출생일 칼럼이 있습니다.
        insert("봄이", "victolee", "페르시안", "m", "2010-08-21", null);
    }
 
    public static void insert(String name, String owner, String species,
                              String gender, String birth, String death){
        Connection conn = null;
        PreparedStatement pstmt = null;
 
        try{
            // 1. 드라이버 로딩
            Class.forName("com.mysql.jdbc.Driver");
 
            // 2. 연결하기
            String url = "jdbc:mysql://localhost/dev";
            conn = DriverManager.getConnection(url, "dev", "dev");
 
 
            // 3. SQL 쿼리 준비
            // 추가하려는 데이터의 값은 전달된 인자를 통해 동적으로 할당되는 값이다.
            // 즉 어떤 값이 전달될지 모르므로 Select 할 때와 달리
            // stmt = conn.createStatement(); 를 작성하지 않고
            // pstmt = conn.prepareStatement(sql); 로 작성하여 데이터를 추가할 것임을 알립니다.
            // 물론 sql 쿼리 내에서 + 연산자로 한 줄로 작성할 수 있지만 가독성이 너무 떨어지게 되므로
            // 이 방법을 권합니다.
            String sql = "INSERT INTO pet VALUES (?,?,?,?,?,?)";
            pstmt = conn.prepareStatement(sql);
 
 
            // 4. 데이터 binding
            pstmt.setString(1, name);
            pstmt.setString(2, owner);
            pstmt.setString(3, species);
            pstmt.setString(4, gender);
            pstmt.setString(5, birth);
            pstmt.setString(6, death);
 
 
            // 5. 쿼리 실행 및 결과 처리
            // SELECT와 달리 INSERT는 반환되는 데이터들이 없으므로
            // ResultSet 객체가 필요 없고, 바로 pstmt.executeUpdate()메서드를 호출하면 됩니다.
            // INSERT, UPDATE, DELETE 쿼리는 이와 같이 메서드를 호출하며
            // SELECT에서는 stmt.executeQuery(sql); 메서드를 사용했었습니다.
            // @return     int - 몇 개의 row가 영향을 미쳤는지를 반환
            int count = pstmt.executeUpdate();
            if( count == 0 ){
                System.out.println("데이터 입력 실패");
            }
            else{
                System.out.println("데이터 입력 성공");
            }
        }
 
        catch( ClassNotFoundException e){
            System.out.println("드라이버 로딩 실패");
        }
 
        catch( SQLException e){
            System.out.println("에러 " + e);
        }
 
        finally{
            try{
                if( conn != null && !conn.isClosed()){
                    conn.close();
                }
                if( pstmt != null && !pstmt.isClosed()){
                    pstmt.close();
                }
            }
            catch( SQLException e){
                e.printStackTrace();
            }
        }
    }
}
  • Insert 쿼리를 수행할 때도 먼저 Connection 객체를 얻어야 한다.
  • INSERT는 일반적으로 동적으로 값이 할당되므로createStatement()를 호출하지 않고, 쿼리를 준비하는 statement라는 의미로 prepareStatement() 메서드를 호출한다.
    그러면 PreparedStatement 를 반환하는데, pstmt.setString() 메서드를 통해 동적으로 값을 할당할 수 있다. 값이 할당되면 pstmt.executeUpdate() 메서드를 실행하여 INSERT 쿼리를 실행 할 수 있다. 반환 값은 영향을 미친 row의 개수이다.

마무리

  • 쿼리를 수행할 때 동적으로 할당해야 하는 값이 있으면 PreparedStatement 객체를 사용하고, 동적으로 할당할 필요가 없으면 Statement 객체를 사용한다.
  • 쿼리의 결과가 있으면 executeQuery() 메서드를 호출하여 ResultSet 객체에 담고, 쿼리의 결과가 없으면 executeUpdate() 메서드를 호출하여 int형 변수에 결과 값을 할당한다.

좋은 웹페이지 즐겨찾기