Jersey REST结合JDBC实现查询接口的架构问题咨询
问题解答
问题1:AnimalPersistence获取连接的方式是否合理,DBConnection的实现是否正确
- 现有获取连接的逻辑功能可用但设计不合理,修改后的每次新建连接的实现也存在问题:
- 最初的单例Connection设计完全不可行:JDBC的Connection不是线程安全的,多并发请求共用同一个连接会出现事务混乱、数据异常等问题。
- 改成每次新建连接虽然解决了线程安全问题,但资源开销极大:每次新建连接都要走TCP握手、数据库权限校验等流程,并发稍高就会占满数据库的连接数,性能极低。
- 正确方案是使用成熟的数据库连接池(比如HikariCP)管理连接,不用自行实现连接的创建销毁逻辑。
问题2:是否需要主动关闭Connection
不需要主动关闭。你已经把Connection放到了try-with-resources的声明块中,Connection实现了AutoCloseable接口,不管try块正常执行结束还是抛出异常,都会自动调用close()方法释放连接,同时Statement和ResultSet也会被自动关闭,无需手动处理。
代码存在的所有错误
- SQL注入风险:
AnimalPersistence.findById方法直接拼接SQL字符串,使用Statement执行,存在严重的SQL注入漏洞。应当替换为PreparedStatement预编译SQL,再传入参数。 - DBConnection线程安全隐患:DBConnection里定义了静态的
connection变量,每次调用getConnection都会覆盖这个变量,多线程并发调用时会出现连接被篡改、串用的问题。应该直接删掉这个静态变量,getConnection方法直接返回DriverManager.getConnection的结果即可,不要把连接存到静态变量里。 - 空指针风险:
getAnimalFromResultSet方法中,如果数据库的date_of_birth字段为null,调用toLocalDate()会直接抛出空指针异常,需要先判断resultSet.getDate("date_of_birth")是否为null再做转换。 - 异常被吞噬:
DBConnection.getConnection方法捕获SQLException后仅打印栈轨迹,直接返回null,后续拿到null连接的代码会直接抛出空指针,无法定位真实的连接错误。应该把SQLException向上抛出,交由上层业务逻辑处理。 - 冗余逻辑:
findById方法中id是主键,查询结果最多只有一条,不需要用while遍历ResultSet,用if判断即可。 - 驱动类过时:如果使用MySQL 8.0+版本,
com.mysql.jdbc.Driver已经废弃,应当替换为com.mysql.cj.jdbc.Driver;JDBC4.0及以上版本不需要手动调用Class.forName加载驱动,类路径下的驱动会被自动扫描加载。 - 冗余导入:
AnimalPersistence类中导入了PreparedStatement、ArrayList、List、JsonMessage、ZoneId多个未使用的类,可直接删除。
内容的提问来源于stack exchange,提问作者dombimihaly89
相关产品推荐
相关产品推荐

