1

我需要使用 Java 和 Hibernate 将值由管道 ( | ) 分隔的文本文件导入到数据库中。文本文件在别处生成,并具有以下布局:

示例文件.txt

|0150|A|B|C|
|0150|X|Y|Z|
|0190|1|2|
|0200|9|8|7|H|F|E|
  • 每行对应一个记录。
  • 第一个值(即 0150、0190、0200)是它保存的信息类型(应该存储到哪个表中)。
  • 其余的是要存储在该表中的值。

到目前为止,我已经能够阅读这些行,找到记录对应的对象 - 使用工厂模式 - 将值分成 String[] 数组并调用方法 createInstance(String[] fields) 来创建对象并将其存储到数据库中 - 使用模板模式:

导入服务接口

public interface ImportServiceInterface {
    public void createInstance(String[] fields);
}

抽象导入服务

public abstract class AbstractImportService implements ImportServiceInterface {
    public static ImportServiceInterface getImportService(String line) {
       // returns the correct subclass
    }

    public void import() {
        createInstance(splitFields());
    }

    public String[] splitFields(String line) {
        // splits the line
    }
}

所以我有 3 个独立的服务,每个服务都实现自己的 createInstance(String[] fields) 版本:

ImportExampleTypeService

public ImportExampleTypeService implements AbstractImportService {
    public void createInstance(String[] fields) {
        ExampleModel myExample = new myExampleModel(); // mapped with Hibernate
        // find which object members corresponds to the fields
        // call the DAO to store the object
    }
}

我的问题是用户将能够指定他自己的布局:值对应的字段、大小和位置。

我考虑过创建一个表来存储布局,然后使用反射匹配属性的名称。

但我一定错过了一些东西,也许有更简单的方法可以做到这一点?

4

3 回答 3

1

SuperCSV通过反射支持自定义分隔符和 java 对象的填充,所以我认为在这种情况下它会为你完成大部分工作。

此外,它支持将标题行的概念作为文件中的第一行,然后定义这些列在 java 对象中映射到哪些字段,或者您可以手动自定义列映射。

于 2013-06-28T21:51:42.683 回答
1

谢谢@increment1 和@Templar 的回答!

要求发生了变化。系统必须能够导入上述格式(不是用户定义的)和用户定义的、类似 CSV 的平面文件,每个文件只有一种记录类型。它让我的生活更轻松。我一直在查看不同的平面文件解析库,我将其发布在这里,以防有人偶然发现同样的问题:

  • jflat:简单易用、可扩展和可定制的框架。可能是大多数人的最佳选择。
  • BeanIO:一个平面文件编组器/解组器,它使用 xml 文件来确定如何解析文件。支持多种格式,每个文件不止一种类型的记录等。
  • FFP:平面文件解析。还支持绝对和相对定义,使用 POJO 而不是 xml 文件。我会选择这个,但它似乎已经死了?
  • 扁虫:与BeanIO非常相似。似乎它启发了 BeanIO,而且在扁虫上也没有太多的活动......

我选择了 BeanIO,因为它的灵活性更适合我的项目。所以这就是我要做的:

1) 保留我的设计,根据需要实现我的 createInstance() 方法;

2) 对用户定义的文件使用不同的实现,使用 BeanIO;

3) 使用 Facade 调用我需要的解析器:

外观接口

public interface ImportFacadeInterface {
    public void importFile();
}

ImportDefaultLayoutFacadeImpl

public class ImportDefaultLayoutFacadeImpl implements ImportFacadeInterface {
    public void importFile() {
        // use the ImportServiceInterface
    }
}

ImportUserDefinedLayoutFacadeImpl

public class ImportUserDefinedLayoutFacadeImpl implements ImportFacadeInterface {
    public void importFile() {
        // use BeanIO
    }
}
于 2013-07-04T12:49:07.550 回答
0

我存储可能的记录结构的方法是使用|0150|作为键和|A|B|C|值的映射。这可能是解析一行的方法。

String line = ...;
String structure = map.get(line.substring(1, 4));
// Now you have the line structure and can parse it into your own format. 
于 2013-06-28T21:17:57.083 回答