跳到主要内容

高级特性

本节介绍 JdbcTemplate 的一些高级特性和相关参数:

打印错误日志和SQL

通过设置 printStmtError 参数在遇到 SQL 报错时打印报错的 SQL。

  • 属性名:printStmtError
  • 默认值:false,表示不打印日志。
例如:在 printStmtError = true 后
Failed SQL statement [select * from test_user2 where id > 10].
java.sql.SQLSyntaxErrorException: Table 'devtester.test_user2' doesn't exist
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.StatementImpl.executeQuery(StatementImpl.java:1200)
at com.zaxxer.hikari.pool.ProxyStatement.executeQuery(ProxyStatement.java:110)
at com.zaxxer.hikari.pool.HikariProxyStatement.executeQuery(HikariProxyStatement.java)
at net.hasor.dbvisitor.jdbc.core.JdbcTemplate.lambda$query$14(JdbcTemplate.java:468)
at net.hasor.dbvisitor.jdbc.core.JdbcTemplate.lambda$execute$0(JdbcTemplate.java:240)
at net.hasor.dbvisitor.jdbc.core.JdbcConnection.execute(JdbcConnection.java:162)
at net.hasor.dbvisitor.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:237)
at net.hasor.dbvisitor.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:467)
at net.hasor.dbvisitor.jdbc.core.JdbcTemplate.queryForList(JdbcTemplate.java:581)
at com.example.demo.jdbc.Execute1SqlMain.main(Execute1SqlMain.java:24)

来自数据库的警告消息

通过设置 ignoreWarnings,dbVisitor 将在 SQL 警告时抛出异常。

  • 属性名:ignoreWarnings
  • 默认值:true,表示忽略 SQL 告警。
MySQL 8.0 触发告警的 SQL
create table test_table (
id bigint,
name national char(10)
)
告警内容
NATIONAL/NCHAR/NVARCHAR implies the character set UTF8MB3, which will be replaced by UTF8MB4 in a future release. 
Please consider using CHAR(x) CHARACTER SET UTF8MB4 in order to be unambiguous.
在 ignoreWarnings = false 时
Exception in thread "main" java.sql.SQLException: Warning not ignored
at net.hasor.dbvisitor.jdbc.core.JdbcConnection.handleWarnings(JdbcConnection.java:225)
at net.hasor.dbvisitor.jdbc.core.JdbcConnection.lambda$execute$0(JdbcConnection.java:182)
at net.hasor.dbvisitor.jdbc.core.JdbcConnection.execute(JdbcConnection.java:162)
at net.hasor.dbvisitor.jdbc.core.JdbcConnection.execute(JdbcConnection.java:176)
at net.hasor.dbvisitor.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:229)
at com.example.demo.jdbc.Execute1SqlMain.main(Execute1SqlMain.java:20)
Caused by: java.sql.SQLWarning: NATIONAL/NCHAR/NVARCHAR implies the character set UTF8MB3, which will be replaced by UTF8MB4 in a future release. Please consider using CHAR(x) CHARACTER SET UTF8MB4 in order to be unambiguous.
at com.mysql.cj.protocol.a.NativeProtocol.convertShowWarningsToSQLWarnings(NativeProtocol.java:2204)
at com.mysql.cj.jdbc.StatementImpl.getWarnings(StatementImpl.java:1733)
at com.zaxxer.hikari.pool.HikariProxyStatement.getWarnings(HikariProxyStatement.java)
at net.hasor.dbvisitor.jdbc.core.JdbcConnection.handleWarnings(JdbcConnection.java:223)
... 5 more

设置查询超时

通过设置 queryTimeout 为大于零的值,让 JdbcTemplate 在执行查询的 Statement 上时设定一个超时时间,例如:java.sql.Statement.setQueryTimeout

  • 属性名:queryTimeout
  • 默认值:0,表示不设置。
  • 单位:
jdbc.setQueryTimeout(6);//属性设置后会影响后续所有查询
jdbc.queryForList("select * from users");

查询结果的 fetchSize

通过设置 fetchSize 为大于零的值,让 JdbcTemplate 在执行查询时通过 Statement 为 JDBC 驱动程序提供一个提示。 它提示此 Statement 生成的 ResultSet 对象需要更多行时应该从数据库获取的行数。 指定的行数仅影响使用此语句创建的结果集合。例如:java.sql.Statement.setFetchSize

  • 属性名:fetchSize
  • 默认值:0,表示不设置。
  • 单位:
jdbc.setFetchSize(256);
jdbc.queryForList("select * from users");
该参数的使用通常受到数据库驱动的影响
MySQL 流式查询的用法
PreparedStatement ps = con.prepareStatement(
"select * from test_user",
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY
);
ps.setFetchSize(Integer.MIN_VALUE);
Postgres 7.4+
con.setAutoCommit(false);
PreparedStatement ps = con.prepareStatement(
"select * from test_user",
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY
);
ps.setFetchSize(255);

maxRows

通过设置 maxRows 为大于零的值,让 JdbcTemplate 在执行查询时通过 Statement 为JDBC 驱动程序提供一个提示。 用于限制从 ResultSet 中返回的最大行数。

例如,将 maxRows 设置为 100,则只会从 ResultSet 中获取前 100 行,并忽略后面的行。

  • 属性名:maxRows
  • 默认值:0,表示不设置。
  • 单位:
jdbc.setMaxRows(200);//属性设置后会影响后续所有查询
jdbc.queryForList("select * from users");
请注意

在一些数据库驱动中设置了 maxRows 并不代表查询结果会在获取到指定数量数据后能立即结束查询。

  • 例如:MySQL 在拿到 maxRows 数量的结果集后仍然会将服务器返回的多余行数据进行消费,只不过这些数据不会放入结果集。

动态数据源

由于一些原因可能无法在创建 JdbcTemplate 的时提供 DataSource 或 Connection,又或者 JdbcTemplate 的方法在被调用时会操作不同的 DataSource 或 Connection。 这时就需要用到 DynamicConnection 动态数据源接口替代。

使用 自定义动态数据源
class LocalDynamicConnection implements DynamicConnection {
@Override
public Connection getConnection() throws SQLException {
return ...;// 获取 Connection 用于查询
}

@Override
public void releaseConnection(Connection conn) throws SQLException {
// 查询结束释放 Connection
}
}
使用 动态数据源
JdbcTemplate jdbc = new JdbcTemplate(new LocalDynamicConnection());
拓展信息

SpringDsAdapter 通过使用 Spring 的 DataSourceUtils 来获取和释放数据源链接,来作为 DynamicConnection 实现逻辑。 因此可以让 dbVisitor 和 Spring JDBC 的事务管理器管理协同工作。

使用它需要依赖(按需选择):