java - 访问存储过程时的 Spring JDBCTemplate 与简单的 JDBC 性能
问题描述
我在使用 JDBCTemplate 通过存储过程访问数据时遇到了与性能相关的问题。相反,当我从 Simple JDBC 访问时,它运行得非常快。
2019-12-04 11:55:43.924 INFO 9512 --- [main] etTestStoredProcPerformanceApplication:未设置活动配置文件,回退到默认配置文件:默认 2019-12-04 11:55:46.002 INFO 9512 --- [main] etTestStoredProcPerformanceApplication :在 2.831 秒内启动 TestStoredProcPerformanceApplication(JVM 运行 3.57)
尝试使用简单的 Jdbc
Calling get_all_persons Attempt : 1 took 1173 milliseconds
Calling get_all_persons Attempt : 2 took 29 milliseconds
Calling get_all_persons Attempt : 3 took 27 milliseconds
Calling get_all_persons Attempt : 4 took 67 milliseconds
Calling get_all_persons Attempt : 5 took 31 milliseconds
Calling get_all_persons Attempt : 6 took 30 milliseconds
Calling get_all_persons Attempt : 7 took 30 milliseconds
Calling get_all_persons Attempt : 8 took 27 milliseconds
Calling get_all_persons Attempt : 9 took 29 milliseconds
尝试使用 jdbcTemplate
2019-12-04 11:55:47.475 INFO 9512 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - 开始... 2019-12-04 11:55:47.514 INFO 9512 --- [ main] com.zaxxer.hikari.pool.PoolBase : HikariPool-1 - 驱动程序不支持获取/设置连接的网络超时。(oracle.jdbc.driver.T4CConnection.getNetworkTimeout()I) 2019-12-04 11:55:47.524 INFO 9512 --- [main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - 启动完成。
Calling get_all_persons Attempt : 1 took 226 milliseconds
Calling get_all_persons Attempt : 2 took 111 milliseconds
Calling get_all_persons Attempt : 3 took 112 milliseconds
Calling get_all_persons Attempt : 4 took 128 milliseconds
Calling get_all_persons Attempt : 5 took 111 milliseconds
Calling get_all_persons Attempt : 6 took 97 milliseconds
Calling get_all_persons Attempt : 7 took 98 milliseconds
Calling get_all_persons Attempt : 8 took 98 milliseconds
Calling get_all_persons Attempt : 9 took 99 milliseconds
2019-12-04 11:55:48.547 INFO 9512 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - 已启动关闭... 2019-12-04 11:55:48.566 INFO 9512 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - 关闭完成。
这个结果来自我的本地机器。当我实际使用 JDBCTemplate 访问我的办公室测试服务器时,它需要 5 到 7 秒,而简单的 JDBC 只需要 2 秒,即使我在每次迭代中创建连接。使用 spring jdbc 模板,它从 application.properties 创建 2 个连接
应用程序属性
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:XE
spring.datasource.username=system
spring.datasource.password=*****
spring.datasource.driver-class=oracle.jdbc.driver.OracleDriver
spring.datasource.type = com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.maximum-pool-size=2
spring.datasource.hikari.leakDetectionThreshold=2000
spring.datasource.hikari.connectionTimeout=20000
spring.datasource.hikari.idleTimeout=500000
spring.datasource.hikari.maxLifetime=1700000
访问存储过程的代码。
@Component
public class Initializer2 implements ApplicationListener<ApplicationReadyEvent> {
@Autowired
private JdbcTemplate jdbcTemplate;
public static String packageName = "myPackage";
public static String procName = "get_all_persons";
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
testStoredProcWithJdbc("");
testStoredProcWithJdbcTemplate("");
}
private void testStoredProcWithJdbcTemplate(String string) {
System.out.println("Trying with jdbcTemplate");
try {
for(int i = 1; i < 10; i++) {
long startTime = System.currentTimeMillis();
SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate);
jdbcCall.withCatalogName(packageName);
jdbcCall.withProcedureName(procName);
jdbcCall.addDeclaredParameter(new SqlOutParameter("o_result_set", oracle.jdbc.OracleTypes.CURSOR));
jdbcCall.addDeclaredParameter(new SqlOutParameter("o_message", oracle.jdbc.OracleTypes.VARCHAR));
jdbcCall.execute();
long endTime = System.currentTimeMillis();
System.out.println("Calling get_all_persons Attempt : "+i+" took "+ (endTime - startTime) + " milliseconds");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void testStoredProcWithJdbc(String procName) {
System.out.println("Trying with Simple Jdbc");
try {
for(int i = 1; i < 10; i++) {
long startTime = System.currentTimeMillis();
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE", "system", "*****");
CallableStatement cstmt = conn.prepareCall("call "+packageName+"."+procName+"(?,?)");
cstmt.registerOutParameter("o_result_set", oracle.jdbc.OracleTypes.CURSOR);
cstmt.registerOutParameter("o_message", oracle.jdbc.OracleTypes.VARCHAR);
cstmt.execute();
ResultSet resultSet = (ResultSet) cstmt.getObject("o_result_set");
List<Person> persons = new ArrayList<>();
Map<String, Object> map = new HashMap<>();
map.put("o_message", cstmt.getString("o_message"));
while(resultSet.next()) {
Person person = new Person();
person.setId(resultSet.getInt("id"));
person.setName(resultSet.getString("name"));
person.setEmail(resultSet.getString("email"));
person.setMobile(resultSet.getLong("mobile"));
if(resultSet.getTimestamp("birthdate") != null)
person.setBirthDate(resultSet.getTimestamp("birthdate").toLocalDateTime());
persons.add(person);
}
map.put("o_result_set", persons);
cstmt.close();
conn.close();
long endTime = System.currentTimeMillis();
System.out.println("Calling get_all_persons Attempt : "+i+" took "+ (endTime - startTime) + " milliseconds");
}
System.out.println("Successful...");
} catch (Exception e) {
e.printStackTrace();
}
}
}
解决方案
推荐阅读
- c - 冒泡排序可以有多个程序吗?
- pandas - 截断数据帧上的线性回归不起作用
- html-email - 如何在 html 电子邮件中嵌入字体
- gradle - Gradle - 仅当目录中的代码已更改时才执行任务
- javascript - 使用 Javascript 过滤 DIV
- django - 在 django 中处理 IntegrityError 的任何方法?
- swiftui - 如何在结构之外访问 TapGesture() 操作/结果
- r - 如何在堆叠的条形图中自动定位内部标签?
- sms - Orange SMS Gateway APi 1.1 不适用于 php
- c# - .Net Core Migration System.ArgumentNullException:值不能为空