代码之家  ›  专栏  ›  技术社区  ›  Brandon Benefield

Spring/JPA应用程序搜索不存在的数据库表

  •  0
  • Brandon Benefield  · 技术社区  · 6 年前

    我有一个使用JPA作为ORM的Spring应用程序,我认为这是正确的,并且轻率地为我的端点创建了一个好的UI。

    尝试使用已保存在数据库中的数据进行POST或PUT请求时,我收到一个错误:

    Servlet.service() for servlet [dispatcher] in context with path [/api/orgchart] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute statement] with root cause
    
    java.sql.SQLSyntaxErrorException: Table 'orgchart_api.employee_department' doesn't exist
    

    很明显,错误是由于JPA试图在 employee_department 表,并且此表不存在。我遇到的问题是 为什么? JPA正试图访问该表。

    数据流:

    Swagger UI—使用JSON发布请求

      {
        "id": 104,
        "isActive": true,
        "manager": null,
        "firstName": "string",
        "middleInitial": null,
        "lastName": "string",
        "department": {
          "id": 104,
          "isActive": true,
          "parentDepartment": {
            "id": 101,
            "isActive": true,
            "parentDepartment": null,
            "manager": null,
            "name": "Marketing"
          },
          "manager": null,
          "name": "Americas"
        },
        "jobTitle": {
          "id": 1001,
          "isActive": true,
          "name": "Jr. Developer"
        },
        "email": "e",
        "skypeName": "e",
        "isManager": false
      }
    

    ->员工控制者

    package com.orgchart.web.controller;
    
    import com.orgchart.model.Employee;
    import com.orgchart.service.EmployeeService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpStatus;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.List;
    
    @RestController
    @RequestMapping("/emps")
    public class EmployeeController {
    
        @Autowired
        EmployeeService employeeService;
    
        @RequestMapping(method = {RequestMethod.POST, RequestMethod.PUT})
        public Employee createOrUpdateEmployee(@RequestBody Employee employee) {
            return employeeService.storeOrUpdate(employee);
        }
    
    }
    

    ->员工服务

    package com.nexient.orgchart.service;
    
    import com.nexient.orgchart.data.entity.DepartmentEntity;
    import com.nexient.orgchart.data.entity.EmployeeEntity;
    import com.nexient.orgchart.data.repository.EmployeeRepository;
    import com.nexient.orgchart.mapper.EmployeeMapper;
    import com.nexient.orgchart.model.Employee;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.util.Assert;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.function.Consumer;
    import java.util.stream.Collectors;
    
    @Service
    public class EmployeeService {
    
        @Autowired
        private EmployeeRepository employeeRepository;
    
        @Autowired
        EmployeeMapper employeeMapper;
    
        public Employee storeOrUpdate(Employee employee) {
            EmployeeEntity employeeEntity = employeeMapper.modelToEntity(employee);
            EmployeeEntity savedEmployeeEntity = employeeRepository.save(employeeEntity);
            Employee employeeModel = employeeMapper.entityToModel(savedEmployeeEntity);
            return employeeModel;
        }
    

    ->员工映射器

    package com.nexient.orgchart.mapper;
    
    import com.nexient.orgchart.data.entity.DepartmentEntity;
    import com.nexient.orgchart.data.entity.EmployeeEntity;
    import com.nexient.orgchart.data.entity.JobTitleEntity;
    import com.nexient.orgchart.model.Department;
    import com.nexient.orgchart.model.Employee;
    import com.nexient.orgchart.model.JobTitle;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.springframework.util.Assert;
    
    @Component
    public class EmployeeMapper implements EntityModelMapper<EmployeeEntity, Employee> {
    
        @Autowired
        private DepartmentMapper departmentMapper;
    
        @Autowired
        private JobTitleMapper jobTitleMapper;
    
        @Override
        public EmployeeEntity modelToEntity(Employee employee) {
            Assert.notNull(employee, "Employee model cannot be null.");
    
            EmployeeEntity employeeEntity = new EmployeeEntity();
            DepartmentEntity departmentEntity = departmentMapper.modelToEntity(employee.getDepartment());
            JobTitleEntity jobTitleEntity = jobTitleMapper.modelToEntity(employee.getJobTitle());
            Employee employeeManager = employee.getManager();
    
            if (employeeManager != null) {
                EmployeeEntity employeeManagerEntity = modelToEntity(employeeManager);
                employeeEntity.setManager(employeeManagerEntity);
            }
    
            employeeEntity.setId(employee.getId());
            employeeEntity.setEmail(employee.getEmail());
            employeeEntity.setFirstName(employee.getFirstName());
            employeeEntity.setMiddleInitial(employee.getMiddleInitial());
            employeeEntity.setLastName(employee.getLastName());
            employeeEntity.setDepartment(departmentEntity);
            employeeEntity.setJobTitle(jobTitleEntity);
            employeeEntity.setIsManager(employee.getIsManager());
            employeeEntity.setSkypeName(employee.getSkypeName());
            employeeEntity.setIsActive(employee.getIsActive());
    
            return employeeEntity;
        }
    

    从这里穿过另一个 <Model>.modelToEntity() 对于 jobTitle department 最后打电话给 employeeRepository.save(employeeEntity) 员工服务 错误来源的文件。

    重申一下,为什么我的帖子请求试图访问 员工\部门 表当我在任何实体中都没有将其指定为表名时?

    实体

    员工实体

    package com.nexient.orgchart.data.entity;
    
    import org.hibernate.validator.constraints.NotEmpty;
    
    import javax.persistence.*;
    import javax.validation.constraints.NotNull;
    import javax.validation.constraints.Size;
    import java.util.Set;
    
    @Entity
    @Table(name = "employee")
    public class EmployeeEntity extends BaseEntity {
    
        @Column(name = "first_name")
        @NotEmpty
        @Size(min = 1)
        private String firstName;
    
        @Column(name = "middle_initial")
        private Character middleInitial;
    
        @Column(name = "last_name")
        @NotEmpty
        @Size(min = 1)
        private String lastName;
    
        @Column(name = "email")
        @NotEmpty
        @Size(min = 1)
        private String email;
    
        @Column(name = "skype_name")
        @NotEmpty
        @Size(min = 1)
        private String skypeName;
    
        @ManyToOne
        @JoinColumn(name = "job_title_id")
        private JobTitleEntity jobTitle;
    
        @ManyToOne
        @JoinColumn(name = "manager_id")
        private EmployeeEntity manager;
    
        @ManyToOne
        @JoinColumn(name = "department_id")
        private DepartmentEntity department;
    
        @OneToMany(mappedBy = "manager")
        private Set<EmployeeEntity> ManagedEmployees;
    
        @OneToMany
        private Set<DepartmentEntity> ManagedDepartments;
    
        @Column(name = "is_manager")
        @NotNull
        private boolean isManager;
    
        ... Getters and Setters ...
    

    职务实体

    package com.nexient.orgchart.data.entity;
    
    import org.hibernate.validator.constraints.NotEmpty;
    
    import javax.persistence.*;
    import java.util.Set;
    
    @Entity
    @Table(name = "job_title")
    public class JobTitleEntity extends BaseEntity {
    
        @Column(name = "name", unique = true)
        @NotEmpty
        private String name;
    
        @OneToMany
        private Set<EmployeeEntity> titleEmployees;
    
        ... Getters and Setters ...
    

    部门实体

    package com.nexient.orgchart.data.entity;
    
    import javax.persistence.*;
    import javax.validation.constraints.NotNull;
    import javax.validation.constraints.Size;
    
    import org.hibernate.validator.constraints.NotEmpty;
    
    import java.util.HashSet;
    import java.util.Set;
    
    @Entity
    @Table(name = "department")
    public class DepartmentEntity extends BaseEntity {
    
        @ManyToOne(fetch = FetchType.EAGER)
        @JoinColumn(name = "manager_id")
        private EmployeeEntity manager;
    
        @Column(name = "name", nullable = false, length = 50, unique = true)
        @NotNull
        @NotEmpty
        @Size(min = 1, max = 45)
        private String name;
    
        @ManyToOne(fetch = FetchType.EAGER)
        @JoinColumn(name = "parent_department_id", referencedColumnName = "ID")
        private DepartmentEntity parentDepartment;
    
        @OneToMany(mappedBy = "parentDepartment")
        private Set<DepartmentEntity> departments = new HashSet<>(0);
    
        @OneToMany(mappedBy = "department")
        private Set<EmployeeEntity> employees = new HashSet<>(0);
    
        ... Getters and Setters ...
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   user268396    6 年前

    这是因为你有 N 员工到 1 部门关系:

    @ManyToOne
    @JoinColumn(name = "department_id")
    private DepartmentEntity department;
    

    JPA实现选择使用专用表而不是可以为空的列来支持此关系。它显然是从 employee_department 从所涉及实体的表名中自动为其命名。

    事实证明,使用配置为生成DDL语句和记录所有SQL语句的JPA实现来运行应用程序可能非常有启发性。确切的配置将取决于您选择的JPA提供程序,但由于您使用的是Spring,因此可能需要 spring.jpa.generate-ddl=true spring.jpa.show-sql=true . 见 the documentation