Java 在不使用字符串的情况下尽可能使数据库表选择静态

Java 在不使用字符串的情况下尽可能使数据库表选择静态,java,database,builder-pattern,Java,Database,Builder Pattern,首先,这个问题会有点长,但为了完整地解释我的问题,我觉得我必须给你很多关于我的项目的信息,所以请容忍我 我在一家经常使用图表的公司工作,为了避免总是需要从SCAT创建图表的麻烦,我决定创建一个新的java项目,并创建一个“包”,我和我的同事可以使用它来创建这些图表。你可以称之为泛型 所以这个项目使用了一个构建器模式和大量的接口和抽象类。其思想是,客户机(开发人员)使用这些接口、模式和类,并重写方法以适应流程。客户机(开发人员)剩下的唯一一件事就是填充这些方法,创建自己的UI并发布程序 这个项目进

首先,这个问题会有点长,但为了完整地解释我的问题,我觉得我必须给你很多关于我的项目的信息,所以请容忍我

我在一家经常使用图表的公司工作,为了避免总是需要从SCAT创建图表的麻烦,我决定创建一个新的java项目,并创建一个“包”,我和我的同事可以使用它来创建这些图表。你可以称之为泛型

所以这个项目使用了一个构建器模式和大量的接口和抽象类。其思想是,客户机(开发人员)使用这些接口、模式和类,并重写方法以适应流程。客户机(开发人员)剩下的唯一一件事就是填充这些方法,创建自己的UI并发布程序

这个项目进展顺利,我创造了很多我非常自豪的功能(因为我是一名学生)。我认为我已经很好地规划了整个过程,但是我遇到了一些问题

首先,让我向您展示这些类,并解释数据流(我会尽可能简短地这样做):

首先是GUI(这是一个用户必须自己创建的类,但用户可以使用内置包通过以下代码创建图表):

有了这个,导演现在准备制作一张图表

PeroidSelection.Hour是一个枚举,它设置了一个标准时间。在这种情况下,它将图表类别轴设置为我们的开始时间,因此收集的数据知道它必须每小时获取数据(在这种情况下为8.00-19.00)这是一个枚举的原因是,这些时段类型是最后一种,唯一可以改变的是我们的营业日和营业时间,我们可以很容易地改变!以下是
周期选择枚举的预览:

    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;
    }
}
进入控制器后,控制器现在已准备好构建图表,但首先必须从数据库中收集数据:

    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();
}
正如您所看到的,构建器是以某种方式构建的,这是因为图表由一个表和一个图表组成,并且这两个必须链接在一起,我不会在图表上详细介绍,因为它与我的问题无关

现在,
buildTypeOne
方法的第一行显示的stat类扩展了名为
statisticPattern
的抽象类,如下所示:

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();

}
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);

}
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;
    }
}
}

同样,开发人员必须实现这个方法,但可以根据自己的喜好填充它。这里最重要的是返回类型是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);
然而,这似乎有点多余,至少可以说是丑陋的

我曾经考虑过再次创建一个枚举,客户机(开发人员)每次想要创建一个新程序时都必须进行更改,但我不确定这是否是正确的方法

我也想听听你对整个项目的看法?我成功了还是失败了


感谢您的阅读,我将期待着阅读您的回复

老实说,我没有完整阅读操作,而是直接进入了问题。道歉…
任何时候您都有这样的代码:

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);
    }  

考虑使用。工厂模式是这种情况下的标准方式(请参阅抽象工厂)

观点:因为您似乎在最后根据后台数据库进行筛选,所以解决方案简单/优雅。是的,它是冗余的和丑陋的,但是有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生态系统中的很多人都喜欢它,而且非常讨厌它——我在这里是第二阵营)。一般来说,我会先把你的问题抽象出来,如果你不能抽象出来,那可能就足够简单了。在您的情况下,我认为您可能可以使用方法/查询来抽象它。如果你做不到,那么跳到一种类型(工厂就是这样做的一种方式)可能是你最好的答案。

我不太确定这个问题与什么有关。这个
if
语句在哪个类的实现中?我猜它是由开发人员实现的,开发人员实现了一个合适的
提供者
?@Stephan在这个程序中实现了获取的数据约束if/else语句您能解释一下在这种情况下您将如何做到这一点吗?工厂不是用来创建对象而不是方法的吗?所有这些if/else语句都与使用不同表并以不同方式创建相同类型对象的方法相连接?你能举一个例子,说明你在了解这一点的同时如何实现这样的模式吗?你应该设计每个类来负责一件事。不要让同一个类负责很多事情,在您的情况下,多个方法访问不同的表。以这种方式重构代码,它将自然地适应工厂模式问题是,从数据库中获取的数据并不总是相同的有时我必须计算数据的百分比,有时我必须获取原始数据而不进行处理,那么您建议我在mi中如何处理这些数据
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);
    }  
  SELECT 
    generic.specificField AS "genericKey",
    ....
  FROM
    TableOne generic
  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);