3

我在 excel 文件(和 csv 文件)中有大量数据。数据需要放入数据库(mysql)中。但是,在它进入数据库之前需要对其进行处理。例如,如果第 1 列小于第 3 列,则将 4 添加到第 2 列。在持久化信息之前必须遵循很多规则。

完成这项任务需要遵循什么好的设计?(使用Java)

补充笔记

该过程需要自动化。从某种意义上说,我不必手动进入并更改数据。我们谈论的是数千行数据,每行包含 15 列信息。

目前,我建立了一种责任链设计。每个规则一个类(Java)。当一个规则完成时,它会调用以下规则。

更多信息

通常每个数据表大约有 5000 行。速度不是一个大问题,因为这种大输入并不经常发生。

我考虑过流口水,但我不确定任务是否足够复杂,流口水。

示例规则:

  1. 所有货币(特定列中的数据)不得包含货币符号。

  2. 类别名称必须统一(例如书柜 = 书柜)

  3. 参赛日期不能是未来日期

  4. 文本输入只能包含 [AZ 0-9 \s]

等等。
此外,如果任何一列信息无效,则需要在处理完成时报告(或者可能停止处理)。

我目前的解决方案有效。但是我认为还有改进的余地,所以我正在寻找关于如何改进以及其他人如何处理类似情况的理想。

我曾考虑过(非常简单地)使用drools,但我不确定这项工作是否足够复杂以利用drools。

4

8 回答 8

1

我觉得你的方法还可以。特别是如果您在每个处理器上使用相同的接口。

你也可以看看一些叫做 Drules 的东西,目前是 Jboss-rules。前段时间我将它用于我的应用程序的规则繁重的部分,我喜欢它的是业务逻辑可以用例如电子表格或 DSL 来表达,然后编译为 java(运行时,我认为有也是一个编译时选项)。它使规则更加简洁,因此更具可读性。它也很容易学习(2天左右)。

这是开源Jboss-rules的链接。在 jboss.com,如果更符合您公司的口味,您无疑可以购买官方维护的版本。

于 2008-10-11T15:51:36.080 回答
1

如果我不想一步完成(正如 Oli 提到的),我可能会使用管道和过滤器设计。由于您的规则相对简单,我可能会做几个基于委托的课程。例如(C# 代码,但 Java 应该非常相似......也许有人可以翻译?):

interface IFilter {
   public IEnumerable<string> Filter(IEnumerable<string> file) {
   }
}

class PredicateFilter : IFilter {
   public PredicateFilter(Predicate<string> predicate) { }

   public IEnumerable<string> Filter(IEnumerable<string> file) {
      foreach (string s in file) {
         if (this.Predicate(s)) {
            yield return s;
         }
      }
   }
}

class ActionFilter : IFilter {
  public ActionFilter(Action<string> action) { }

  public IEnumerable<string> Filter(IEnumerable<string> file) {
      foreach (string s in file) {
         this.Action(s);
         yield return s;
      }
  }
}

class ReplaceFilter : IFilter {
  public ReplaceFilter(Func<string, string> replace) { }

  public IEnumerable<string> Filter(IEnumerable<string> file) {
     foreach (string s in file) {
        yield return this.Replace(s);
     }
  }
}

从那里,您可以直接使用委托过滤器,也可以根据具体情况对它们进行子类化。然后,将它们注册到将它们通过每个过滤器的管道。

于 2008-10-11T21:30:53.777 回答
1

只需创建一个函数来执行每个规则,并为每个值调用每个适用的函数。我不明白这需要任何异国情调的架构。

于 2008-10-11T21:53:14.760 回答
0

每个规则一个类?真的吗?也许我不了解这些规则的数量或复杂性,但我会(半伪代码):

public class ALine {
    private int col1;
    private int col2;
    private int coln;
    // ...

    public ALine(string line) {
         // read row into private variables
         // ...

         this.Process();
         this.Insert();
    }

    public void Process() {
         // do all your rules here working with the local variables
    }

    public void Insert() {
        // write to DB
    }
}

foreach line in csv
    new ALine(line);
于 2008-10-11T15:29:56.390 回答
0

您为每个规则使用类的方法听起来确实有点重,但它的优点是在新规则出现时易于修改和扩展。

至于加载数据批量加载是要走的路。我已经阅读了一些信息,这些信息表明它可能比使用插入语句加载快 3 个数量级。你可以在这里找到一些关于它的信息

于 2008-10-11T15:33:14.340 回答
0

将数据批量加载到临时表中,然后使用 sql 应用您的规则。使用临时表,作为插入真实表的基础。删除临时表。

于 2008-10-11T15:35:59.437 回答
0

你可以看到所有不同的答案都来自他们自己的经验和观点。

由于我们对您系统中的复杂性和行数了解不多,因此我们倾向于根据我们之前所做的提供建议。

如果您想将实施范围缩小到 1/2 的解决方案,请尝试提供更多详细信息。

祝你好运

于 2008-10-11T17:53:20.923 回答
0

这可能不是您想听到的,无论如何都不是“有趣的方式”,但是有一种更简单的方法可以做到这一点。

So long as your data is evaluated line by line... you can setup another worksheet in your excel file and use spreadsheet style functions to do the necessary transforms, referencing the data from the raw data sheet. For more complex functions you can use the vba embedded in excel to write out custom operations.

I've used this approach many times and it works really well; its just not very sexy.

于 2008-10-13T16:06:11.683 回答