You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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相关代码:
@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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 20:30:57