2010-05-25 2 views
5

MySQL 스키마를 파싱하기위한 자바 라이브러리가 있는지 여부를 아는 사람이 있습니까? 코드에서 스키마에 지정된 테이블과 필드를 결정할 수 있기를 원합니다. 아니면 내 것을 쓸 필요가 있을까요?Java 스키마 파서?

감사합니다.

편집 : 그냥 피하려고 다시 발명 불필요하게 바퀴를 :)

+0

당신이 그것을 필요에 따라 오히려 간단한 방법으로 그 일을하는 방법이있을 수 있습니다에 대한. 그러면이 응용 프로그램은 무엇이 될까요? 그렇지 않으면 http://stackoverflow.com/questions/660609/sql-parser-library-for-java를 참조하십시오. – bobah

+0

@bobah - ok 예 http://stackoverflow.com/questions/660609/sql-parser- library-for-java에는 해답이 있습니다 (예 : jsqlparser). 덕분에 –

답변

2

내 자신의 질문에 대답 :이 개별 문이 아닌 스키마에서 발견되는 등 여러 문을 구문 분석 http://jsqlparser.sourceforge.net/

jsqlparser를 사용하여

오전. 그래서 ';'에 스키마를 나눕니다. 또한 ''문자를 좋아하지 않으므로이를 제거해야합니다. 코드는 특정 테이블에 대한 열 이름을 얻을 수 있습니다 :

public class BUDataColumnsFinder { 

public static String[] readSql(String schema) throws IOException { 
    BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(schema))); 
    String mysql = ""; 
    String line; 
    while ((line = br.readLine()) != null) { 
     mysql = mysql + line; 
    } 
    br.close(); 
    mysql = mysql.replaceAll("`", ""); 
    return mysql.split(";"); 
} 

public static List<String> getColumnNames(String tableName, String schemaFile) throws JSQLParserException, IOException { 

    CCJSqlParserManager pm = new CCJSqlParserManager(); 
    List<String> columnNames = new ArrayList<String>(); 

    String[] sqlStatements = readSql(schemaFile); 

    for (String sqlStatement : sqlStatements) { 

     Statement statement = pm.parse(new StringReader(sqlStatement)); 

     if (statement instanceof CreateTable) { 

      CreateTable create = (CreateTable) statement; 
      String name = create.getTable().getName(); 

      if (name.equalsIgnoreCase(tableName)) { 
       List<ColumnDefinition> columns = create.getColumnDefinitions(); 
       for (ColumnDefinition def : columns) { 
        columnNames.add(def.getColumnName()); 
       } 
       break; 
      } 
     } 
    } 

    return columnNames; 
} 


public static void main(String[] args) throws Exception { 

    String schemaFile = "/home/john/config/bu-schema.sql"; 

    String tableName = "records"; 

    List<String> columnNames = BUDataColumnsFinder.getColumnNames(tableName, schemaFile); 

    for (String name : columnNames) { 
     System.out.println("name: " + name); 
    } 

} 

} 
1

왜 그냥 테이블과 열을 찾아 DatabaseMetaData의를 사용할 수 있습니까? 이것은 SQL로 표현 된 스키마가 연결된 데이터베이스에 대해 실행되었다고 추측하지만, 이는 만족하기 어려운 가정은 아닙니다.

데이터가 CSV 형식 인 경우 MySQL에서 데이터를 가져올 수 있습니다. 그런 일을하기 위해 Java 코드를 작성하기 전에 MySQL 도구에 대해 더 깊이 파고들 수 있습니다. 그래도 작동하지 않으면 ETL 도구를 사용하여 도움을받을 수 있습니다. Java를 작성하는 것이 최후의 해결책이 될 것입니다.

+0

불행히도이 코드는 (현재) 데이터베이스가 빌드되기 전에 실행됩니다. 그러나, 어쩌면 물건의 순서를 변경할 수 있습니다. 팁을 주셔서 감사합니다. –

+1

Java 코드가 데이터베이스를 만들어야하고 (그렇게해서는 안되는 경우가 아니라면) SQL DDL을 구문 분석해야한다고 생각하지 않습니다. – duffymo

+0

아니요, DB를 만들지 않습니다. 그것이하고있는 일은 스키마에 정의 된 열을 가진 db 가져 오기를위한 파일을 생성하는 것입니다.이 값은이 열을 포함하는 소스 데이터 파일에서 가져온 값과 정적 인 순서가 아닌 다른 많은 열을 포함합니다. –

0

당신은 알리바바의 Druid project에서 코드를 사용하는 것이 좋습니다. 정교한 연결 풀링 라이브러리로 설계되었지만이 프로젝트는 MySQL, Oracle, SQL Server 등과 같은 ANSI SQL 및 ANSI 이외의 언어에 대해 매우 고급 인 parser and AST을 지원합니다. 프로젝트는 오픈 소스이며 매우 자유로운 Apache License Version 2.0을 지닙니다.

라이브러리의이 부분에 대한 주요 진입 점은 SQLUtils.java입니다. 당신은 문장의 형식화 된 모델에 액세스 할 수 SQLUtils.parseStatements에서 반환 된 값을 사용할 수 있습니다

List<SQLStatement> statements = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL); 
for (SQLStatement statement : statements) { 
    if (statement instanceof MySqlCreateTableStatment) { 
     MySqlCreateTableStatment createTable = (MySqlCreateTableStatment) statement; 
     // Use methods like: createTable.getTableSource() 
    } 
}