我目前正在学习有关在 Spring Boot webapp 中实现 JDBC 和使用数据库的更多信息,并且我遇到了写在帖子底部的以下 Stack Trace。
我创建了一个简单的 Employee 模型,我试图在我的 main() 所在的同一个类上执行一些数据库代码。模型和主类是整个项目中仅有的两个 java 文件。我正在尝试实现以下 run() 代码,该代码覆盖接口 CommandLineRunner 中的代码,但我没有得到应该在log.info("Part A:")之后出现的日志:
log.info("Part A:")
employees.forEach(employee -> {log.info(employee.toString());
log.info("part a");});
——我注意到的事情:
我注意到堆栈跟踪开始之前日志的最后一行来自:“Thread-1”而不是“main”。我认为这意味着来自主线程以外的某个线程在正常关闭之前遇到了错误并关闭了连接。
另外,我认为因为HikariPool 在 "peer's close_notify" 之前关闭,我认为它指的是 HikariPool 的正常关闭,所以我无法看到我一直试图获取的最后一点日志记录。我想查看的最后一点日志记录是插入到我的数据库中的员工的日志记录。
我想看到的最后一点日志记录应该从这行代码中获取:
employees.forEach(employee -> {log.info(employee.toString());
log.info("part a");});
——注意事项:
由于日志中的这一行,我以为我会看到员工插入到我的数据库中,但是当我直接在 MySQL 命令行客户端上查询时,它返回了一个空集:
2018-11-03 21:08:35.362 INFO 2408 --- [ main] c.j.jdbctest1.JdbcTest1Application : rows affected: 1
我不明白为什么当没有任何东西插入数据库时一行会受到影响。
堆栈跟踪和日志:(下面粘贴的堆栈跟踪实际上重复了几次,但为简洁起见,我将其切断。)
2018-11-03 21:08:32.997 INFO 2408 --- [ main] c.j.jdbctest1.JdbcTest1Application : Starting JdbcTest1Application on KitKat with PID 2408 (C:\Users\Nano\Downloads\jdbc-test1\jdbc-test1\target\classes started by Nano in C:\Users\Nano\Downloads\jdbc-test1\jdbc-test1)
2018-11-03 21:08:33.003 INFO 2408 --- [ main] c.j.jdbctest1.JdbcTest1Application : No active profile set, falling back to default profiles: default
2018-11-03 21:08:33.770 INFO 2408 --- [ main] c.j.jdbctest1.JdbcTest1Application : Started JdbcTest1Application in 1.024 seconds (JVM running for 1.778)
2018-11-03 21:08:33.770 INFO 2408 --- [ main] c.j.jdbctest1.JdbcTest1Application : Creating tables
2018-11-03 21:08:33.770 INFO 2408 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2018-11-03 21:08:34.082 INFO 2408 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2018-11-03 21:08:35.135 INFO 2408 --- [ main] c.j.jdbctest1.JdbcTest1Application : Inserting Baggins Hopkins
2018-11-03 21:08:35.362 INFO 2408 --- [ main] c.j.jdbctest1.JdbcTest1Application : rows affected: 1
2018-11-03 21:08:35.362 INFO 2408 --- [ main] c.j.jdbctest1.JdbcTest1Application : Querying for employee
2018-11-03 21:08:36.065 INFO 2408 --- [ main] c.j.jdbctest1.JdbcTest1Application : Part A:
2018-11-03 21:08:36.065 INFO 2408 --- [ Thread-1] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
Sat Nov 03 21:08:36 KST 2018 WARN: Caught while disconnecting...
EXCEPTION STACK TRACE:
** BEGIN NESTED EXCEPTION **
javax.net.ssl.SSLException
MESSAGE: closing inbound before receiving peer's close_notify
STACKTRACE:
javax.net.ssl.SSLException: closing inbound before receiving peer's close_notify
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:129)
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:308)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:264)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:255)
at java.base/sun.security.ssl.SSLSocketImpl.shutdownInput(SSLSocketImpl.java:645)
at java.base/sun.security.ssl.SSLSocketImpl.shutdownInput(SSLSocketImpl.java:624)
at com.mysql.cj.protocol.a.NativeProtocol.quit(NativeProtocol.java:1312)
at com.mysql.cj.NativeSession.quit(NativeSession.java:182)
at com.mysql.cj.jdbc.ConnectionImpl.realClose(ConnectionImpl.java:1750)
at com.mysql.cj.jdbc.ConnectionImpl.close(ConnectionImpl.java:720)
at com.zaxxer.hikari.pool.PoolBase.quietlyCloseConnection(PoolBase.java:135)
at com.zaxxer.hikari.pool.HikariPool.lambda$closeConnection$1(HikariPool.java:441)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
** END NESTED EXCEPTION **
Java 代码:
@SpringBootApplication
public class JdbcTest1Application implements CommandLineRunner {
private static final Logger log = LoggerFactory.getLogger(JdbcTest1Application.class);
@Autowired
JdbcTemplate jdbcTemplate;
public static void main(String[] args) {
SpringApplication.run(JdbcTest1Application.class, args);
}
@Override
public void run(String... args) throws Exception {
log.info("Creating tables");
jdbcTemplate.execute("DROP TABLE IF EXISTS employees");
jdbcTemplate.execute("CREATE TABLE employees (emp_id int, name varchar(100), role varchar(100), status varchar(100))");
log.info("Inserting Baggins Hopkins");
int rowsAffected = jdbcTemplate.update("INSERT INTO EMPLOYEE(EMP_ID, NAME, ROLE, STATUS)"
+ " VALUES(1,'Baggins Hopkins','thief','WORKING')");
log.info("rows affected: "+ Integer.toString(rowsAffected));
log.info("Querying for employee");
String sql = "SELECT emp_id,name,role,status FROM employees";
List<Employee> employees = jdbcTemplate.query(sql,(rs, rowNum)->
new Employee(rs.getInt("emp_id"), rs.getString("name"),
rs.getString("role"),Status.valueOf(rs.getString("status"))));
log.info("Part A:");
employees.forEach(employee -> {log.info(employee.toString());
log.info("part a");});
}
}
另外为了以防万一,我从 application.properties 粘贴了这段代码:
spring.datasource.url=jdbc:mysql://localhost:3306/employee_database
spring.datasource.username=employee
spring.datasource.password=employee
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver