java - 使数据库表选择尽可能静态而不使用字符串

标签 java database builder-pattern

首先,这个问题会有点长,但为了充分解释我的问题,我觉得我必须给你很多关于我的项目的信息,所以请容忍我!
我在一家经常使用图表的公司工作,为了避免总是要用scats创建图表的麻烦,我决定创建一个新的java项目,并创建一个“包”,我和我的同事可以使用它来创建这些图表。你可以称它们为普通的。
因此,这个项目使用一个构建器模式和许多接口和抽象类。其思想是客户机(开发人员)使用这些接口、模式和类,并重写方法以适应流。对于客户机(开发人员)来说,唯一剩下的事情就是填充这些方法,并创建ui-him自我和发布程序。
这个程序正在形成良好的形状,我创造了许多功能,我非常自豪(因为我是一个学生),我认为我已经计划了整个过程,很好,但我遇到了一些问题!
首先,让我向您展示类并解释数据流(我将尽可能简短地这样做):
首先是gui(这是一个用户必须自己创建的类,但他可以使用内置包通过以下代码创建图表):

ChartBuilder cb = new LineChartBuilder();
                  Director d = new Director();
d.buildTypeOne(cb, "Hello", PeriodSelection.HOUR,"");

有了这个,导演现在可以做一个图表了。
< cc>是设置标准时间的枚举,在这种情况下,它将图表类别轴设置为我们的开头,因此所收集的数据知道它必须以小时为单位(在这种情况下从8到19)得到数据,这是为什么EnUM是这些类型的周期是唯一的,唯一可以改变的是我们的开头。我们可以很容易地改变的日子和时间!以下是PeroidSelection.Hour的预览:
    public enum PeriodSelection{
    HOUR(new String[]{"8:00", "9:00", "10:00", "11:00", "12:00", "13:00", "14:00", "15:00", "16:00", "17:00", "18:00", "19:00"}),
    MONTH(new String[]{"Jan", "Feb", "Marts", "April", "Maj", "Juni", "Juli", "Agu", "Sep", "Oct", "Nov", "Dec"}),
    DAYS(new String[]{"Mandag", "Tirsdag", "Onsdag","Torsdag","Fredag","Lørdag","Søndag"});

    private String[] timeIntervals;
    private PeriodSelection(String[] timeIntervals){
        this.timeIntervals = timeIntervals;
    }
    public String[] getTimeIntervals(){
        return timeIntervals;
    }
}

