REST API调用H2数据库查询返回空结果,main方法正常的问题修复
问题:REST API使用Hibernate查询H2数据库返回空列表,但main方法查询正常
我开发了一个使用Hibernate从H2数据库获取数据的REST API,已向数据库添加数据,但API中的查询返回空列表,而main方法中执行相同的查询却能返回正确数据,请问该如何解决此问题?
DroneResource.java
@Path("/drones") public class DroneResource { @GET @Produces("application/json") public List<Employee> getEmployee() { EmployeeDAO dao = new EmployeeDAO(); // 返回空列表 List employees = dao.getEmployees(); return employees; } public static void main(String[] args) { EmployeeDAO dao = new EmployeeDAO(); // 从数据库返回正确数据 List employees = dao.getEmployees(); } }
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory name="hibernateSessionFactory"> <property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property> <property name="hibernate.connection.driver_class">org.h2.Driver</property> <property name="hibernate.connection.url">jdbc:h2:./h2db;AUTO_SERVER=TRUE</property> <property name="hibernate.connection.username">admin</property> <property name="hibernate.connection.password">admin</property> <property name="hibernate.show_sql">true</property> <property name="hibernate.format_sql">true</property> <property name="hbm2ddl.auto">update</property> <property name="hibernate.connection.server_timezone">UTC</property> <mapping class="com.gitlab.olorini.test.Employee"/> </session-factory> </hibernate-configuration>
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd" version="5.0"> <display-name>Drones manager</display-name> <servlet> <servlet-name>Example API</servlet-name> <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> <init-param> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>com.gitlab.olorini.web.services.endpoints</param-value> </init-param> <init-param> <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name> <param-value>true</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>Example API</servlet-name> <url-pattern>/rest/*</url-pattern> </servlet-mapping> </web-app>
数据库实体类 Employee.java
@Entity public class Employee { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; @Column private String name; @Column private int age; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
DAO 相关代码
EmployeeDAO.java
public class EmployeeDAO { public List<Employee> getEmployees(){ Session session = SessionUtil.getSession(); Query query = session.createQuery("from Employee"); List<Employee> employees = query.list(); session.close(); return employees; } }
SessionUtil.java
public class SessionUtil { private static SessionUtil instance=new SessionUtil(); private SessionFactory sessionFactory; public static SessionUtil getInstance(){ return instance; } private SessionUtil(){ Configuration configuration = new Configuration(); configuration.configure("hibernate.cfg.xml"); sessionFactory = configuration.buildSessionFactory(); } public static Session getSession(){ Session session = getInstance().sessionFactory.openSession(); return session; } }
build.gradle
plugins { id 'java' id 'war' } group 'com.github.olorini' version '1.0-SNAPSHOT' sourceCompatibility = '1.8' project.webAppDirName = 'web' repositories { mavenCentral() flatDir { dirs 'lib' } } dependencies { implementation 'log4j:log4j:1.2.17' implementation 'org.hibernate:hibernate-core:5.6.12.Final' implementation 'javax.validation:validation-api:2.0.1.Final' runtimeOnly 'com.h2database:h2:2.1.214' implementation 'com.sun.jersey:jersey-bundle:1.19.4' implementation 'com.sun.jersey:jersey-json:1.19.4' testImplementation 'junit:junit:4.13.2' } test { useJUnitPlatform() }
排查与解决方法
1. 数据库路径不统一
Web应用和本地main方法的工作目录不同,导致各自访问的是不同的H2数据库文件。
- 解决:把H2连接URL改成绝对路径,比如
jdbc:h2:/Users/xxx/project/h2db;AUTO_SERVER=TRUE,确保Web容器和main方法访问同一个数据库文件。
2. 事务未正确处理
Hibernate在某些环境下,查询操作也需要显式开启事务才能获取数据。
- 修改EmployeeDAO代码:
public List<Employee> getEmployees(){ Session session = SessionUtil.getSession(); List<Employee> employees = new ArrayList<>(); try { session.beginTransaction(); Query query = session.createQuery("from Employee"); employees = query.list(); session.getTransaction().commit(); } catch (Exception e) { if (session.getTransaction().isActive()) { session.getTransaction().rollback(); } e.printStackTrace(); } finally { session.close(); } return employees; }
3. 实体类缺少无参构造函数
Hibernate和JSON序列化都要求实体类有无参构造函数,当前Employee类没有,可能导致数据无法正常实例化或序列化。
- 给Employee添加无参构造:
@Entity public class Employee { // 原有字段和方法 public Employee() {} // 添加无参构造 }
4. H2自动服务器模式问题
AUTO_SERVER=TRUE在Web容器环境下可能存在连接冲突,导致无法正确读取数据。
- 解决:启动独立的H2服务器,修改连接URL为
jdbc:h2:tcp://localhost/./h2db,确保Web应用通过TCP连接访问同一个数据库。
5. 类路径下实体映射未被加载
检查Web应用中Hibernate是否能找到Employee类,确认hibernate.cfg.xml中的<mapping class="com.gitlab.olorini.test.Employee"/>路径正确,且实体类已被打包到WAR包中。
内容的提问来源于stack exchange,提问作者Olorono
相关产品推荐
相关产品推荐

