Spring Data JPA 无法找到具有ID的对象。

huangapple 未分类评论50阅读模式
英文:

Spring Data JPA unable to find object with id

问题

我在项目中使用了JPA + Hibernate + Spring Data JPA来与数据库(MySQL)进行交互。

最近我遇到了一个错误,错误信息如下:

org.springframework.orm.jpa.JpaObjectRetrievalFailureException: 无法找到具有id 1700的com.kanda.mindwire.domain.results.CognitiveResult;嵌套异常是javax.persistence.EntityNotFoundException: 无法找到具有id 1700的com.kanda.mindwire.domain.results.CognitiveResult
    at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:379) ~[spring-orm-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    ...

代码尝试获取Employee实体的列表,该实体与CognitiveResult具有OneToOne关系。我曾认为可能存在一个cognitive_id=1700Employee记录,但是当我查询数据库时,发现并没有这样的记录。

问题是Hibernate从哪里获取了这个id,以及如何修复?

以下是我提供的代码片段:

Employee.java

@Table(uniqueConstraints = @UniqueConstraint(columnNames = {Employee_.EMAIL}))
@Entity
@Data
public class Employee extends BaseEmployee {
    @Column
    private String email;
    ...
    @ManyToOne
    @JoinColumn(name = "company_id")
    private Company company;
        
    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "cognitive_id", referencedColumnName = "id")
    private CognitiveResult cognitiveResult;
    ...
}

CognitiveResult.java

@Entity
@Table(name = "cognitive_results")
@Data
public class CognitiveResult extends BaseAssesment {
    ...
    @OneToOne(mappedBy = "cognitiveResult")
    private Employee employee;
    
    @PreRemove
    public void removeCognitiveForEmployee() {
        if (employee != null) {
            employee.setCognitiveResult(null);
        }
    }
    ...
}

EmployeeRepository.java

public interface EmployeeRepository extends BaseRepository<Employee> {
    ...
    List<Employee> findByCompany(Company company);
    ...
}

Company.java

@Entity
@Data
public class Company extends BaseSettingsEntity {
    ...
    @OneToMany(mappedBy = "company", cascade = CascadeType.ALL)
    private Set<Employee> employees = new HashSet<>();
    ...
}

所有的领域模型都继承自BaseEntity.java

@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Entity
@Data
public abstract class BaseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    @Column(updatable = false, nullable = false)
    protected Long id;
    ...
}

在调用findByCompany时出现了异常:

@Slf4j
public class EmployeeService extends BaseEntityService<Employee> {
    
    private final EmployeeRepository repo;

    public Map<String, Map<EmployeeJob, List<Employee>>> findWithFilter(EmployeeFilterWrapper filter, String username) {
        List<Employee> employeeList;
        User user = userService.findByUsername(username);
        Company company = user.getCompany();
        ...
    }
    ...
}
英文:

I'm using JPA + Hibernate + Spring Data JPA on my project for working with database (MySQL).
Recently I've got an error which says:

org.springframework.orm.jpa.JpaObjectRetrievalFailureException: Unable to find com.kanda.mindwire.domain.results.CognitiveResult with id 1700; nested exception is javax.persistence.EntityNotFoundException: Unable to find com.kanda.mindwire.domain.results.CognitiveResult with id 1700