进入Director,Director现在已经准备好构建图表,但首先它必须从数据库中收集数据:
    public void buildTypeOne(ChartBuilder builder, String title, PeriodSelection selection, String queueName){
    try {
        builder.setObjectList(stat.getData(queueName, start, end));
    } catch (DopeDBException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    builder.selection = selection;
    builder.initiate(title);
    builder.createSeries();
    builder.createSymbol();

    builder.createTable();
}

正如你所看到的,生成器是以某种方式构建的,这是因为图表由一个表和一个图表组成,并且这两个图表必须链接在一起,我不会在图表上详细讨论,因为它与我的问题没有关联。
现在,PeriodSelection enum方法的第一行显示的stat类扩展并抽象为buildTypeOne类,如下所示:
public abstract class StatisticPattern {


protected ArrayList<ObjectInterface> cq = new ArrayList<>();
protected ObjectInterface contact;
protected ProviderInterface p;
/**
 * 
 * 
 * {@link Constructor}
 */
public StatisticPattern(){
    try {
        p = new Provider();
    } catch (DopeDBException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
/**
 * 
 * @param name
 * @param start
 * @param end
 * @return
 * @throws SQLException
 * @throws DopeDBException
 */
protected ArrayList<ObjectInterface> getData(String name, DateTime start, DateTime end) throws SQLException, DopeDBException{
    return cq;
}
/**
 * 
 * @param contact2
 */
protected void processSingleQueueData(ObjectInterface contact2) {
}
/**
 * 
 * @param queueName
 * @throws SQLException
 */
protected void obtainNewData(String queueName) throws SQLException {

}

/**
 * 
 * @param name
 * @param start
 * @param end
 * @return
 */
protected boolean doIhaveIt(String name, DateTime start, DateTime end) {
    return false;
}
/**
 * 
 * @param start
 * @param end
 * @return
 */
protected boolean checkDatas(DateTime start, DateTime end) {
    return start.toDateMidnight().isEqual(end.toDateMidnight());
}
/**
 * 
 * @param start
 * @param end
 * @return
 */
protected Integer daysBetween(DateTime start, DateTime end) {
    return  end.dayOfYear().get()-start.dayOfYear().get();

}

正如eailer所说,这个类的目的是我们的开发人员将扩展这个类并重写这些方法,以便指导人员可以找到这些方法并使用它们,它们选择如何实现和填充方法,这与程序之间是不同的。
在这个程序中,statistic类如下所示:
public class Statistics extends StatisticPattern {
private DateTime start;
private DateTime end;


/**
 *  This class checks whether the program has already collected the data
 * @Override
 */
public ArrayList<ObjectInterface> getData(String name, DateTime start, DateTime end) throws DopeDBException{
    if (this.start.equals(start) && this.end.equals(end)) {
        if (name.equalsIgnoreCase("All")) {
            return cq;
        }else if (doIhaveIt(name, start, end)) {
            return cq;
        }
    }else {
        try {
            obtainNewData(name);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    return cq;
}
@Override
protected void obtainNewData(String queueName) throws SQLException {
    setDates(start, end);
    this.cq = p.obtainData(start, end, queueName);

}

如您所见,我已经创建了自己的statisticPattern方法实现,这个方法调用getData方法,然后从p(我们的provider类,也称为数据库连接)获取数据。
您可能已经猜到,provider类还实现了在obtainNewData方法中只有一个方法的接口。
public interface ProviderInterface {

public ArrayList<ObjectInterface> obtainData(DateTime start, DateTime end, String name) throws SQLException;

}
同样,开发人员必须实现这个方法,但可以根据自己的喜好填充它。这里最重要的是返回类型是objectinterface类型的arraylist:
public interface ObjectInterface {

HashMap<String, Integer> data = new HashMap<String, Integer>();
String type = "";

public String getType();
public void addData(String key, Integer value);
public Integer getData(Object key);

}
基本上,它必须实现一个hashmap,其中包含图表应该填充的所有数据。创建对象后,将添加此数据,然后将其添加到提供程序中的列表中,然后将返回此列表,并且控制器将其设置为ChartBuilders数据列表,然后该列表将填充图表。
在这种情况下,必须填充图表的最终对象如下所示:
public class ContactQueue implements ObjectInterface {

    private HashMap<String, Integer> data = new HashMap<String, Integer>();
    private String type;
    public ContactQueue(String type){
        this.type = type;
    }
    public String getType(){
        return type;
    }
    public void addData(String key, Integer value){
        if (data.containsKey(key)) {
            Integer i = data.get(key);
            data.put(key, value+i);
        }else {
            data.put(key, value);
        }

    }
    public Integer getData(Object key){
        return data.get(key);
    }
    public String toString(){
        return type;
    }
}

现在开始提问!
当只有一种类型的数据需要收集时,所有这些都可以完美地工作。但我目前正在开发的程序必须从5个不同的表中获取数据,所有这些表都必须添加到它们的每个图表中我的问题是如何设计它以便它选择数据库表?并返回该specefic表的列表?
我已经尝试了以下代码:
        if (name.equalsIgnoreCase("Besvarelse")) {
        return besvarelse25(start, end);
    }else if (name.equalsIgnoreCase("intern")) {
        return intern(start, end);
    }else if (name.equalsIgnoreCase("besvarelseProcent")) {
        return besvarelseProcent(start,end);
    }else if (name.equalsIgnoreCase("Email_data")) {
        return email_data(start, end);
    }else if (name.equalsIgnoreCase("Email_Hånd")) {
        return email_haand(start, end);
    }else if (name.equalsIgnoreCase("Email_Antal")) {
        return email_antal(start, end);
    }
    else if (name.equalsIgnoreCase("Henvendelser")) {
        return henvendelser(start, end);
    }

不过,至少可以说,这看起来有点累赘和丑陋。
我考虑过再次创建一个枚举,客户端(开发人员)每次创建新程序时都必须更改它,但我不确定这是正确的方法吗?
我也想听听你对整个项目的看法?我是成功了还是失败了?
感谢您的阅读,我期待您的回复

最佳答案

观点:由于您在最后似乎是基于后台数据库进行筛选,因此解决方案简单/优雅。是的,它是多余和丑陋的,但是有5个相似信息表的模式也是如此(如果我读得对的话)。如果成功的话,我认为你没有问题。
如果您担心的是需要选择“正确类型”的表,则可以找到每个表的通用质量:
类似->

  SELECT 
    generic.specificField AS "genericKey",
    ....
  FROM
    TableOne generic

然后,您可以创建一个hashmap(或对象,您的调用),以满足设计的某种程度的一致性。
又像->
  for(Field f : resultSet.values())//Pseudo Code, obviously javax.sql is a bit more complex
    hashMap.put(f.getName(), f.getValue());
...
  return genericProcessing(hashMap, start, end);

因为您知道键/方法(由sql别名定义),所以有一个简单的解决方法。然而,如果这是一个公共api,那么更“严格”(接口)的方法可能是更好的选择。
如果你的数据不相关,那么我认为你的设计反映了数据。这没什么问题。
(第二种观点是,上述工厂模式只是另一种抽象形式。Java生态系统中的很多人都喜欢它,很多人讨厌它——我在这里是第二个阵营)。一般来说,我会先把你的问题抽象出来,如果你不能抽象出来,那可能就够简单了。在你的例子中,我认为你可以用一个方法/查询来抽象它。如果你不能跳到一个类型(工厂是一种方式来做这件事)可能是你最好的答案。

关于java - 使数据库表选择尽可能静态而不使用字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13916456/

相关文章:

c# - 自动生成不可变类和匹配的构建器类

java - 将命令行参数存储在数组类中

java - 如何从 Intellij Idea 中的当前项目中删除所有未使用的导入

java - 如何在 Java 应用程序中嵌入迷你控制台?

database - 重构到 n 层

java - 我可以将 myBatis 配置为使用构建器模式创建类的实例吗?

java - 如果输入小写字母,我的十六进制到二进制转换器将为空

java - 以编程方式插入架构

mysql - "products can be made of many products"的数据库结构

rust - 如何在 Rust 中使用链式方法调用编写惯用的构建模式?