H2数据库查询提示BOOK表不存在问题求助(禁用JPA)
H2数据库读取数据失败:表"BOOK"未找到问题排查
问题现象
尝试从H2数据库读取数据到JSP页面,数据已成功存入数据库,但读取失败。加载图书信息页面时抛出如下错误:
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "BOOK" not found; SQL statement: select book0_.ID as id1_1_, book0_.AUTHOR as author2_1_, book0_.GENRE as genre3_1_, book0_.ILLUSTRATOR as illustra4_1_, book0_.SERIES as series5_1_, book0_.TITLE as title6_1_ from BOOK book0_ [42102-214]
注:项目明确禁止使用JPA。
相关代码
Model
package org.bookarchive.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "BOOK") public class Book { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) @Column(name = "ID") private Long id; @Column(name = "TITLE", nullable = false) private String title; @Column(name = "SERIES") private String series; @Column(name = "AUTHOR", nullable = false) private String author; @Column(name = "ILLUSTRATOR") private String illustrator; @Column(name = "GENRE") private String genre; // getter、setter、hashCode、equals、toString方法 }
Controller
@RestController @RequestMapping("/api/favoritebooks") @Configuration @ComponentScan("org.bookarchive") public class RestListController { Logger logger = LoggerFactory.getLogger(RestListController.class); @Autowired private ListService bookList; ModelAndView mv = new ModelAndView("bookList"); @GetMapping public ModelAndView getBookListHome() { List<Book> books = bookList.findAllBooks(); mv.addObject("books", books); return mv; } }
DAO
package org.bookarchive.dao; import java.util.List; import javax.persistence.Query; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Root; import org.bookarchive.model.Book; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; @Repository public class DAOImpl implements DAO { @Autowired private SessionFactory sessionFactory; @SuppressWarnings("unchecked") @Override public List<Book> findAllBooks() { Session s = sessionFactory.getCurrentSession(); CriteriaBuilder cb = s.getCriteriaBuilder(); CriteriaQuery<Book> cq = cb.createQuery(Book.class); Root<Book> root = cq.from(Book.class); cq.select(root); Query query = s.createQuery(cq); return query.getResultList(); } }
JavaScript Service
'use strict'; angular.module('myApp').factory('ListService', ListServiceFactory) ListServiceFactory.$inject = ['$http', '$log'] function ListServiceFactory($http, $log) { let REST_SERVICE_URI = 'http://localhost:8081/favoritebooks/'; let factory = { fetchAllBooks: fetchAllBooks, createBook: createBook, updateBook:updateBook, deleteBook:deleteBook }; return factory; function fetchAllBooks() { return $http.get(REST_SERVICE_URI).then( function (response) { return response.data; }, function (errResponse) { $log.error('Error while fetching Books ', errResponse); } ); } }
JavaScript Controller
'use strict'; angular.module('myApp').controller('RestListController', ['$scope', '$log' ,'ListService', function($scope, $log, ListService) { var self = this; self.book = { id: null, title: '', series: '', author: '', illustrator: '', genre: ''}; self.books = []; self.submit = submit; self.edit = edit; self.remove = remove; self.reset = reset; findAllBooks(); function findAllBooks(){ ListService.fetchAllBooks() .then( function(d) { self.books = d; }, function(errResponse){ $log.error('Error while fetching Books ', errResponse); } ); } }
JSP页面
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE html> <html> <head> <title>Book Archive</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> <link href="/static/css/app.css" rel="stylesheet"></link> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.js"></script> </head> <body> <div align="center"> <h2>Complete Book List</h2><BR> <table border="1"> <tr> <th>Book Id</th> <th>Title</th> <th>Series</th> <th>Author</th> <th>Illustrator</th> <th>Genre</th> </tr> <c:forEach var="book" items="${books}"> <tr> <td>${book.id}</td> <td>${book.title}</td> <td>${book.series}</td> <td>${book.author}</td> <td>${book.illustrator}</td> <td>${book.genre}</td> <td> <button type="button" ng-click="ctrl.edit(book)" class="btn btn-success custom-width">Edit</button> <button type="button" ng-click="ctrl.remove(book)" class="btn btn-danger custom-width">Remove</button> </td> </tr> </c:forEach> </table> </div> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.js"></script> <script src="/static/js/app.js"></script> <script src="/static/js/service/listService.js"></script> <script src="/static/js/controller/listController.js"></script> </body> </html>
问题分析与修复方案
1. 核心错误:表"BOOK"未找到
- 检查H2数据库实际表结构:登录H2控制台,确认数据库中是否存在名为
BOOK的表。H2默认可能开启大小写敏感,若实际表名为小写book,会导致SQL查询大写表名失败。可修改H2连接URL添加;CASE_INSENSITIVE_IDENTIFIERS=true关闭大小写敏感,或修正实体类@Table注解的name属性为实际表名。 - 序列缺失问题:实体类使用
GenerationType.SEQUENCE生成ID,需确认H2中存在对应序列,否则插入数据时可能自动创建表但序列不匹配,导致后续查询异常。
2. 违反JPA禁用要求
代码中Model使用了@Entity、@Table等JPA注解,DAO使用了JPA的Criteria API,若项目严格禁止JPA,需:
- 移除Model中的所有JPA注解,改用Hibernate XML映射文件配置实体与表的映射关系。
- DAO层改用Hibernate原生API或原生SQL查询,例如:
@Override public List<Book> findAllBooks() { Session s = sessionFactory.getCurrentSession(); Query query = s.createSQLQuery("SELECT * FROM BOOK").addEntity(Book.class); return query.list(); }
3. Controller注解与响应类型不匹配
@RestController会将返回值序列化为JSON,但当前方法返回ModelAndView(用于服务器端视图渲染),导致前端收到的是JSP页面HTML而非图书数据JSON。需调整:- 若保留服务器端渲染(JSTL遍历):将
@RestController改为@Controller,此时前端无需Angular请求,直接通过JSTL的${books}获取数据。 - 若使用Angular异步获取数据:修改Controller方法返回
List<Book>,移除ModelAndView相关代码:
- 若保留服务器端渲染(JSTL遍历):将
@RestController @RequestMapping("/api/favoritebooks") public class RestListController { @Autowired private ListService bookList; @GetMapping public List<Book> getBookList() { return bookList.findAllBooks(); } }
4. 前端请求地址错误
JavaScript Service中的REST_SERVICE_URI为http://localhost:8081/favoritebooks/,但Controller的@RequestMapping是/api/favoritebooks,需修正为:
let REST_SERVICE_URI = 'http://localhost:8081/api/favoritebooks/';
5. 事务配置缺失
DAO的findAllBooks方法使用sessionFactory.getCurrentSession(),需确保方法在事务上下文执行,否则会抛出Session未绑定异常。在Service层的对应方法添加@Transactional注解,或在DAO方法上添加该注解。
内容的提问来源于stack exchange,提问作者Matthew Earlywine
相关产品推荐
相关产品推荐

