【问题标题】:Spring Data JPA mapping one-to-one relationship returns null valueSpring Data JPA 映射一对一关系返回空值
【发布时间】:2021-03-01 11:27:07
【问题描述】:

我正在制作 Spring Boot 后端,但遇到以下问题。当我从VersionableFileRepository 得到Software 并在其上调用getSystem 函数时,我在关系中得到了实际的System。但是当我从VersionableFileRepository 得到Documentation 时,它的getSystem 函数返回null。我以同样的方式处理SoftwareDocumentation,所有这些实例都有一个System

用代码说明:

versionableFileRepository.findById(fileId).get().getSystem()fileId 识别Software 时返回有效System,在Documentation 时返回null

怎么了?我在实现中搞砸了什么吗?

我有以下课程:

@Entity
public class System {

    @Id
    @GeneratedValue
    private long id;

    private String name;

    @OneToOne(cascade = CascadeType.REMOVE, orphanRemoval = true)
    @JoinColumn(name = "software_id", referencedColumnName = "id")
    private Software software;

    @OneToOne(cascade = CascadeType.REMOVE, orphanRemoval = true)
    @JoinColumn(name = "documentation_id", referencedColumnName = "id")
    private Documentation documentation;

    //other fields, getters and setters...
}
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class VersionableFile {
    
    @Id
    @GeneratedValue
    private long id;

    @OneToMany(mappedBy = "file", cascade = CascadeType.REMOVE, orphanRemoval = true)
    private List<FileVersion> versions = new ArrayList<>();

    public abstract System getSystem();

    public abstract void setSystem(System system);

    //getters and setters...

}
@Entity
public class Software extends VersionableFile {

    @OneToOne(mappedBy = "software")
    @JsonIgnore
    private System system;

    @Override
    public System getSystem() {
        return system;
    }

    @Override
    public void setSystem(System system) {
        this.system = system;
    }
}
@Entity
public class Documentation extends VersionableFile {

    @OneToOne(mappedBy = "documentation")
    @JsonIgnore
    private System system;

    @Override
    public System getSystem() {
        return system;
    }

    @Override
    public void setSystem(System system) {
        this.system = system;
    }
}
@Repository
public interface VersionableFileRepository extends CrudRepository<VersionableFile, Long> {
}

数据库:

数据库中的一切看起来都不错,这是system 表:

而对应的对象可以在另外两个表(softwaredocumentation)中找到。此外,还定义了适当的约束。

我认为这是一个 JPA 问题,因为当我从 SystemRepository(此处未提及)获得 System 对象时,它具有正确的 softwaredocumentation 字段。

提前感谢您的帮助!

【问题讨论】:

  • 发布您的数据库中确切存在的内容。如果它不存在或格式错误,则不是 JPA 问题
  • 感谢评论,我弥补了

标签: java spring jpa spring-data-jpa spring-data


【解决方案1】:

已经评论了,但看起来更好,我想我在这里找到了一些重要的东西。

提案 1

您的实体结构对我来说似乎不错。但是,您的 Java 代码存在一个重大问题,无法从数据库中检索这些实体。

versionableFileRepository.findById(fileId).get().getSystem()

fileIddocumentId 是纯长数字。 JPA 如何知道您是要检索软件还是文档?这行不通。正如您所构建的那样,它将具有单独的表 Documentation 和 Software,并且每个表都有一个列 Id 作为主键。

使用特定的存储库使 JPA 更容易

@Repository
public interface SoftwareRepository extends CrudRepository<Software, Long> {
}

然后检索软件只需使用softwareRepository.findById(id).get().getSystem()

@Repository
    public interface DocumentationRepository extends CrudRepository<Documentation, Long> {
    }

然后检索文档只需使用documentationRepository.findById(id).get().getSystem()

提案 2

如果您希望继续前进,那么我会认为该错误专门针对您生成的 ID。您希望案例文档和软件中的不同表具有不同的 ID。然后 JPA 可以从 Id 中区分您拥有的实体。

要实现这一点,您必须更改生成 ID 的策略

public abstract class VersionableFile {
    
    @Id
    @GeneratedValue( strategy = GenerationType.TABLE)
    private long id;

     ....  

【讨论】:

  • 感谢您的建议!我做了推荐的更改,但不幸的是它现在仍然不起作用。
  • 然后粘贴您的数据库记录的屏幕截图。可能有什么问题
  • 我已经修改了问题。它现在包含此信息。软件和文档表也有相应的记录。
猜你喜欢
  • 1970-01-01
  • 2021-09-15
  • 1970-01-01
  • 1970-01-01
  • 2020-12-17
  • 1970-01-01
  • 1970-01-01
  • 2020-11-30
  • 2020-07-10
相关资源
最近更新 更多