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

Java Spring Boot Hibernate JPA+PostgreSQL返回空响应问题排查

问题:Spring Boot REST API 返回空列表但Hibernate已执行查询

我是Java新手,正在用Restful API开发具备CRUD功能的简单Web应用。访问localhost:8080/api/Employee时返回空列表,但PostgreSQL的Employee表中已有数据,且Hibernate已执行查询语句:

Hibernate: select e1_0.EmployeeID,e1_0.FirstName,e1_0.LastName,e1_0.MiddleName from Employee e1_0

相关代码如下:

Employee.java

package project.test.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;

import java.util.Date;

@Entity
@Data
@Getter
@Setter
@Table(name = "Employee")
public class Employee {
    @Id
    @Column(name = "EmployeeID")
    private String EmployeeID;

    @Column(name = "FirstName")
    private String FirstName;

    @Column(name = "MiddleName")
    private String MiddleName;

    @Column(name = "LastName")
    private String LastName;

    public Employee() {

    }

    public Employee(String EmployeeID, String FirstName, String MiddleName, String LastName) {
        super();
        this.EmployeeID = EmployeeID;
        this.FirstName = FirstName;
        this.MiddleName = MiddleName;
        this.LastName = LastName;
    }

    public String getEmployeeID() {
        return EmployeeID;
    }

    public void setEmployeeID(String EmployeeID) {
        this.EmployeeID = EmployeeID;
    }

    public String getFirstName() {
        return FirstName;
    }

    public void setFirstName(String FirstName) {
        this.FirstName = FirstName;
    }

    public String getMiddleName() {
        return MiddleName;
    }

    public void setMiddleName(String MiddleName) {
        this.MiddleName = MiddleName;
    }

    public String getLastName() {
        return LastName;
    }

    public void setLastName(String LastName) {
        this.LastName = LastName;
    }

}

EmployeeRepository.java

package project.test.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import project.test.entity.Employee;

public interface EmployeeRepository extends JpaRepository<Employee, String> {
}

EmployeeService.java

package project.test.service;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import project.test.entity.Employee;
import project.test.repository.EmployeeRepository;

@Service
public class EmployeeService {
    @Autowired
    private EmployeeRepository employeeRepository;

    public List<Employee> getAllEmployees() {
        return employeeRepository.findAll();
    }
}

EmployeeController.java

package project.test.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import project.test.entity.Employee;
import project.test.service.EmployeeService;

@RestController
@RequestMapping("/api")
public class EmployeeController {
    @Autowired
    private EmployeeService employeeService;

    // Get all employees
    @GetMapping("/Employee")
    public List<Employee> getAllEmployees() {
        return employeeService.getAllEmployees();
    }
}

原因分析与解决方案

1. 属性命名与序列化冲突

你的实体类属性使用大驼峰命名(如EmployeeID),且同时混用@Data、@Getter、@Setter注解,还手写了getter/setter方法。这会导致:

  • Lombok生成的方法与手写方法冲突,破坏JavaBean规范
  • Jackson默认序列化规则是小驼峰,无法识别大驼峰属性的getter,最终返回的JSON中没有属性值,看起来像空列表

解决:

  • 删除所有手写的getter/setter方法,只保留@Data注解(@Data已包含@Getter、@Setter等功能)
  • 将实体属性改为小驼峰命名,通过@Column映射数据库的大驼峰列名

修改后的Employee.java示例:

package project.test.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Data;

@Entity
@Data
@Table(name = "Employee")
public class Employee {
    @Id
    @Column(name = "EmployeeID")
    private String employeeId;

    @Column(name = "FirstName")
    private String firstName;

    @Column(name = "MiddleName")
    private String middleName;

    @Column(name = "LastName")
    private String lastName;

    public Employee() {
    }

    public Employee(String employeeId, String firstName, String middleName, String lastName) {
        this.employeeId = employeeId;
        this.firstName = firstName;
        this.middleName = middleName;
        this.lastName = lastName;
    }
}

2. 事务上下文缺失

虽然Hibernate执行了查询,但如果查询不在事务上下文内,可能导致数据无法正确加载到持久化上下文。

解决:
在EmployeeService的查询方法上添加@Transactional(readOnly = true)注解:

import org.springframework.transaction.annotation.Transactional;

@Service
public class EmployeeService {
    @Autowired
    private EmployeeRepository employeeRepository;

    @Transactional(readOnly = true)
    public List<Employee> getAllEmployees() {
        return employeeRepository.findAll();
    }
}

3. 数据库配置验证

确认application.properties/application.yml中的数据库配置正确:

  • 数据库URL指向正确的实例
  • 账号密码拥有该表的查询权限
  • 指定了PostgreSQL方言

示例配置:

spring.datasource.url=jdbc:postgresql://localhost:5432/your_db_name
spring.datasource.username=your_user
spring.datasource.password=your_pwd
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect

4. 数据类型匹配检查

确认数据库中EmployeeID列的数据类型与实体类的String类型一致,若数据库是整数类型而实体用String,会导致数据无法映射,返回空对象。


内容的提问来源于stack exchange,提问作者Alan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 11:10:54