Java Spring/JPA应用程序搜索不存在的数据库表
我有一个使用JPA作为ORM的Spring应用程序,我认为这是正确的,并且大摇大摆地为我的端点创建了一个漂亮的UI 尝试使用已保存在数据库中的数据发出POST或PUT请求时,我收到一个错误:Java Spring/JPA应用程序搜索不存在的数据库表,java,spring,jpa,Java,Spring,Jpa,我有一个使用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.spring
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\u department
表上的数据,而该表不存在。我遇到的问题是弄清楚为什么JPA试图访问该表
数据流:
大摇大摆的用户界面->用JSON发布请求
->雇员控制员
->雇员服务
->雇员映射器
职业性
package com.nexient.orgchart.data.entity;
导入org.hibernate.validator.constraints.NotEmpty;
导入javax.persistence.*;
导入java.util.Set;
@实体
@表(name=“职务”)
公共类JobTitleEntity扩展了BaseEntity{
@列(name=“name”,unique=true)
@空空如也
私有字符串名称;
@独身癖
私人设定所有权的雇员;
…能手和二传手。。。
部门实体
package com.nexient.orgchart.data.entity;
导入javax.persistence.*;
导入javax.validation.constraints.NotNull;
导入javax.validation.constraints.Size;
导入org.hibernate.validator.constraints.NotEmpty;
导入java.util.HashSet;
导入java.util.Set;
@实体
@表(name=“department”)
公共类DepartmentEntity扩展BaseEntity{
@manytone(fetch=FetchType.EAGER)
@JoinColumn(name=“manager\u id”)
私人雇员实体经理;
@列(name=“name”,nullable=false,length=50,unique=true)
@NotNull
@空空如也
@尺寸(最小值=1,最大值=45)
私有字符串名称;
@manytone(fetch=FetchType.EAGER)
@JoinColumn(name=“家长\部门\ id”,referencedColumnName=“id”)
私人部门实体部门;
@OneToMany(mappedBy=“家长部门”)
私有集部门=新哈希集(0);
@OneToMany(mappedBy=“部门”)
私有集employees=newhashset(0);
…能手和二传手。。。
发生这种情况是因为您与N
员工有1
部门关系:
@ManyToOne
@JoinColumn(name = "department_id")
private DepartmentEntity department;
您的JPA实现选择使用专用表来支持此关系,而不是使用可为空的列。它显然已自动从相关实体的表名中派生出此关系的employee\u department
名称
使用配置为生成DDL语句并记录所有SQL语句的JPA实现运行应用程序可能会非常有启发性。确切的配置将取决于您选择的JPA提供程序,但由于您使用的是Spring,您可能需要
Spring.JPA.generate DDL=true
和Spring.JPA。show sql=true
。请参见您知道我如何防止这种情况发生,还是让创建此表更好?我的帖子似乎运行了一段时间,然后在几个请求后出现了此错误。到目前为止,我唯一能够修复此错误的方法是重置数据库和服务器。要“防止”如果发生这种情况,您必须有效地放弃该点,并手动定义一个实体
,以替换原始关系/映射。这还意味着对代码的其余部分进行破坏性更改:您将需要额外的存储库来追溯关系。与您的JPA提供商进行斗争以改变其行为/预期是非常必要的当然不是一个好主意。不过,最好调整一下数据库,以便包含关系所需的表。
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;
}
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 ...
@ManyToOne
@JoinColumn(name = "department_id")
private DepartmentEntity department;