Java项目中如何通过JDBC查询Azure SQL数据库的特定图书条目
现有代码只返回第一条记录的核心原因
你现在的实现有两个明显的问题,直接导致只能拿第一行:
- 写死的SQL是
SELECT * FROM books,没有任何WHERE过滤条件,本来就是全表拉取所有数据 - 拿到ResultSet后只调用了一次
resultSet.next()就直接返回映射好的对象,根本没遍历剩下的行
分场景实现目标查询
所有带条件的查询都用?做SQL占位符,绝对不要把用户输入的字符串硬拼进SQL里——既防SQL注入,也能处理带单引号、特殊字符的书名/作者名,避免语法报错。
场景1:按指定ISBN查单本图书
ISBN是图书唯一标识,查询结果最多1条,改造后的代码完全兼容你原来的类和日志风格:
// 新增入参:要匹配的目标ISBN,其余保持原方法的访问修饰符和逻辑 private static books readBookByIsbn(Connection connection, String targetIsbn) throws SQLException { log.info("Start query book by ISBN: " + targetIsbn); // 加WHERE过滤,用?做占位符 String querySql = "SELECT * FROM books WHERE isbn = ?;"; // 用try-with-resources自动关闭Statement、ResultSet,适配Azure SQL的连接数限制,避免占满配额 try (PreparedStatement readStatement = connection.prepareStatement(querySql)) { // 给占位符赋值(占位符序号从1开始,不是0) readStatement.setString(1, targetIsbn); try (ResultSet resultSet = readStatement.executeQuery()) { if (!resultSet.next()) { log.info("No data matched for ISBN: " + targetIsbn); return null; } // 映射结果的逻辑和你原来的代码完全一致 books book = new books(); book.setisbn(resultSet.getString("isbn")); book.setDetails(resultSet.getString("Title")); book.setA_vorname(resultSet.getString("AFirstname")); book.setA_nachname(resultSet.getString("ALastname")); book.setRelease(resultSet.getInt("release")); book.setGenre(resultSet.getString("Genre")); book.setBeschreibung(resultSet.getString("description")); book.setDone(resultSet.getBoolean("done")); log.info("Read matched book: " + book.toString()); return book; } } }
场景2:按Genre查同分类下所有图书
这种场景返回的是多条结果,不能返回单个books对象,要改成返回列表,循环遍历ResultSet的每一行:
private static List<books> readBooksByGenre(Connection connection, String targetGenre) throws SQLException { log.info("Start query all books in genre: " + targetGenre); String querySql = "SELECT * FROM books WHERE Genre = ?;"; List<books> matchedBooks = new ArrayList<>(); try (PreparedStatement readStatement = connection.prepareStatement(querySql)) { readStatement.setString(1, targetGenre); try (ResultSet resultSet = readStatement.executeQuery()) { // 循环遍历每一行,每读到一行就新建一个books对象,不然列表里全是最后一条的数据 while (resultSet.next()) { books book = new books(); book.setisbn(resultSet.getString("isbn")); book.setDetails(resultSet.getString("Title")); book.setA_vorname(resultSet.getString("AFirstname")); book.setA_nachname(resultSet.getString("ALastname")); book.setRelease(resultSet.getInt("release")); book.setGenre(resultSet.getString("Genre")); book.setBeschreibung(resultSet.getString("description")); book.setDone(resultSet.getBoolean("done")); matchedBooks.add(book); } } } if (matchedBooks.isEmpty()) { log.info("No books found for genre: " + targetGenre); } else { log.info("Totally found " + matchedBooks.size() + " books"); } return matchedBooks; }
场景3:按书名关键词模糊匹配
如果需要找书名包含指定关键词的书,把WHERE条件改成LIKE模糊匹配就行:
// SQL改成模糊查询 String querySql = "SELECT * FROM books WHERE Title LIKE ?;"; // 给占位符传参的时候前后拼%通配符,比如关键词是"Linux",就传"%Linux%" readStatement.setString(1, "%" + targetKeyword + "%");
新手常见踩坑提醒
- 遍历多行结果时,一定要在while循环内部新建books对象,不要在循环外定义同一个对象反复赋值——不然所有列表项指向同一个对象,最后存的全是最后一行的数据
- 尽量不要长期用
SELECT *,明确写需要查询的字段名,Azure SQL是按IO流量计费的,查多余字段会平白增加成本,也不会因为表加了多余字段突然读不出数据 - 所有JDBC的资源(PreparedStatement、ResultSet)一定要确保关闭,不然Azure SQL会把未关闭的连接算到配额里,跑几次就会报连接数不够的错,用try-with-resources语法可以自动关资源,不用手动写finally块
内容的提问来源于stack exchange,提问作者Fleksiu
相关产品推荐
相关产品推荐

