2

Drupal CMS からデータを取得する Java クラスがあります。最終的に Drupal には、Java に取り込んでキャッシュする必要があるかなりの数のコンテンツ タイプが存在することになります。Drupal の動作方法により、各コンテンツ タイプは個別のデータベース ビューになります。

サービスレイヤーによって呼び出される次のメソッドがあり、特定のオブジェクトタイプを返します。しかし、私が恐れているのは、コンテンツ タイプごとにこれらのメソッドが急増していることです。

誰かがそれをより一般的にする方法を提案できますか? データベース メソッドは、2 番目のコード サンプルに示されています。私もそれをジェネリックにできるかどうか、そしてそれが価値があるかどうかはわかりません。たぶん、最初のメソッドで 1 つのメソッドを呼び出し、2 番目のメソッドで case ステートメントを使用することができます。

public DeliverySchedule getDeliverySchedule(final String cmsKey) { //     <---- make return type (Del Schedule) generic

    String cacheKey = TYPEDS + cmsKey;
    DeliverySchedule cmsInstance = CMSObjectCache.getCachedCMSObject(cacheKey, DeliverySchedule.class);   // Make generic

    // Object not found in cache, go to database.
    if (cmsInstance == null) {
        try {
            cmsInstance = getDeliveryScheduleFromDB(cmsKey);   //  <---- How can I make this generic so I can avoid DRY?
            CMSObjectCache.putCachedCMSObject(cacheKey, new CMSObject(DeliverySchedule.class, cmsInstance));
            return cmsInstance;
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
    } else {
        return cmsInstance;
    }
}

上記のコンテンツ タイプに固有のデータベース アクセス方法:

    // Called from above
private List<DeliverySchedule> getDeliverySchedulesFromDB() {
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
    final String sql = "select * "
            + "         from cmsutil.delivery_schedules as m "
            + "         where m.effdate = (select max(mm.effdate) "
            + "                            from cmsutil.delivery_schedules as mm "
            + "                            where mm.cms_key = m.cms_key "
            + "                            and mm.effdate <= current_date)";


    List<DeliverySchedule> listcmsObject = jdbcTemplate.query(sql, new DeliveryScheduleMapper());
    return jdbcTemplate.query(sql, new DeliveryScheduleMapper());
}
4

2 に答える 2

1

通常、テーブルまたはビューごとに DAO (DAO のインターフェイスとそれを実装するクラス) があります。そうすれば、特定のテーブル スキーマが変更された場合、変更は 1 つの DAO クラスに分離されます。

コンテンツ タイプを一般化して、単一のインターフェイスと、各コンテンツ タイプのインターフェイスを実装するクラスを持つことができます。これにより、一般的なコンテンツ タイプ レイヤー、特定のコンテンツ タイプ、およびデータ アクセス レイヤーでの変更に適応できるようになります。

多くのコードになる可能性があることに同意しますが、各コンポーネントが他のコンポーネントから分離されている場合、コンポーネントの変更/追加、またはスキーマの変更に対処する際に柔軟性が得られます. デカップリングと抽象化は、短期的には苦痛になる可能性がありますが、長期的には、エンジニアリング チーム全体で報われる傾向があります。

私はこのような質問や議論を楽しんでおり、提案やその他のアプローチに対して常にオープンです。

于 2012-06-11T16:53:15.697 に答える
0

クラスの新しいインスタンスを作成するには、クラスオブジェクトで反射ギアを使用する必要があります。つまり、インスタンスにそのクラスのレコードがあるジェネリッククラスを使用します。あなたの豆がmybeanを拡張するとしましょう。

abstract class<T extends MyBean> Mapper implements T {
    abstract void map(ResultSet rs);
}

class DAO<T extends MyBean> {
    Class<Mapper<T>> theMapperClass;
    DAO(Class<T> clazz) { 
        this.theMapperClass = getMapperClassFor(clazz); 
    }

    List<T> getAList() {
        List<T> l = new ArrayList<T>();
        ResultSet rs = runTheQuery();
        while(rs.next()) {
            l.add(theMapperClaxx.newInstance().map(rs));
        }
        return l;
    }
}

そういうこと。

   DAO<Foo> fooDao = new Dao<Foo>(Foo.class);
   List<Foo> l = fooDao.getAList();

   List<? extends MyBean> l = someDao.getAList();

   static <T extends Mybean> List<T> boink(Class<T> clazz) {
       DAO<T> tDao = (DAO<T>) daoMap.get(clazz);
       return tDao.getAList();
   }

   List<Foo> l = boink(Foo.class);
于 2012-07-18T03:11:52.913 に答える