在我们的项目中,我们需要在没有任何数据库服务器的情况下评估SQL语句。你能建议任何能够评估基于数学的SQL语句并返回结果的免费Java库吗?
例如;
SELECT 2*2 AS RESULT
4
可能会被称为int result = SQLEvaluator.evaluate("SELECT 2*2 AS RESULT");
答案 0 :(得分:1)
您可以使用嵌入式Java专用数据库服务器,如Java Derby,HSQL或其他具有非持久性内存数据库的服务器。优点是存在真正的标准兼容引擎。
在Java Scripting API上可能会提供一个瘦包装器,因此您也可以使用变量和函数。
脚本的使用将是
public static void main(String[] args) {
ScriptEngineManager manager = new ScriptEngineManager();
for (ScriptEngineFactory factory : manager.getEngineFactories()) {
System.out.printf("language: %s, engine: %s%n", factory.getLanguageName(), factory.getEngineName());
}
ScriptEngine engine = manager.getEngineByName("SQL");
try {
Object result = engine.eval("SELECT 1+2;");
} catch (ScriptException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
}
}
为Java Scripting API实现SQL
使用文本文件为sqlscript.jar创建项目:
/META-INF/services/javax.script.ScriptEngineFactory
含有:
my.sqlscript.SQLScriptEngineFactory
例如,可以通过语言名称来发现引擎工厂类。 它提供了一个ScriptEngine用于评估。
package my.sqlscript;
public class SQLScriptEngineFactory implements ScriptEngineFactory {
@Override
public ScriptEngine getScriptEngine() {
return new SQLScriptEngine(this);
}
}
引擎可以完成工作。在这里我使用了HSQLDB,它在没有FROM的情况下遇到了SELECT问题,但使用JavaDB / Derby pr H2SQL可以做得更好。 并不是说可用的参数绑定也需要一点管道。
public class SQLScriptEngine extends AbstractScriptEngine {
private final SQLScriptEngineFactory factory;
public SQLScriptEngine(SQLScriptEngineFactory factory) {
this.factory = factory;
}
@Override
public Object eval(String script, ScriptContext context)
throws ScriptException {
StringBuilder sb = new StringBuilder(); // Multi-column/multi-row result
Object singleValue = null; // Single value result
Server hsqlServer = new Server();
try {
File dbFile = File.createTempFile("sqlscript", ".db");
String dbURL = dbFile.toURI().toURL().toString();
hsqlServer.setLogWriter(null);
hsqlServer.setSilent(true);
hsqlServer.setDatabaseName(0, "db1");
hsqlServer.setDatabasePath(0, dbURL);
} catch (IOException | MalformedURLException ex) {
throw new ScriptException(ex);
}
hsqlServer.start();
try {
Class.forName("org.hsqldb.jdbcDriver");
Connection connection =
DriverManager.getConnection("jdbc:hsqldb:hsql://localhost/db1", "sa", "");
try (PreparedStatement statement = connection.prepareStatement(script);
ResultSet rs = statement.executeQuery();) {
ResultSetMetaData meta = rs.getMetaData();
int columns = meta.getColumnCount();
int row = 1;
while (rs.next()) {
for (int column = 1; column <= columns; ++column) {
Object value = rs.getObject(column);
singleValue = row == 1 && column == 1? value : null;
sb.append(value);
if (column < columns) {
sb.append("\t");
}
}
sb.append("\n");
++row;
}
}
} catch (SQLException | ClassNotFoundException e2) {
Logger.getLogger(SQLScriptEngine.class.getName()).log(Level.SEVERE, null, e2);
}
hsqlServer.stop();
return singleValue != null ? singleValue : sb.toString();
}
}
您可以在工厂类中使连接更持久,并使用伪SQL语句shutdown
来显式关闭连接。
的结论强> 的
这是一个相对简单的抽象层,可以帮助重用。除了提供自己的课程外。
答案 1 :(得分:1)
可以使用ZQL来实现,如下面的代码所示。但我认真建议您选择一个简单的嵌入式数据库,例如H2(example here)并使用它(项目运行状况要高得多)。
public class H2ExpEval {
public static void main(String... args) throws Exception {
evaluateUsingH2("SELECT 2+2");
evaluateUsingH2("SELECT 3+7-5");
evaluateUsingH2("SELECT 2*2*2+1");
}
private static void evaluateUsingH2(String sql) throws Exception {
Class.forName("org.h2.Driver");
// opens an in-memory database: no files are saved and it's all quicker
Connection conn = DriverManager.getConnection("jdbc:h2:mem:");
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery(sql);
if (rs.next()) {
System.out.println(rs.getString(1));
}
stat.close(); conn.close();
}
}
输出:
4
5
9
要使用它,请将其添加到pom.xml
:
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.3.171</version>
</dependency>
public class ZqlEvalDemo {
public static void main(String args[]) throws Exception {
System.out.println(evaluate("SELECT 2+2 FROM RESULT;"));
System.out.println(evaluate("SELECT 3+7-5 FROM RESULT;"));
System.out.println(evaluate("SELECT 2*2*2+1 FROM RESULT;"));
}
private static ZqlParser p = new ZqlParser();
private static Object evaluate(String s) throws Exception {
p.initParser(new java.io.ByteArrayInputStream(s.getBytes()));
ZStatement st = p.readStatement();
ZSelectItem zSelectItem = ((ZQuery) st).getSelect().get(0);
ZExpression exp = (ZExpression) zSelectItem.getExpression();
return new ZEval().evalExpValue(new ZTuple(), exp);
}
}
输出:
4.0
5.0
9.0
对于依赖项,可以从ZQL Page下载,或者出于测试目的,将其添加到pom.xml
(测试目的,因为我们不知道谁维护了该存储库):
<dependencies>
<dependency>
<groupId>com.experlog</groupId>
<artifactId>zql</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>zql</id>
<name>zql</name>
<url>http://dbappserv.cis.upenn.edu:8080/artifactory/ext-releases-local</url>
</repository>
</repositories>