Improvements in JDBC 4.0

This is the summary of an article from JavaWorld.com.

Annotations and the generic DataSet

  • DataSet
  • extends java.util.List.
  • has a java.sql.ResultSet (when connected) or a javax.sql.rowset.CachedRowSet (when disconnected) in it.
  • Query
    • is instantiated by Connection.createQueryObject() or DataSource.createQueryObject()

    interface EmployeeQueries extends BaseQuery {
      @Select (sql=”SELECT employeeId, firstName, lastName FROM employee”)
      DataSet getAllEmployees ();

      @Update (sql=”delete from employee”)
      int deleteAllEmployees ();
    }

    Connection con = …
    EmployeeQueries empQueries = con.createQueryObject (EmployeeQueries.class);
    DataSet empData = empQueries.getAllEmployees ();
    for (Employee e: empData) {
      System.out.println(e.getFirstName());
    }

    Exception Handling Hierarchies

    • SQLException is now classified into multiplle sub-classes for better identification of the cause.
    • Support for chained exceptions and iterability

    catch(SQLException ex) {
      for(Throwable t : ex) {
        System.out.println(“exception:” + t);
      }
    }

    Leverage nonstandard vendor implemented resources

    java.sql.Wrapper supports non-standard vendor-dependent types safely

    PreparedStatement ps = …;
    if (ps.isWrappedFor(OraclePreparedStatement.class)) {
      OraclePreparedStatement ops = ps.unwrap(OraclePreparedStatement.class);
    }

    This is very similar to a simple downcasting pattern which uses instanceof keyword, but it is different and flexible in that isWrappedFor(…) and unwrap(…) can perform downcasting recursively and programmatically by its definition. To put simply, this is a safe downcasting pattern for the decorator pattern. This pattern will be also very useful for other use cases, not just for connection pool implementations.

    Miscellaneous

    • New types
    • SQLXML: created by calling Connection.createSQLXML()
    • RowId: represents vendor-independent value to reference a row in a database directly.
    • has a different life time: DatabaseMetadata.getRowIdLifetime()
  • Connection.isValid() and Connection.setClientInfo()
  • Use of Java SPI: No need to call Class.forName(…) anymore

  • JavaWorld에서 읽은 기사의 요약입니다.

    어노테이션과 DataSet

    • DataSet
    • java.util.List를 상속
    • 내부적으로 java.sql.ResultSet (접속되어 있을 때)나 javax.sql.rowset.CachedRowSet (접속이 끊어져 있을 때)를 갖고 있음
  • Query
    • Connection.createQueryObject()나 DataSource.createQueryObject()를 호출해 생성

    interface EmployeeQueries extends BaseQuery {
      @Select (sql=”SELECT employeeId, firstName, lastName FROM employee”)
      DataSet getAllEmployees ();

      @Update (sql=”delete from employee”)
      int deleteAllEmployees ();
    }

    Connection con = …
    EmployeeQueries empQueries = con.createQueryObject (EmployeeQueries.class);
    DataSet empData = empQueries.getAllEmployees ();
    for (Employee e: empData) {
      System.out.println(e.getFirstName());
    }

    예외 처리의 계층화

    • SQLException이 여러 하위 클래스로 구분되어 예외의 원인을 좀 더 자세히 알 수 있음.
    • Chained exception을 지원하고 간결한 for 루프를 쓸 수 있음.

    catch(SQLException ex) {
      for(Throwable t : ex) {
        System.out.println(“exception:” + t);
      }
    }

    벤더 종속적 자원의 활용

    java.sql.Wrapper는 벤더 종속적 타입을 안전하게 사용할 수 있는 방법을 제공

    PreparedStatement ps = …;
    if (ps.isWrappedFor(OraclePreparedStatement.class)) {
      OraclePreparedStatement ops = ps.unwrap(OraclePreparedStatement.class);
    }

    이것은 instanceof 키워드를 사용하는 기존의 단순한 다운캐스팅 패턴과 아주 비슷하지만, isWrappedFor(…)와 unwrap(…)가 다운캐스팅을 재귀적 및 프로그램적으로 수행할 수 있다는 점에서 다릅니다. 간단히 말해 데코레이터 패턴에서 쓸 수 있는 안전한 다운캐스팅 패턴인 셈입니다. 이 패턴은 커넥션 풀 구현 뿐만 아니라 다른 비슷한 곳에서도 유용하게 적용할 수 있을 것 같네요.

    기타

    • 새 타입
    • SQLXML: Connection.createSQLXML()을 호출해서 생성
    • RowId: 데이터베이스의 한 행을 직접적으로 참조할 수 있는 값을 나타내는 벤더 종속적 값
    • 라이프타임이 다를 수 있음: DatabaseMetadata.getRowIdLifetime()
  • Connection.isValid()와 Connection.setClientInfo()
  • Java SPI의 사용: Class.forName(…)을 더 이상 직접 호출할 필요가 없음