web-dev-qa-db-fra.com

Comment exécuter un fichier de script SQL en Java?

Je souhaite exécuter un fichier de script SQL en Java sans lire le contenu complet du fichier dans une requête volumineuse ni l'exécuter.

Existe-t-il un autre moyen standard?

33
Vladimir

Il n'y a pas de moyen portable de le faire. Vous pouvez exécuter un client natif en tant que programme externe, mais:

import Java.io.*;
public class CmdExec {

  public static void main(String argv[]) {
    try {
      String line;
      Process p = Runtime.getRuntime().exec
        ("psql -U username -d dbname -h serverhost -f scripfile.sql");
      BufferedReader input =
        new BufferedReader
          (new InputStreamReader(p.getInputStream()));
      while ((line = input.readLine()) != null) {
        System.out.println(line);
      }
      input.close();
    }
    catch (Exception err) {
      err.printStackTrace();
    }
  }
}
  • L'échantillon de code a été extrait de ici et modifié pour répondre à la question en supposant que l'utilisateur souhaite exécuter un fichier de script PostgreSQL.
19
Pablo Santa Cruz

Il existe un excellent moyen d’exécuter des scripts SQL à partir de Java sans les lire vous-même, tant que vous n’aurez pas une dépendance à ant A mon avis, une telle dépendance est très bien justifiée dans votre cas. Voici un exemple de code dans lequel la classe SQLExec réside dans ant.jar:

private void executeSql(String sqlFilePath) {
    final class SqlExecuter extends SQLExec {
        public SqlExecuter() {
            Project project = new Project();
            project.init();
            setProject(project);
            setTaskType("sql");
            setTaskName("sql");
        }
    }

    SqlExecuter executer = new SqlExecuter();
    executer.setSrc(new File(sqlFilePath));
    executer.setDriver(args.getDriver());
    executer.setPassword(args.getPwd());
    executer.setUserid(args.getUser());
    executer.setUrl(args.getUrl());
    executer.execute();
}
25
Ruslans Uralovs

Non, vous devez lire le fichier, le diviser en plusieurs requêtes, puis les exécuter individuellement (ou à l'aide de l'API de traitement par lots de JDBC).

Une des raisons est que chaque base de données définit sa propre manière de séparer les instructions SQL (certaines utilisent ;, d'autres /, certaines autorisent les deux ou même de définir votre propre séparateur).

5
Aaron Digulla

La bibliothèque Flyway est vraiment bonne pour cela:

    Flyway flyway = new Flyway();
    flyway.setDataSource(dbConfig.getUrl(), dbConfig.getUsername(), dbConfig.getPassword());
    flyway.setLocations("classpath:db/scripts");
    flyway.clean();
    flyway.migrate();

Cette analyse les emplacements pour les scripts et les exécute dans l'ordre. Les scripts peuvent être versionnés avec V01__name.sql. Ainsi, si seul le migrate est appelé, seuls ceux qui ne sont pas encore exécutés seront exécutés. Utilise une table appelée 'schema_version' pour garder la trace des choses. Mais vous pouvez aussi faire d’autres choses, voir la documentation: flyway .

L'appel de nettoyage n'est pas obligatoire, mais il est utile de démarrer à partir d'une base de données vierge . on m'a attrapé.

4
Stephen

Vous ne pouvez pas utiliser JDBC car il ne supporte pas. La solution consiste à inclure iBatis iBATIS est un cadre de persistance et appelle le constructeur Scriptrunner comme indiqué dans iBatis documentation.

Il n’est pas bon d’inclure un cadre de persistance très lourd comme ibatis afin d’exécuter un simple script SQL de toutes les manières possibles en utilisant la ligne de commande. 

$ mysql -u root -p db_name < test.sql
3
Srinivas M.V.

JDBC ne prenant pas en charge cette option, le meilleur moyen de résoudre ce problème consiste à exécuter des lignes de commande via le programme Java. Ci-dessous, un exemple pour postgresql:

private void executeSqlFile() {
     try {
         Runtime rt = Runtime.getRuntime();
         String executeSqlCommand = "psql -U (user) -h (domain) -f (script_name) (dbName)";
         Process pr = rt.exec();
         int exitVal = pr.waitFor();
         System.out.println("Exited with error code " + exitVal);
      } catch (Exception e) {
        System.out.println(e.toString());
      }
}
2
Raposo

L’outil externe le plus simple que j’ai trouvé qui soit également portable est jisql - https://www.xigole.com/software/jisql/jisql.jsp . Vous l’exécuteriez de la manière suivante:

Java -classpath lib/jisql.jar:\
          lib/jopt-simple-3.2.jar:\
          lib/javacsv.jar:\
           /home/scott/postgresql/postgresql-8.4-701.jdbc4.jar 
    com.xigole.util.sql.Jisql -user scott -password blah     \
    -driver postgresql                                       \
    -cstring jdbc:postgresql://localhost:5432/scott -c \;    \
    -query "select * from test;"
1
raisercostin

JDBC ne prend pas en charge cette option (bien qu'un pilote de base de données puisse l'offrir) . Quoi qu'il en soit, le chargement de tout le contenu du fichier en mémoire ne devrait pas poser de problème.

0
Itay Maman

Essayez ce code:

String strProc =
         "DECLARE \n" +
         "   sys_date DATE;"+
         "" +
         "BEGIN\n" +
         "" +
         "   SELECT SYSDATE INTO sys_date FROM dual;\n" +
         "" +
         "END;\n";

try{
    DriverManager.registerDriver ( new Oracle.jdbc.driver.OracleDriver () );
    Connection connection = DriverManager.getConnection ("jdbc:Oracle:thin:@your_db_IP:1521:your_db_SID","user","password");  
    PreparedStatement psProcToexecute = connection.prepareStatement(strProc);
    psProcToexecute.execute();
}catch (Exception e) {
    System.out.println(e.toString());  
}
0
nabil