【问题标题】:Spring JPA creates new record instead of updating existing recordSpring JPA 创建新记录而不是更新现有记录
【发布时间】:2021-03-30 08:52:09
【问题描述】:

我正在使用标准 Spring CrudRepository。当尝试更新记录时,即使主键被分配了一个非空值,也会创建一条新记录。

对我做错了什么有什么建议吗?

谢谢, 提摩太

软件版本

  • Spring Boot 2.4.0
  • 数据库 postgres 9.6.17

要保存的实体

@Entity
@Table(name = "dc_motor")
public class DcMotor implements Serializable, DatabaseEntity {
    private static final long serialVersionUID = 4015060163435939638L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Version
    private Integer version;
    // other fields here
    // does NOT define equals() nor hashCode()
}

服务层中的保存方法

@Override
    public DcMotorRest saveMotor(DcMotorRest motorToBeSaved) throws MotorNotFoundException {
        if (motorToBeSaved.getId() != null) {

            Optional<DcMotor> motor = dcRepo.findById(motorToBeSaved.getId());

            if (!motor.isPresent())
                throw new MotorNotFoundException(
                        "DC Motor with ID [%d] not found.  Unable to update.  Use empty / null id to create a new DC Motor"
                                .formatted(motorToBeSaved.getId()));
        }

        // troubleshooting code
        DcMotor t = new DcMotor(motorToBeSaved);
        if (t.getId() == null) {
            logger.debug("ID is null in motor to be saved");
        } else {
            logger.debug("ID is [{}] in motor to be saved", t.getId());
        }
        DcMotor savedMotor = dcRepo.save(t);    // dcRepo extends CrudRepository<DcMotor, Long>

        // DcMotor savedMotor = new DcMotor(motorToBeSaved);

        return new ModelMapper().map(savedMotor, DcMotorRest.class);
    }

日志输出

  DEBUG 7868 --- [nio-8070-exec-1] c.e.s.w.service.impl.DcMotorServiceImpl  : ID is [2333] in motor to be saved
  DEBUG 7868 --- [nio-8070-exec-1] org.hibernate.SQL                        : insert into dc_motor ( ...) values (...)

【问题讨论】:

  • 您正在创建DcMotor 的新实例,并且您没有向我们展示您正在使用的构造函数的代码。请确保 t 在此行之后有 Id:DcMotor t = new DcMotor(motorToBeSaved);
  • 感谢您的点评!新输出“null”或 id 正下方的日志语句。在这种情况下,它的值是 2333。但是记录的 SQL 是一个插入。

标签: spring-boot spring-data-jpa


【解决方案1】:

是的,问题就在这里:

DcMotor t = new DcMotor(motorToBeSaved);

基本上它是你创建的一个对象,Hibernate 不知道它,所以它被认为是一个新对象。您需要先在数据库中找到该实体,对其进行更新然后保存。

【讨论】:

    【解决方案2】:

    你需要使用

    var inDb = dcRepo.findOne(motorToBeSaved.getId());
    

    更新该实例,然后调用

    dcRepo.save(inDb);
    

    另一种方法是使用EntityManager https://stackoverflow.com/a/62925149/14072498

    【讨论】:

      猜你喜欢
      • 2023-01-12
      • 2020-06-20
      • 2012-07-25
      • 2011-12-10
      • 1970-01-01
      • 2010-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多