设置 LOG 后,为什么 h2 在第一次连接时忽略 slf4j 消息?
Why does h2 ignore slf4j messages on the first connection when LOG is set?
请参阅下面的示例代码和输出(标准输出上有 Slf4j/logback)。我找不到任何关于此的错误报告。我正在使用内存模式的 h2 版本 1.3.176(最后稳定版)。为 LOG(0、1 或 2)设置什么值似乎无关紧要,但必须设置。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class H2TraceTest {
public static void main(String[] args) throws SQLException {
System.out.println("Query connection 1");
Connection myConn = DriverManager.getConnection("jdbc:h2:mem:tracetest;TRACE_LEVEL_FILE=4;LOG=2");
myConn.createStatement().execute("SELECT 1");
System.out.println("Query connection 2");
DriverManager.getConnection("jdbc:h2:mem:tracetest").createStatement().execute("SELECT 1");
System.out.println("Query connection 1 again");
myConn.createStatement().execute("SELECT 1");
System.out.println("End");
}
}
输出:
Query connection 1
Query connection 2
16:17:02.955 INFO h2database - jdbc[3]
/**/Connection conn2 = DriverManager.getConnection("jdbc:h2:mem:tracetest", "", "");
16:17:02.958 DEBUG h2database - jdbc[3]
/**/Statement stat2 = conn2.createStatement();
16:17:02.959 DEBUG h2database - jdbc[3]
/**/stat2.execute("SELECT 1");
16:17:02.959 INFO h2database - jdbc[3]
/*SQL #:1*/SELECT 1;
Query connection 1 again
End
我知道 H2 documentation 关于 TRACE_LEVEL_FILE
的说法:它影响所有连接。但这不(完全)正确:
每个连接都保留对日志系统的惰性引用。如果您使用特殊标记 TRACE_LEVEL_FILE=4
更改它,那么该引用不会针对所有现有连接进行更改 - 但仅针对那些在该更改后进行首次日志记录的人。
因此,如果您使用连接字符串 "jdbc:h2:mem:tracetest;TRACE_LEVEL_FILE=4"
,一切都如预期的那样,因为您的会话在更改日志系统之前不会写入任何日志消息。不幸的是,jdbc:h2:mem:tracetest;TRACE_LEVEL_FILE=4;LOG=2
中的 LOG=2
首先被评估,因为这两个参数都被写入和读取无序的 Map
。并且因为 LOG=2
正在生成日志语句,所以对日志适配器 (=4) 的引用永远不会应用于当前会话。只到下一个。
你能做什么:
- 仅使用
"jdbc:h2:mem:tracetest;TRACE_LEVEL_FILE=4"
- LOG=2
无论如何都是默认值。如果您需要任何其他日志模式,您可以使用 connection.createStatement().executeUpdate("SET LOG 1")
- 向连接字符串添加一些默认参数,直到
TRACE_LEVEL_FILE
参数成为映射中的第一个参数(不太可靠,因为顺序可能取决于 VM)
- 立即放弃第一个连接
- 填写错误报告并等待修复(或自己修复),因为我认为这是某种错误
我知道这是一个老问题,但这里有一个可靠的方法(即您可以确保先将 TRACE_LEVEL_FILE
设置为 4
:
String url = "jdbc:h2:mem:tracetest;INIT=SET TRACE_LEVEL_FILE=4\;SET DB_CLOSE_DELAY=-1/* for example, i.e. do other stuff */";
请参阅下面的示例代码和输出(标准输出上有 Slf4j/logback)。我找不到任何关于此的错误报告。我正在使用内存模式的 h2 版本 1.3.176(最后稳定版)。为 LOG(0、1 或 2)设置什么值似乎无关紧要,但必须设置。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class H2TraceTest {
public static void main(String[] args) throws SQLException {
System.out.println("Query connection 1");
Connection myConn = DriverManager.getConnection("jdbc:h2:mem:tracetest;TRACE_LEVEL_FILE=4;LOG=2");
myConn.createStatement().execute("SELECT 1");
System.out.println("Query connection 2");
DriverManager.getConnection("jdbc:h2:mem:tracetest").createStatement().execute("SELECT 1");
System.out.println("Query connection 1 again");
myConn.createStatement().execute("SELECT 1");
System.out.println("End");
}
}
输出:
Query connection 1
Query connection 2
16:17:02.955 INFO h2database - jdbc[3]
/**/Connection conn2 = DriverManager.getConnection("jdbc:h2:mem:tracetest", "", "");
16:17:02.958 DEBUG h2database - jdbc[3]
/**/Statement stat2 = conn2.createStatement();
16:17:02.959 DEBUG h2database - jdbc[3]
/**/stat2.execute("SELECT 1");
16:17:02.959 INFO h2database - jdbc[3]
/*SQL #:1*/SELECT 1;
Query connection 1 again
End
我知道 H2 documentation 关于 TRACE_LEVEL_FILE
的说法:它影响所有连接。但这不(完全)正确:
每个连接都保留对日志系统的惰性引用。如果您使用特殊标记 TRACE_LEVEL_FILE=4
更改它,那么该引用不会针对所有现有连接进行更改 - 但仅针对那些在该更改后进行首次日志记录的人。
因此,如果您使用连接字符串 "jdbc:h2:mem:tracetest;TRACE_LEVEL_FILE=4"
,一切都如预期的那样,因为您的会话在更改日志系统之前不会写入任何日志消息。不幸的是,jdbc:h2:mem:tracetest;TRACE_LEVEL_FILE=4;LOG=2
中的 LOG=2
首先被评估,因为这两个参数都被写入和读取无序的 Map
。并且因为 LOG=2
正在生成日志语句,所以对日志适配器 (=4) 的引用永远不会应用于当前会话。只到下一个。
你能做什么:
- 仅使用
"jdbc:h2:mem:tracetest;TRACE_LEVEL_FILE=4"
-LOG=2
无论如何都是默认值。如果您需要任何其他日志模式,您可以使用connection.createStatement().executeUpdate("SET LOG 1")
- 向连接字符串添加一些默认参数,直到
TRACE_LEVEL_FILE
参数成为映射中的第一个参数(不太可靠,因为顺序可能取决于 VM) - 立即放弃第一个连接
- 填写错误报告并等待修复(或自己修复),因为我认为这是某种错误
我知道这是一个老问题,但这里有一个可靠的方法(即您可以确保先将 TRACE_LEVEL_FILE
设置为 4
:
String url = "jdbc:h2:mem:tracetest;INIT=SET TRACE_LEVEL_FILE=4\;SET DB_CLOSE_DELAY=-1/* for example, i.e. do other stuff */";