Как выполнить файл сценария SQL в Java?
Я хочу выполнить файл сценария SQL на Java без чтения всего содержимого файла в большой запрос и его выполнения.
есть ли другой стандартный способ?
9 ответов
нет переносимый способ сделать это. Вы можете выполнить собственный клиент как внешнюю программу, чтобы сделать это, хотя:
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();
}
}
}
- пример кода был извлечен из здесь и изменен, чтобы ответить на вопрос, предполагая, что пользователь хочет выполнить файл сценария с PostgreSQL.
существует отличный способ выполнения SQL-скриптов с Java, не читая их самостоятельно, пока вы не возражаете иметь зависимость от Ant. На мой взгляд, такая зависимость очень хорошо оправдана в вашем случае. Вот пример кода, где класс SQLExec живет в 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();
}
нет, вы должны прочитать файл, разделить его на отдельные запросы, а затем выполнить их по отдельности (или с помощью пакетного API JDBC).
одна из причин заключается в том, что каждая база данных определяет свой собственный способ разделения операторов SQL (некоторые используют ;
, другие /
, некоторые позволяют одновременно или даже определить свой собственный разделитель).
вы не можете использовать JDBC, поскольку он не поддерживает . Работа вокруг будет включать в себя iBatis iBATIS-это структура персистентности и вызов Scriptrunner
конструктор как показано в iBatis документация .
нехорошо включать тяжелую структуру персистентности, такую как ibatis, чтобы запускать простые сценарии sql любыми способами, которые вы можете сделать с помощью командной строки
$ mysql -u root -p db_name < test.sql
библиотека Flyway действительно хороша для этого:
Flyway flyway = new Flyway();
flyway.setDataSource(dbConfig.getUrl(), dbConfig.getUsername(), dbConfig.getPassword());
flyway.setLocations("classpath:db/scripts");
flyway.clean();
flyway.migrate();
это сканирует местоположения для сценариев и запускает их по порядку. Скрипты могут быть версионными с именем V01__.sql, поэтому, если вызывается только миграция, будут выполняться только те, которые еще не запущены. Использует таблицу под названием "schema_version" для отслеживания вещей. Но может делать и другие вещи, см. документы:flyway.
чистый вызов не требуется, но полезно начать с чистого DB. Также следует учитывать местоположение (по умолчанию "classpath: db/migration"), нет места после":", который поймал меня.
поскольку JDBC не поддерживает эту опцию, лучшим способом решить этот вопрос является выполнение командных строк через программу Java. Ниже приведен пример для 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());
}
}
самый простой внешний инструмент, который я нашел, который также переносим, - jisql -https://www.xigole.com/software/jisql/jisql.jsp . Вы бы запустили его как:
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;"
JDBC не поддерживает эту опцию (хотя конкретный драйвер БД может предложить это). Во всяком случае, не должно быть проблем с загрузкой всего содержимого файла в память.
попробуйте этот код:
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());
}