通用数据库方法

时间:2012-06-11 15:54:01

标签: java generics

我有一个Java类,可以从Drupal CMS中检索数据。 Drupal中最终会有很多内容类型需要用于Java和缓存。由于Drupal的工作方式,每种内容类型都是一个单独的数据库视图。

我有以下方法由服务层调用,它返回一个特定的对象类型。但是,我担心这些方法对每种内容类型的扩散。

有人可以建议一种让它更通用的方法吗?数据库方法显示在第二个代码示例中。我不知道我是否可以使它成为通用的,如果值得的话。也许我可以在第一个方法中调用一个方法,并让第二个方法使用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());
}

2 个答案:

答案 0 :(得分:1)

通常,每个表或视图都有一个DAO(DAO的接口和实现它的类)。这样,如果特定的表架构发生更改,您的更改将被隔离到一个DAO类。

您可以将内容类型概括为具有单个接口和实现每种内容类型的接口的类。这应该允许您适应通用内容类型层,特定内容类型和数据访问层的更改。

我同意它可能会变成很多代码,但如果每个组件与其他组件分离,它会在更改/添加组件或处理模式更改时为您提供灵活性。解耦和抽象在短期内可能会很痛苦,但从长远来看,往往会在工程团队中获得回报。

我喜欢这些问题/讨论,并且总是对建议或其他方法持开放态度。

答案 1 :(得分:0)

要创建类的新实例,需要在类对象上使用反射齿轮。所以你要做的是使用一个泛型类,其实例有该类的记录。让我们说你的bean会延长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);