【问题标题】:Why can't a column be set to null using JPA?为什么不能使用 JPA 将列设置为空?
【发布时间】:2020-04-16 15:09:10
【问题描述】:

让我们从这个实体开始:

@Entity
public class MyEntity {
  ...
  @Column(length = 80)
  private String description;

  @Column(name = "enum_column", precision = 18)
  @Convert(converter = EnumColumnConverter.class)
  private MyEnum enumColumn;
  ...
}

在这里,您会看到两个可以为空的列(在我的实体和数据库中)。转换器将枚举替换为数据库中的 Long 值。相应地定义了一个存储库类:

@Repository
public interface MyEntityRepository extends JpaRepository<MyEntity, Long> {}

DTO 是从服务包中定义的:

public class MyEntityDto {
  ...
  private String description;
  private MyEnum enumColumn;
  ...
}

DTO 和实体之间的映射是使用 Dozer 完成的。 DTO 是从 Java FX UI 修改的。在 UI 和持久性之间定义了一个服务来保存修改的实体。

@Service
@Transactional
public class MyEntityService {
  @Autowired MyEntityRepository myEntityRepository;

  ...

  public List<MyEntityDto> save(List<MyEntityDto> dtosToSave) {
    List<MyEntityDto> results = Collections.emptyList();

    if (dtosToSave != null && !dtosToSave.empty()) {
      Iterable<MyEntity> entities = convertDtosWithDozer(dtosToSave);
      List<MyEntity> savedEntities = myEntityRepository.saveAll(entities);
      results = convertEntitiesWithDozer(savedEntities);
    }
    return results;
}

在 UI 中,我修改了现有行,其中 descriptionenumColumn 都不是 null。这两个值都设置为null

问题是它们都没有在数据库中设置为null。在日志中,Hibernate 生成的update 请求不包括这些列。当我调试代码时,这些列是 dtosToSaveentitiessavedEntitiesresults 中的 null

我为MyEntityRepository 创建了一个单元测试,我在其中保存了一个非空descriptionentityColumn 的实体。我使用存储库从数据库重新加载实体,以确保这些列不为空。我将它们设置为null,保存实体,然后从数据库中加载回来。现在这两列确实是null,这正是我所期待的。

我的问题:我在这里缺少什么?为什么存储库不保存null 列?如果我设置任何非 null 值,它会完美运行。

提前致谢。

更新:我的问题可能与此有关吗? Jpa Repository save() doesn't update existing data

【问题讨论】:

  • 为什么要使用这个转换器?它有什么作用?
  • @CodeScale 正如我提到的,转换器用于将数据库中的枚举替换为 long。我们目前正在更新软件。数据库中允许进行最少的修改。并且有很多遗留代码使用这些信息。但这不是问题...
  • @CodeScale 我选择了这两列,但可能是其他列。
  • 在您的存储库中,您将 Long 定义为 Pk 类型。在您的实体中看不到 Id 吗?
  • @CodeScale 是的,有一个 id。如果您注意到,该类的内容以“...”开头和结尾,这意味着还有其他列和方法。我省略了它们,因为我认为没有必要用它们来描述问题。我想展示一个列有问题的示例。如果没有看到一个 id 并假设有一个,真的会令人困惑吗?您要我添加整个实体吗?正好有 43 列,包括一个 ID……如果你真的想要,我可以做到。

标签: java hibernate jpa


【解决方案1】:

您通过推土机将您的 dto 转换为实体,但此时实体仍处于分离状态...。要更新现有实体,您首先需要通过存储库通过数据库加载它们。类似repository.findById(Id id);

然后您将获得处于“附加”状态的实体,因此将应用状态转换(字段更新)。

save() 期间,您的所有实体状态转换都将转换为相应的 DML,您的更新现在应该可以工作了。

关于此声明

 I reload the entity from the database using the repository to be sure these columns are not null. I set them to null, save the entity, and load it back from the database. Now both columns are indeed null, which is what I've been expecting.

正如你所说的you reload entity from the database,它可以工作

【讨论】:

    猜你喜欢
    • 2021-10-12
    • 1970-01-01
    • 1970-01-01
    • 2017-10-31
    • 1970-01-01
    • 2020-07-21
    • 2011-03-17
    • 2020-12-03
    • 2012-08-14
    相关资源
    最近更新 更多