1

Java 6 (およびそれ以降) でおもちゃのデータ アクセス メカニズムを開発しています。各モデル クラスにはfindById、指定された ID を持つ行からオブジェクトをインスタンス化する静的メソッドが必要です。以下に示すアプローチを思いつきました。私のアプローチは良い習慣と見なされますか? そうでない場合、何を改善できますか?

データベース (MySQL) ブートストラップ スクリプト:

create database test;
create user test identified by 'test';
grant all on test.* to test;
use test;
create table products(id integer,name varchar(10));
insert into products values(1,'led');

ソースコード:

import java.sql.*;

class Test {
    public static void main(String[] args) throws SQLException, ClassNotFoundException {
        Class.forName("com.mysql.jdbc.Driver");
        Product p = Product.findById(1);
        System.out.println(p.id + " " + p.name);
    }
}

class Database {
    static <T extends Model<T>> T findById(T m, String sql, int id) throws SQLException {
        try (Connection conn = DriverManager.getConnection("jdbc:mysql:///test", "test", "test");
                PreparedStatement stmt = conn.prepareStatement(sql)) {
            stmt.setInt(1, id);
            try (ResultSet rs = stmt.executeQuery()) {
                rs.next();
                m.load(rs);
            }
        }
        return m;
    }
}

abstract class Model<T> {
    abstract void load(ResultSet rs) throws SQLException;
}

class Product extends Model<Product> {
    int id;
    String name;

    static Product findById(int id) throws SQLException {
        return Database.findById(new Product(), "select * from products where id=?", id);
    }

    @Override
    void load(ResultSet rs) throws SQLException {
        this.id = rs.getInt("id");
        this.name = rs.getString("name");
    }
}
4

4 に答える 4

2

Productエンティティ ( ) とデータ アクセス レイヤーの間に密結合を導入して、懸念と責任を混在させています。

別れるべき

  • エンティティ (ゲッター/セッターと、場合によっては内部ビジネス ロジックのみを持ちます。モデル全体に​​応じて、それも分離したい場合があります)
  • データ アクセス レイヤー: エンティティ ( ) ごとに、エンティティProductDaoを取得/保存/削除するために実行するメソッドを備えたインターフェイスがあります。次に、選択したテクノロジ (この場合は JDBC) を使用して、これらの具体的な実装を行うことができます。したがって、後でデータ アクセス技術を変更したい場合は、たとえばこれら (JdbcProductDaoおよび) を別の実装にすることができます。HibernateProductDao

さらに一歩進んで、DAO レイヤーを実際のリポジトリ レイヤーから分離したい場合もありますが、システム内にあるさまざまなエンティティ クラスの数によっては、時期尚早の最適化と見なされる可能性があります。

これには多くの利点があります。

  • 光結合は全体的に優れた設計です
  • より良いテスト容易性など

また、ジェネリック メソッドをあらゆる場所に配置しようとすることは、必ずしも良い考えではありません。通常、必要なメソッドはfindByIdエンティティごとにわずかに異なり、一部のメソッドは、説明したジェネリック メソッドに適合しませんDatabase(I'それが静的メソッドであるとは言及していませんが、これは悪臭です)。私の現在のチームでは、3 つのルールを使用しています。リファクタリングされたジェネリック クラス/メソッドを導入するのは、システムの 3 番目の要素を記述している場合にのみ、そのメリットが得られるからです。それ以外の場合は、時期尚早の最適化と見なします。

于 2012-09-03T12:08:40.593 に答える
2

私はむしろDAOベースのアプローチを使用したいと思います。基本的な CRUD メソッドを使用して 1 つのクラスを作成する必要があります。GenericDao<T>派生したすべての DAO クラスには、指定されたエンティティ クラスに対してすぐに使用できる CRUD 機能があります。

説明されている手法を示す 2 つの記事を次に示し ます 。 ibm.com/developerworks/java/library/j-genericdao/index.html

于 2012-09-03T11:55:27.527 に答える
1

ベーシックなデザインが気に入っています。しかし、実際のプロダクション プロジェクトでは、次の 3 つの変更を行います。

  1. データベースおよび任意のリソース コードで、finally ブロックを追加し、各接続 (1 つしかありません) を個別の try-catch で閉じます。そうしないと、con リークが発生します。
  2. データベース内: 共有接続プールを使用する
  3. Product getById で、製品が再利用される場合はそれらを HashMap にキャッシュします。既にロードされている場合は、毎回新しいオブジェクトを作成する場合は代わりにそれを返します。これは使用状況によって異なりますが、100 行から 5,000 行あり、時々変更されるが何度も読み取られる多くのテーブルに対して実行します。
于 2012-09-03T11:57:57.640 に答える
0

オブジェクト リレーショナル マッピング (ORM) とデータ アクセス オブジェクト (DAO) の方法論を再発明しています。Hibernateなど、ここでやろうとしていることを正確に実行する多くの Java ライブラリが存在します。この質問に対する正しい答えを得るよりも、このライブラリの方が便利だと思うかもしれません。

于 2012-09-03T12:01:00.537 に答える