Spring Data CrudRepository(Hibernate)的findOne方法返回null。

3

我无法通过ID找到现有的实体,具体原因未知。

该实体具有以下视图:

@Entity
@Table(name = "persons")
@NamedEntityGraph(name = "includeRemunerationAndCredential",attributeNodes = {
    @NamedAttributeNode("remunerations"),
    @NamedAttributeNode("credentials")
})
@JsonSerialize
public class Person implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@Column(name = "first_name", nullable = false, length = 50)
@NotNull
private String firstName;

@Column(name= "second_name",  nullable = false, length = 50)
@NotNull
private String secondName;

@Column(name = "father_name", length = 50)
private String fatherName;

@Column(name = "phone_number", length = 20)
private String phoneNumber;

@Column(name = "date_of_birth")
private LocalDateTime dateOfBirth;

@Column(name = "role", nullable = false, length = 50)
@Enumerated(EnumType.STRING)
private Role role;

@Column(name = "date_of_creation", nullable = false)
@NotNull
private LocalDateTime dateOfCreation;

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "carwash")
private CarWash carWash;

@OneToMany(fetch = FetchType.LAZY, mappedBy = "person")
private List<Remuneration> remunerations;

@OneToMany(fetch = FetchType.LAZY, mappedBy = "person")
private Set<Credential> credentials;

@Column(name = "enable", nullable = false)
private Boolean enable;

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "owner", nullable = false)
private Owner owner;

// getters and setters

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    Person person = (Person) o;

    return id != null ? id.equals(person.id) : person.id == null;

}

@Override
public int hashCode() {
    return id != null ? id.hashCode() : 0;
}

@Override
public String toString() {
    return "Person{" +
            "id=" + id +
            ", firstName='" + firstName + '\'' +
            ", secondName='" + secondName + '\'' +
            ", fatherName='" + fatherName + '\'' +
            ", phoneNumber='" + phoneNumber + '\'' +
            ", dateOfBirth=" + dateOfBirth +
            ", role=" + role +
            ", dateOfCreation=" + dateOfCreation +
            ", carWash=" + (carWash == null ? carWash : carWash.getId()) +
            ", remunerations=" + (remunerations == null ? remunerations : remunerations.size()) +
            ", enable=" + enable +
            ", owner=" + (owner == null ? "N/A" : owner.getName()) +
            '}';
}

我的DAO有以下视图:

public interface PersonDAO extends CrudRepository<Person, Long> {}

我的服务由这个类提供。
@Service("userDetailsService")
@Transactional
public class MyUserDetailService implements UserDetailsService {

@Autowired
PersonDAO personDAO;

@Override
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
    //final Iterable<Person> all = personDAO.findAll();
    final Person one = personDAO.findOne(15L);

    return null;
}

如果在服务中注释掉personDAO.findAll(),那么personDAO.findOne(15L)将返回null,但是如果取消对findAll()的注释,则可以找到findOne(15L)。如何修复这个问题,使得findOne能够在不执行findAll()的情况下工作?


为什么你返回 null? - Amer Qarabsa
2
显然,持久化的ID不是15。证明它 - 展示你的数据库。 - Abhijit Sarkar
我只是返回null来减少方法的大小。无论如何,它对Spring Data没有任何影响。 - Bizon4ik
数据是如何进入数据库的?它已经在那里了吗?还是通过其他代码插入的?如果是后者,请向我们展示该代码。 - Jens Schauder
听起来好像findAll可能会触发一次flush。 - Jens Schauder
1个回答

0

我几天前遇到了完全相同的问题,后来发现原因是我检索的实体有一个对另一个实体的外键引用,而该实体又有另一个对第三个实体的外键引用,而这些引用中的最后一个被配置为不可为空。但问题在于,当在数据库中检查所查找的项时,外键实际上具有空值;因此,当持久性框架将服务转换为查询时,它会进行内部连接而不是外部连接,这将从结果中删除实体,因为第二个和第三个实体之间的连接由于空值而失败。

在第二个实体字段中删除上述描述的不可为空子句可以解决检索第一个实体的服务中的问题。

请检查您的实体是否没有以类似的方式映射:例如,我可以看到实体Person具有对实体Owner的外键引用,该引用不可为空;也许owner为空,这就是问题所在?如果不为空,请检查所有其他外键引用,然后检查所有内部引用链以及其他第三方实体,以确保您没有在其中一个字段中强制执行非空,而相关列实际上是可为空的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接