【问题标题】:Problem with saving foreign key with @OneToOne annotation. Saving as null使用 @OneToOne 注释保存外键的问题。保存为空
【发布时间】:2020-12-05 17:43:57
【问题描述】:

我有两个实体(ProjectOtherData)和一个抽象实体。我正在使用 MySQL 和 Quarkus 框架。

问题:当我尝试保存 Project 实体字段时,project_id 仍然是 null

表架构:



在下一张图片中显示,“project_other_data”表中的 fk 约束:

抽象实体

@MappedSuperclass
public class AbstractEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected Long id;

    // getters and setters
}

项目实体

@Entity
@Table(name = "projects")
public class Project extends AbstractEntity {

    @NotNull
    @Column(name = "name")
    private String name;

    @NotNull
    @Column(name = "surname")
    private String surname;

    @Column(name = "date_create")
    @JsonbDateFormat(value = "yyyy-MM-dd")
    private LocalDate dateCreate;

    @Column(name = "date_update")
    @JsonbDateFormat(value = "yyyy-MM-dd")
    private LocalDate dateUpdate;

    @OneToOne(mappedBy = "project", cascade = CascadeType.ALL)
    private OtherData otherData;

    // getters and setters
}

其他数据实体

@Entity
@Table(name = "project_other_data")
public class OtherData extends AbstractEntity {

    @OneToOne
    @JoinColumn(name = "project_id")
    private Project project;

    @Column(name = "days_in_year")
    private Integer daysInYear;

    @Column(name = "holidays_in_year")
    private Integer holidaysInYear;

    @Column(name = "weeks_in_year")
    private Integer weeksInYear;

    @Column(name = "free_saturdays")
    private Integer freeSaturdays;

    @Column(name = "downtime_coefficient")
    private BigDecimal downtimeCoefficient;

    @Column(name = "changes")
    private Integer changes;

    // getters and setters
}

用代码保存实体:

@Path("projects")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ProjectRest {

    @Inject
    ProjectService projectService;

    @POST
    public Response saveProject(Project project) {
        return Response.ok(projectService.saveProject(project)).build();
    }
}
@RequestScoped
@Transactional
public class ProjectService {

    @Inject
    EntityManager entityManager;

    public Project saveProject(Project project) {

        if (project.getId() == null) {
            entityManager.persist(project);
        } else {
            entityManager.merge(project);
        }

        return project;
    }
}

【问题讨论】:

  • 您第二次展示了 Project 类,而不是 OtherData 类。请添加OtherData 类的代码。
  • @Turing85,哦,对不起。没注意到。我刚刚编辑了它。
  • 你能把@JoinColumn(name = "project_id")修改成@JoinColumn(name = "project_id", referencedColumnName="id")吗?
  • 另外,您是自动生成表模式还是手动生成表模式?您似乎缺少表 project_other_data.project_id 上的外键约束。
  • @act_inGlasses 接受答案后无需编辑标题,请参见此处:meta.stackexchange.com/questions/116101/… Cheers!

标签: java one-to-one quarkus jpa-annotations


【解决方案1】:

我能够通过POST使用嵌入OtherData 的新Project 来重现该问题。我用于POST的body:

{
    "name": "John",
    "surname": "Doe",
    "otherData": {}
}

要点是:数据库实体也用作DTO。因此,请求正文的otherData 中的字段project 设置为null(因为没有传递Project,这将是一个递归无限定义)。

在处理从 rest 控制器到服务到存储库的实体期间,otherDataproject 永远不会设置。一个快速的解决方法是修改ProjectService::saveProject如下:

public Project saveProject(Project project) {
    project.getOtherData().setProject(project); // This line was added
    if (project.getId() == null) {
        entityManager.persist(project);
    } else {
        entityManager.merge(project);
    }

    return project;
}

这将解决数据库问题(project_id 将被设置),但会导致下一个问题。由于

,无法序列化响应正文

org.jboss.resteasy.spi.UnhandledException:javax.ws.rs.ProcessingException:RESTEASY008205:JSON 绑定序列化错误 javax.json.bind.JsonbException:无法从 com.nikitap.org_prod.entities 序列化属性“otherData” .项目

...

原因:javax.json.bind.JsonbException:在类 com.nikitap.org_prod.entities.Project 中找到递归引用。

对象结构是循环的(project 引用 otherData,返回引用 project,...)杰克逊无法解决这个循环。

要解决此问题,我建议将 DTO 和数据库实体分开并在它们之间显式映射。本质上:

  • 构建 Dto 对象以表示您希望以非循环顺序接收的 JSON 请求和响应
  • 将与 JSON 相关的注释从数据库实体类传输到 DTO 类
  • 在服务层或存储库层(您的选择)中,将 DTO 映射到数据库实体,设置所有字段(包括从 projectotherData 的引用,反之亦然)
  • 在同一层中,将数据库实体映射回非循环 DTO
  • 从 REST 端点返回 DTO

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-22
    相关资源
    最近更新 更多