在SBT

时间:2015-12-10 23:49:14

标签: scala intellij-idea sbt h2

我有一个使用H2的Scala项目,我使用以下SQL创建一个触发器:

  s"""
     | CREATE TRIGGER $triggerName
     |    BEFORE UPDATE ON $inTable
     |    FOR EACH ROW
     |    AS $$$$org.h2.api.Trigger create() { return new org.project.database.LoggingTrigger("$onModifyColumn", "$logValueOfColumn", "$storeInColumn"); } $$$$;
   """

当我在IntellIJ下运行我的测试和/或应用程序时,触发器按预期工作(两者都成功创建并随后具有所需效果)。当我尝试从命令行(IntelliJ之外)在SBT下运行应用程序或测试时,出现以下错误:

[error]  org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "/org/h2/dynamic/trigger/TRIGGER_LXQX2FJ1UVEBCJ1GWRKFJQVTHEZYZTRB.java:6: error: package org.h2.api does not exist
[error]      public static org.h2.api.Trigger create() { return new org.project.database.LoggingTrigger(""last_error_message"", ""hostname"", ""last_error_host""); }
[error]                              ^
[error]  

/org/h2/dynamic/trigger/TRIGGER_LXQX2FJ1UVEBCJ1GWRKFJQVTHEZYZTRB.java:6: error: package org.project.database does not exist
    [error]      public static org.h2.api.Trigger create() { return new org.project.database.LoggingTrigger(""last_error_message"", ""hostname"", ""last_error_host""); }
           ^
[error]  2 errors
[error]  " [42000-187] (DbException.java:345)
[error] org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
[error] org.h2.message.DbException.get(DbException.java:179)
[error] org.h2.message.DbException.get(DbException.java:155)
[error] org.h2.util.SourceCompiler.throwSyntaxError(SourceCompiler.java:364)
[error] org.h2.util.SourceCompiler.javaxToolsJavac(SourceCompiler.java:288)
[error] org.h2.util.SourceCompiler$1.findClass(SourceCompiler.java:150)
[error] org.h2.util.SourceCompiler.getClass(SourceCompiler.java:164)
[error] org.h2.util.SourceCompiler.getMethod(SourceCompiler.java:178)
[error] org.h2.schema.TriggerObject.loadFromSource(TriggerObject.java:97)
[error] org.h2.schema.TriggerObject.load(TriggerObject.java:78)
[error] org.h2.schema.TriggerObject.setTriggerAction(TriggerObject.java:136)
[error] org.h2.schema.TriggerObject.setTriggerSource(TriggerObject.java:129)
[error] org.h2.command.ddl.CreateTrigger.update(CreateTrigger.java:117)
[error] org.h2.command.CommandContainer.update(CommandContainer.java:78)
[error] org.h2.command.Command.executeUpdate(Command.java:254)
[error] org.h2.jdbc.JdbcPreparedStatement.execute(JdbcPreparedStatement.java:198)

在两个上下文中记录java.class.path系统属性的值会产生非常不同的结果。从IntelliJ开始,这是一个非常长的路径,包括所有依赖JAR。来自SBT,它只是C:\Program Files (x86)\sbt\bin\sbt-launch.jar

我的猜测是SBT通过IntelliJ的一些不同机制来排序主进程的类路径。由于应用程序通常在SBT下运行,因此类路径上可以使用正确的依赖项。但是,显然存在一些差异(例如,在上面注销java.class.path时可见的那个),这会阻止主进程将正确的类路径传递给H2。

特别奇怪H2找不到自己的一个包。 org.h2.api.Trigger与上面的异常类型和抛出异常的代码在同一个JAR中。此依赖项正确包含在项目的Build.scala文件中。

2 个答案:

答案 0 :(得分:0)

SBT使用嵌套和委托类加载器的复杂层次结构来隔离构建的不同部分,并控制可见性和管理失败。

java.class.path系统属性在这里基本上无关紧要。如果你想了解这里使用的类路径/类加载器,你必须在调试器中捕获它并直接检查类加载器(你应该找到一个URLClassLoadersDualLoaders链。

  

使用H2的Scala项目

你可以扩展应用程序的哪个部分“使用”H2以及通过什么方式?我认为这将是你问题的关键。

答案 1 :(得分:0)

很确定您的库依赖项中有不必要的'%“ TEST”'。

您的build.sbt中可能有类似的内容:

libraryDependencies += "com.h2database" % "h2" % "1.3.161" % "TEST"

这将导致sbt在编译过程中失败;删除“%“ TEST”':

libraryDependencies += "com.h2database" % "h2" % "1.3.161"