JDBC動作


1.概要


最近は副刊でJDBCというデータベースアクセス技術を学びました.JDBCはJavaが提供するデータベースアクセスインタフェースで、ドライバと呼ばれるインプリメンテーションを使用してJavaからDBに接続できます!Javaで使用されているDBアクセス技術(MyBasis、JPAなど)はすべてJDBCに基づいて操作されているので、JDBCはもっと明確に勉強して、今回は別に整理しておきます!!

2.JDBC構造



JDBCを使用してDBに接続する手順は次のとおりです.ユーザは、JavaアプリケーションでJDBC APIを使用してDBにアクセスしたいと考えている.しかしJDBC API自体はインタフェースであるため,実装体が実際の使用方法に必要である.インプリメンテーションをインポートする役割は、DriverManagerというクラスが担当します.このクラスにDriverがインポートされている場合は、Javaとデータベースに接続する準備ができています.

3.JDBC動作方式


3.1クラス構造

├─jdbc
│  ├─util
│  │  ├─DBConnection.java
│  │  ├─DBClose.java
│  ├─ProductDao.java
│  ├─ProductDaoImpl.java
│  ├─ProductDto.java
│  ├─ProductMain.java
クラス構造は上記のとおりです.これは副刊からJDBCを勉強する際に使う仕組みです.各クラスの役割は次のとおりです.
  • jdbc.util.DBConnection→MySQL Driverで実際のDBMSサーバに接続する役割
  • jdbc.util.DBPClose→DBのオブジェクトを接続するための接続の役割を解除します.
  • jdbc.ProductDao→実際のデータベースにアクセスする役割.インターフェース.
  • jdbc.ProductDaoImpl→ProductDao実施手順
  • jdbc.ProductDto→クライアントとサーバの間でデータを渡す役割.
  • jdbc.ProductMain→実際のビジネスロジックを実行する
  • 3.2操作方式


    ProductMainクラスでSearchAll()メソッドを実装して使用したので,このメソッドの動作方法でJDBCの流れを理解する.
    ProductDaoImplクラスでは、SearchAll()メソッドを見てみましょう.
    // 1번 코드 - ProductDaoImpl 클래스의 searchAll() 메서드//
    
    @Override
    public List<ProductDto> searchAll() {
    	List<ProductDto> list = new ArrayList<>();
    
    	try (Connection conn = DBConnection.getConnection()) {
    
    		String sql = "select product_id, product_name, product_price, product_desc, ";
    		sql += "date_format(register_date, '%y.%m.%d') register_date \n";
    		sql += "from product";
    		
    		try (PreparedStatement pstmt = conn.prepareStatement(sql); 
    				 ResultSet rs = pstmt.executeQuery()) {
    			while (rs.next()) {
    				ProductDto productDto = new ProductDto();
    				productDto.setProductId(rs.getString("product_id"));
    				productDto.setProductName(rs.getString("product_name"));
    				productDto.setProductPrice(rs.getInt("product_price"));
    				productDto.setProductDesc(rs.getString("product_desc"));
    				productDto.setRegisterDate(rs.getString("register_date"));
    
    				list.add(productDto);
    			}
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
    	} catch (SQLException e) {
    		e.printStackTrace();
    	}
    	return list;
    }
    このコードを表示するには、まずConnectionオブジェクトを取得し、connオブジェクトからpreparedStatementオブジェクトを取得し、ResultSetオブジェクトをpstmtオブジェクトにインポートします.
    では、ここにリストされている各クラスがどのような役割を果たしているのか、この順序でインポートします.

    3.2.1 Connectionクラス

    // 2번 코드 - Connection 객체를 리턴하는 메서드//
    
    private static final String URL = "jdbc:mysql://127.0.0.1:3306/ssafydb?serverTimezone=UTC&useUniCode=yes&characterEncoding=UTF-8";
    private static final String DB_ID = "ssafy";
    private static final String DB_PASS = "1234";
    
    public static Connection getConnection() throws SQLException {
    		return DriverManager.getConnection(URL, DB_ID, DB_PASS);
    }
    Connectionオブジェクトはjavaです.sql APIが提供するDriverManagerクラスでは、内部ロジックを経て戻って使用します.
    ただし、このコードのみを使用してコードを実行すると、次のExceptionㅠが表示されます.

    Driver Manager内部では、ClassLoaderでJDBC Driverを読み込んでDriverインプリメンテーションを登録していますが、上記のコードにはDriverインプリメンテーションを登録する方法がないため、Driver Managerではドライバの例外が見つかりません.
    簡単に言えばドライバの場所が見つからない!!
    したがって、次のコードを追加する必要があります.
    // 3번 코드 - 드라이버를 등록하는 부분을 추가했다.//
    
    private static final String DRIVER = "com.mysql.cj.jdbc.Driver";
    private static final String URL = "jdbc:mysql://127.0.0.1:3306/ssafydb?serverTimezone=UTC&useUniCode=yes&characterEncoding=UTF-8";
    private static final String DB_ID = "ssafy";
    private static final String DB_PASS = "1234";
    	
    static {
    	try {
    		Class.forName(DRIVER);
    		System.out.println("성공");
    	} catch (ClassNotFoundException e) {
    		// TODO Auto-generated catch block
    		System.out.println("실패");
    		e.printStackTrace();
    	}
    }
    	
    public static Connection getConnection() throws SQLException {
    	return DriverManager.getConnection(URL, DB_ID, DB_PASS);
    }
    ここでDRIVERはMySQL Driver実装体の位置である.Class.forName()メソッドでJVMに登録し、DriverManagerで読み込みます.→ Class.forName()の詳細
    💡 実際、JDBC 4.0からドライバが自動的に初期化されます(コード2)!(どうしたんですか)💡
    自動サービス発見問題はJava 1.6とサービス提供ビジネスチャンス制によって解決された.これにより、サービスプロバイダは、サービスを含むJARファイルのMETA INF/servicesの下にサービスを配置して、サービスを宣言することができる.
    このメカニズムでは、ドライバが自動的に登録されるため、クラスを手動でロードする必要はありません.ただし、手動でクラスをロードしても、サービスプロバイダがその場にいても失敗することはありません.最近使用したJVMとJDBC 4ドライバを使用してドライバのロードを明示的に呼び出すのは完全に合法的です.
    サービスプロバイダ仕様は、手動でクラスをロードする代わりに宣言されます.たとえば、PostgreSQL JDBCドライバは、META-INF/サービス/の下にファイルがあります.ファイル名はjavaです.sql.ドライバ(JDBCドライバのルール).JDBCドライバのorgなどの標準化されたクラス名が含まれています.postgresql.Driverです
    以上の内容はhttps://www.baeldung.com/java-jdbc-loading-drivers#jdbc-4-approachここで確認した内容です!!

    3.2.2 PreparedStatementクラス


    Connectionオブジェクトのロードに成功し、DBMSサーバへの接続に成功しました.Javaから必要なクエリーを発行し、その結果をjavaとして値を受信するプロセスしか残っていません.まず、JavaからDBMSにクエリーを送信するには、PreparedStatementクラスが必要です.
    先ほど(コード1)に次のようなコードがありました.
    // 4번 코드 - PreparedStatement 객체 선언부//
    
    try (PreparedStatement pstmt = conn.prepareStatement(sql); 
    		 ResultSet rs = pstmt.executeQuery())
    ここで、PreparedStatementはConnectionオブジェクトから内部ロジックを経て、戻って使用します.PreparedStatementはAutoCloseableインタフェースを継承して使用するため、try文のカッコで宣言します.(使用完了後自動クローズ可能)
    prepareStatement()パラメータから受信したsqlには、使用するクエリー文に関する情報が含まれます.

    3.2.3 ResultSetクラス


    PrepareStatementオブジェクトを受信すると、executeQuery()メソッドを実行してSELECT文を実行した結果をResultSetオブジェクトに返すことができます.
    // 코드 5 - ResultSet 객체로 받은 테이블 정보를 DTO에 저장하는 코드 //
    
    while (rs.next()) {
    	ProductDto productDto = new ProductDto();
    	productDto.setProductId(rs.getString("product_id"));
    	productDto.setProductName(rs.getString("product_name"));
    	productDto.setProductPrice(rs.getInt("product_price"));
    	productDto.setProductDesc(rs.getString("product_desc"));
    	productDto.setRegisterDate(rs.getString("register_date"));
    	
    	list.add(productDto);
    }
    ResultSetは、初期化時に受信したテーブルの最初の行を指し、next()を実行するたびに次の行に移動できます.
    また,get~~()メソッドでは,カラムのインデックス(整数)をパラメータとして受け入れることもできるし,行のラベル名を受け入れることもできる.(コード5)は、現在の行の値をラベル名で取得します.
    この3つのクラスを用いてselectAll()の論理実装を完了した.生成されたリストをクライアントに返します.
    
    // 코드 6 - 클라이언트가 리스트를 반환 받아 사용하는 모습//
    
    private void searchAll() {
    		List<ProductDto> list = ProductDaoImpl.getProductDao().searchAll();
    		showList(list);
    }
    生成されたリストを使用して、次のビューを作成して出力します.

    4.考察


    JDBCは全てのDB技術の基礎になっているので、本来勉強しようとしていた技術の一つですが、毎日遅れてしまい、今回はサインのおかげで、やっと少しでも近づけることができました.JDBCの動作をある程度理解している以上、後でMyBasisやJPAを勉強するときに、どのような関連があるかを確認することができます.