【问题标题】:Nested entities contains null after save嵌套实体在保存后包含 null
【发布时间】:2022-01-14 11:27:10
【问题描述】:

我有一个像这样的嵌套实体的实体

public class MyEntity {
    @ManyToOne
    @JoinColumn(name="FK_ENTITY2")
    private Entity2 fkEntity2;

    @ManyToOne
    @JoinColumn(name="FK_ENTITY3")
    private Entity3 fkEntity3;
}

entity2 和 entity3 像这样:

public class Entity2/3{
   @Id
   private Long id;
   
   @Column(name = "code")
   private String code;
   
   @Column(name = "desc")
   private String desc;

   //getter and setter etc
}

Entity2Entity3 的值都存储在数据库中,所以当我在 MyEntity 上进行插入时,我正在这样做:

@Transactional
@Service
public MyService {
  //idFromController and otherIdFromController refers to existent records in the database
  public MyDto save(Long idFromController, Long otherIdFromController){
    Entity2 entity2 = new Entity2();
    entity2.setId(idFromController);

    Entity3 entity3 = new Entity3();
    entity3.setId(otherIdFromController);

    MyEntity newMyEntity = new MyEntity();
    newMyEntity.setEntity2(entity2);
    newMyEntity.setEntity3(entity3);

    MyEntity result = myEntityRepository.saveAndFlush(newMyEntity);

    return getDto(result);
  }

}

它工作正常,数据使用正确的外键正确存储在数据库中但是...... 插入后,我想构建一个 DTO,其中包含来自嵌套实体的 id、code 和 desc,如下所示:

private MyDto getDto(MyEntity result){
  MyDto dto = new MyDto();
  dto.setId2(result.getEntity2().getId()); 
  dto.setCode2(result.getEntity2().getCode()); 
  dto.setDesc2(result.getEntity2().getDesc()); 

  dto.setId3(result.getEntity3().getId()); 
  dto.setCode3(result.getEntity3().getCode()); 
  dto.setDesc3(result.getEntity3().getDesc()); 
}

这就是问题所在,我只得到了 id 字段和 null 的代码和描述。

当我在搜索中调用getDto() 时,它可以工作并且每个字段都有正确的值,所以它与插入事务有关吗?我该如何解决?

【问题讨论】:

  • 设置断点并调试...
  • 我假设,您的代码不完整..例如你有用@Entity注释的所有必要的类吗?
  • 垃圾进,垃圾出。实体是 pojo,因此如果您没有填充要关联到新 MyEntity 的 Entity3/Entity2 实例中的值,您将获得相同的 MyEntity 实例及其引用。您需要从数据库中刷新实例以强制重新加载。尝试使用 em.refresh(myEntity) 并返回结果,但最好使用 find 调用读取 entity2/3 实例,并在 saveAndFlush 调用之前使用它来设置引用。

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


【解决方案1】:

当你创建 DTO 时,(现有的)实体并没有附加到持久化上下文,所以相应的数据还没有从 DB 中加载,无法复制到 DTO。

一种选择是加载实体,例如通过 'myRepository.findById...' 并关联返回的(托管)实体。

【讨论】:

  • 在嵌套实体上使用 findById 我能够检索数据,我将进行更多调查并尝试了解是否可以在持久性上下文中刷新实体
【解决方案2】:

您错过了多对一关系的某些部分。首先在 MyEntity 类中,最好定义一个获取类型。在Entity2Entity3 中,您需要将@OneToMany 定义为与获取类型声明和cascade = CascadeType.ALL 关系的另一端,它只是告诉休眠它可以在您执行保存、删除时对相关实体执行的操作,更新。我将您的代码重新格式化如下

public class Entity2/3{
   @Id
   private Long id;
   
   @Column(name = "code")
   private String code;
   
   @Column(name = "desc")
   private String desc;

    @OneToMany(cascade = CascadeType.ALL,mappedBy ="fkEntity2",fetch=FetchType.LAZY)
private List<Entity2> entityTwoList;
// for Entity3
@OneToMany(cascade = CascadeType.ALL,mappedBy ="fkEntity3",fetch=FetchType.LAZY)
private List<Entity3> entityThreeList;

public class MyEntity {
  @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="FK_ENTITY2")
    private Entity2 fkEntity2;

   @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="FK_ENTITY3")
    private Entity3 fkEntity3;
}
}

【讨论】:

    猜你喜欢
    • 2017-08-31
    • 1970-01-01
    • 2011-11-02
    • 1970-01-01
    • 2021-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多