at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:379) ~[spring-orm-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:257) ~[spring-orm-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528) ~[spring-orm-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61) ~[spring-tx-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242) ~[spring-tx-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153) ~[spring-tx-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:149) ~[spring-data-jpa-2.2.3.RELEASE.jar:2.2.3.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at com.sun.proxy.$Proxy157.findByCompany(Unknown Source) ~[na:na]
at com.kanda.mindwire.service.employee.EmployeeService.findWithFilter(EmployeeService.java:210) ~[classes/:1.0-SNAPSHOT]

The code is trying to fetch the list of Employee entity which is having a OneToOne relation with CognitiveResult. I was thinking that it might be that there are Employee row with cognitive_id=1700 but when I query my db I see that there are no such row.

The question is from where hibernate takes this id and how to fix it?

Here is my code:
Employee.java

@Table(uniqueConstraints = @UniqueConstraint(columnNames = {Employee_.EMAIL}))
@Entity
@Data
public class Employee extends BaseEmployee {

@Column
private String email;
....
@ManyToOne
@JoinColumn(name = &quot;company_id&quot;)
private Company company;
    
@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = &quot;cognitive_id&quot;, referencedColumnName = &quot;id&quot;)
private CognitiveResult cognitiveResult;
...
}

CognitiveResult.java

@Entity
@Table(name = &quot;cognitive_results&quot;)
@Data
public class CognitiveResult extends BaseAssesment {
...

@OneToOne(mappedBy = &quot;cognitiveResult&quot;)
private Employee employee;

@PreRemove
public void removeCognitiveForEmployee() {
    if (employee != null) {
        employee.setCognitiveResult(null);
    }
}
...
}

EmployeeRepository.java

public interface EmployeeRepository extends BaseRepository&lt;Employee&gt; {
...
    List&lt;Employee&gt; findByCompany(Company company);
...
}

Company.java

@Entity
@Data
public class Company extends BaseSettingsEntity {
...
@OneToMany(mappedBy = &quot;company&quot;, cascade = CascadeType.ALL)
private Set&lt;Employee&gt; employees = new HashSet&lt;&gt;();
/**
 * Logic for syncing employees
 * @param employee
 */
 public void removeEmployee(Employee employee) {
    if (!employees.contains(employee)) {
        return;
    }

    employees.remove(employee);
    employee.setCompany(null);
 }

 public void addEmployee(Employee employee) {
    if (employees.contains(employee)) {
         return;
    }

    employees.add(employee);
    employee.setCompany(this);
 }
...
}

All of my domain models inherit from BaseEntity.java

@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Entity
@Data
public abstract class BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
@Column(updatable = false, nullable = false)
protected Long id;
...
}

And the exception occurs while calling findByCompany:

@Slf4j
public class EmployeeService extends BaseEntityService&lt;Employee&gt; {

private final EmployeeRepository repo;

public Map&lt;String, Map&lt;EmployeeJob, List&lt;Employee&gt;&gt;&gt; findWithFilter(EmployeeFilterWrapper filter, String username) {
    List&lt;Employee&gt; employeeList;
    User user = userService.findByUsername(username);
    Company company = user.getCompany();
    if (company == null)
        throw new InvalidCompanyException(&quot;Company not assigned for a user!&quot;);

    if (filter != null &amp;&amp; filter.getDivisionsFilter() != null &amp;&amp; CollectionUtils.isNotEmpty(filter.getDivisionsFilter().getDivisions())) {
        employeeList = repo.findEmployeeByDivisionNamesAndCompany(filter.getDivisionsFilter().getDivisions(), company.getName());
    } else {
        employeeList = repo.findByCompany(company);
    }
...
}

答案1

得分: 0

发现了一个问题。另一张表中有一个指向缺失 cognitive_id 的链接,这是因为我最近直接在数据库中清除了这些实体,但忘记了它们引用了其他表。
这是一个继承自 EmployeeSupervisors 表。

@Entity
@Table(name = "supervisors")
@Data
public class Supervisor extends Employee {
...
}
英文:

Found an issue. There where a link to missing cognitive_id in another table and it is missing because I was clearing those entites directly in db recently, but forgot that they reference other table.
It was a Supervisors table which is inherited from Employee

@Entity
@Table(name = &quot;supervisors&quot;)
@Data
public class Supervisor extends Employee {
...
}

huangapple
  • 本文由 发表于 2020年5月4日 22:22:54
  • 转载请务必保留本文链接:https://java.coder-hub.com/61594478.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定