You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

H2嵌入式模式下Trigger类找不到问题及Maven类路径配置咨询

H2触发器类找不到问题解决(VSCode Maven项目)

问题场景

创建了继承org.h2.api.Trigger的自定义触发器类com.gamebad.storagemanager.data.triggers.MyTrigger,执行以下SQL创建触发器:

CREATE TABLE IF NOT EXISTS TEST(NAME CHARACTER VARYING(255))

CREATE TRIGGER IF NOT EXISTS MY_TRIGGER
ON TEST BEFORE INSERT FOR EACH ROW
CALL 'com.gamebad.storagemanager.data.triggers.MyTrigger'

在VSCode中直接运行Maven项目时,出现类找不到错误:

org.h2.jdbc.JdbcSQLSyntaxErrorException: Error creating or initializing trigger "MY_TRIGGER" object, class "com.gamebad.storagemanager.data.triggers.MyTrigger", cause: "org.h2.message.DbException: Class ""com.gamebad.storagemanager.data.triggers.MyTrigger"" not found [90086-224]"; see root cause for details; SQL statement:
CREATE TRIGGER IF NOT EXISTS "PUBLIC"."MY_TRIGGER"
BEFORE INSERT 
ON "PUBLIC"."TEST"
FOR EACH ROW
CALL "com.gamebad.storagemanager.data.triggers.MyTrigger" [90043-232]
        at com.h2database@2.3.232/org.h2.message.DbException.getJdbcSQLException(DbException.java:644)
        at com.h2database@2.3.232/org.h2.engine.SessionRemote.readSQLException(SessionRemote.java:663)
        at com.h2database@2.3.232/org.h2.engine.SessionRemote.readException(SessionRemote.java:646)
        at com.h2database@2.3.232/org.h2.engine.SessionRemote.done(SessionRemote.java:620)
        at com.h2database@2.3.232/org.h2.command.CommandRemote.executeUpdate(CommandRemote.java:225)
        at com.h2database@2.3.232/org.h2.jdbc.JdbcPreparedStatement.execute(JdbcPreparedStatement.java:262)
        at com.gamebad.storagemanager/com.gamebad.storagemanager.data.DatabaseController.lambda$6(DatabaseController.java:117)
        at com.gamebad.storagemanager/com.gamebad.storagemanager.data.DatabaseController.lambda$2(DatabaseController.java:81)
        at com.gamebad.storagemanager/com.gamebad.storagemanager.data.DatabaseController.execute(DatabaseController.java:65)
        at com.gamebad.storagemanager/com.gamebad.storagemanager.data.DatabaseController.execute(DatabaseController.java:78)
        at com.gamebad.storagemanager/com.gamebad.storagemanager.data.DatabaseController.execute(DatabaseController.java:76)
        at com.gamebad.storagemanager/com.gamebad.storagemanager.data.DatabaseController.execute(DatabaseController.java:75)
        at com.gamebad.storagemanager/com.gamebad.storagemanager.data.DatabaseController.execute(DatabaseController.java:117)
        at com.gamebad.storagemanager/com.gamebad.storagemanager.Main.test(Main.java:49)
        at com.gamebad.storagemanager/com.gamebad.storagemanager.Main.main(Main.java:172)

但将项目打包为包含所有依赖的单个Jar包后运行正常,能正确加载触发器类。

原因

VSCode直接运行项目时,H2的类加载器与应用程序的类加载器隔离,无法访问到项目编译后的自定义触发器类;而打包成fat jar后,所有类都在同一Jar包内,类加载器能统一加载所有类。

解决方案

1. 使用Maven exec插件统一类路径

在pom.xml中添加exec-maven-plugin配置,确保运行时类路径包含项目编译类和所有依赖:

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>3.1.0</version>
            <configuration>
                <!-- 替换为你的主类全路径 -->
                <mainClass>com.gamebad.storagemanager.Main</mainClass>
                <includeProjectDependencies>true</includeProjectDependencies>
                <includePluginDependencies>false</includePluginDependencies>
                <classpathScope>compile</classpathScope>
            </configuration>
        </plugin>
    </plugins>
</build>

配置完成后,在VSCode的Maven面板中执行exec:java命令运行项目,而非直接运行Main类。

2. 指定H2使用应用类加载器

在建立H2连接时,添加CLASS_LOADER参数,指定H2使用应用中的某个类的类加载器来加载触发器:

// 替换为你的H2连接URL,CLASS_LOADER值为主类全路径
String url = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;CLASS_LOADER=com.gamebad.storagemanager.Main";
Connection conn = DriverManager.getConnection(url, "sa", "");

3. 查看当前运行类路径

如果需要验证类路径是否正确,可在代码中添加以下代码打印当前类路径:

ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
if (contextClassLoader instanceof URLClassLoader urlClassLoader) {
    for (URL url : urlClassLoader.getURLs()) {
        System.out.println("类路径项: " + url.getFile());
    }
}

也可以在VSCode的运行配置中添加-verbose:class参数,启动时会打印所有类的加载来源,方便排查类加载问题。

内容的提问来源于stack exchange,提问作者Ibrahim Rashwan El-Gebaly

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 03:05:19