Excel 파일의 내용으로 임시 데이터베이스를 만드는 LinkResolver의 다음 초기 구현을 생각해 냈습니다. 임시 데이터베이스의 클로즈 처리 (close-handling) 및 임시 파일 제거 (temporary-file-removal)와 같은 몇 가지 사항이 여전히 부족하지만 기본 목적으로 작동하는 것으로 보입니다.
/**
* Sample LinkResolver which reads the data from an Excel file
* The data is read from the first sheet and needs to contain a
* header-row with column-names and then data-rows with string/numeric values.
*/
public class ExcelFileLinkResolver implements LinkResolver {
private final LinkResolver parentResolver;
private final String fileNameInDB;
private final String tableName;
private final File excelFile;
public ExcelFileLinkResolver(LinkResolver parentResolver, String fileNameInDB, File excelFile, String tableName) {
this.parentResolver = parentResolver;
this.fileNameInDB = fileNameInDB;
this.excelFile = excelFile;
this.tableName = tableName;
}
@Override
public Database resolveLinkedDatabase(Database linkerDb, String linkeeFileName) throws IOException {
if(linkeeFileName.equals(fileNameInDB)) {
// TODO: handle close or create database in-memory if possible
File tempFile = File.createTempFile("LinkedDB", ".mdb");
Database linkedDB = DatabaseBuilder.create(Database.FileFormat.V2003, tempFile);
try (Workbook wb = WorkbookFactory.create(excelFile, null, true)) {
TableBuilder tableBuilder = new TableBuilder(tableName);
Table table = null;
List<Object[]> rows = new ArrayList<>();
for(org.apache.poi.ss.usermodel.Row row : wb.getSheetAt(0)) {
if(table == null) {
for(Cell cell : row) {
tableBuilder.addColumn(new ColumnBuilder(cell.getStringCellValue()
// column-names cannot contain some characters
.replace(".", ""),
DataType.TEXT));
}
table = tableBuilder.toTable(linkedDB);
} else {
List<String> values = new ArrayList<>();
for(Cell cell : row) {
if(cell.getCellTypeEnum() == CellType.NUMERIC) {
values.add(Double.toString(cell.getNumericCellValue()));
} else {
values.add(cell.getStringCellValue());
}
}
rows.add(values.toArray());
}
}
Preconditions.checkNotNull(table, "Did not have a row in " + excelFile);
table.addRows(rows);
} catch (InvalidFormatException e) {
throw new IllegalStateException(e);
}
return linkedDB;
}
return parentResolver.resolveLinkedDatabase(linkerDb, linkeeFileName);
}
}
POI를 통해 관련 데이터에 액세스하는 것과 달리 Jackcess API를 통해 데이터를 구체적으로로드해야하는 이유가 있습니까? – jtahlborn
실제로 Access 데이터베이스에서 데이터를 읽으려는 경우 Excel 파일이 일부 쿼리에만 필요하며 Jackcess는 링크가 올바르게 해석되지 않고 실패합니다. – centic
나는 이해한다고 생각하지 않는다. Jackcess 내에서 "원격"테이블을 읽는 것을 피할 수는 없습니까? 또는 ucanaccess를 사용하여 여러 테이블로 실제 SQL 쿼리를 실행하고 있습니까? – jtahlborn