産業発展に携わっているすべての人に 流血の企業 データベースワークレイヤーの作成に何度も対処しなければなりませんでした。 私たちもこれに直面しました。
私たちのプロジェクトは、フィンランドのVaadinフレームワークとデータベース層のコアにある純粋なJDBC上に構築されています。 JDBCの経験がなかったため、スパゲッティコードの十分な大きさのレイヤーを積み上げ、それから勇敢に対処しました。
どのようにそれと戦ったか、どのような自転車をカットして発明したかについて。
そのような決定に至った理由
Vaadinでは、 BeanItem Container
を使用してUIコンポーネントにデータを表示できます。ここで読むことができます。
ドメイン概要
ユーザーに表示される特定の数のエンティティであり、ユーザーはそれらを編集する必要があります:削除、変更、追加。
エンティティは、 Bean
仕様を使用して記述されました。
public class Element implements Serializable{ private Integer id = 0; private String name = ""; private Float price = 0.0F; // getter and setter for property }
そのような要素のコンテナは簡単に作成されます:
BeanItemContainer<Element> container = new BeanItemContainer<>(Element.class);
そして、このコンテナはsetContainerDataSource(...)
メソッドを使用してUIに置き換えられます。
このコンテナを取得するには、まずデータベースクエリを使用して取得したResultSet
からElement
クラスのインスタンスに解析する必要があります。
当初、ソリューションは次の種類でした。
public Element(ResutlSet rs){ try { id = rs.getInt("id"); }catch(SqlException e){ id = 0; e.printStackTrace(); } try { name = rs.getString("name"); }catch(SqlException e){ name = ""; e.printStackTrace(); } try { price = rs.getFloat("price"); }catch(SqlException e){ price = 0.0f; e.printStackTrace(); } }
そしてここで、Javaの第一人者とカルマの怒った表情は、マイナスに飛ぶように私に向けられるべきです。
しかし、概念は次のとおりです: ResultSet
からのデータの解析中にフィールドがエラーを引き起こした場合、システムはException
で抜け出て動作し続け、エラーログを書き込むべきではありません(ログは別の記事では説明しません)。
しかし、私はそのようなコードがひどいことを認めており、ボブおじさんの悪名高い本を読んだ後、このコードを修正するための抵抗できない欲求が現れました。
その結果、彼らはResultSet
からデータを取得するライブラリを作成しました。
実装
Decoratorパターンを使用して、小さなExecutorライブラリを作成しました。
このライブラリは、データを取得するための安全なメソッドを追加することにより、 ResultSet
の機能を拡張します。
public Integer getInt(String columnName) { Integer i = 0; try { i = rs.getInt(columnName); } catch (SQLException ignored) { } return i; } public Integer getIntNull(String columnName) { Integer i = 0; try { i = rs.getInt(columnName); if (rs.wasNull()) return null; } catch (SQLException ignored) { } return i; } public String getString(String columnName) { String s = ""; try { s = rs.getString(columnName); if (s == null) return ""; } catch (SQLException ignored) { } return s; }
したがって、Vaadinで少し怖いように見えるデータを処理するときに、結果を取得し、 Exception
なく動作することを100%保証します。
質問に対するException
必要な場合、答えは次のとおりです。単純なSqlExecption
ないため、呼び出されたException
タイプのExecutor
コンストラクExecutor
を追加し、正しい操作のためのメソッドを実装する計画です。
次の形式のAPIが計画されています( UPD: コメントからの提案が行われます )。
public Executor(ResultSet rs, Class<? extends RuntimeException> exceptionClass){ this.rs = rs; this.exceptionClass = exceptionClass; } public Integer getIntThrow(String columnName) { Integer i = 0; try { i = rs.getInt(columnName); if (rs.wasNull()) return null; } catch (SQLException ex) { throw exceptionClass.newInstance(); } return i; }
そしてユースケース
public Element(ResutlSet rs){ Executor ex = new Executor(rs, CreateElementException.class); id = ex.getIntThrow("id"); name = ex.getStringThrow("name"); price = ex.getFloatThrow("price"); } private class CreateElementException extends RuntimeException{ private String message = ""; public CreateElementException(String message){ this.message = message; } @Override public String getMessage(){ return "Exception with access to column with name " + this.message; } }
使用例
このライブラリを使用した後のコードで何が起こるか。 Element
クラスのコンストラクターは次のように変更されました。
public Element(ResutlSet rs){ Executor ex = new Executor(rs); id = ex.getInt("id"); name = ex.getString("name"); price = ex.getFloat("price"); }
その結果:
- より少ないコード。
- エンティティを記述する多数のクラスが存在する場合のコードベースの削減。
- コードが認識しやすくなり、エラーが発生する場所が少なくなります。
- テストを簡単に記述できます。
- 依存関係にある追加ライブラリの外観。
おわりに
別の自転車を作りました 自転車もできる必要がある 、データベースからデータを受信するためのユニバーサルで安全なアクセスを提供します。 ソースライブラリを使用したい人はGitHubにようこそ。 ソリューションの評価を受け取りたい 自転車 そして建設的な提案とコメント。