Spring JPA 创建新记录而不是更新现有记录

Tim*_*gel 5 spring-data-jpa spring-boot

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

关于我做错了什么有什么建议吗?

谢谢,蒂莫西

软件版本

  • 春季启动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()
}
Run Code Online (Sandbox Code Playgroud)

服务层中的保存方法

@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);
    }
Run Code Online (Sandbox Code Playgroud)

日志输出

  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 (...)
Run Code Online (Sandbox Code Playgroud)

Roa*_* S. 8

你需要使用

var inDb = dcRepo.findOne(motorToBeSaved.getId());
Run Code Online (Sandbox Code Playgroud)

更新该实例,然后调用

dcRepo.save(inDb);
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用EntityManager /sf/answers/4404760461/