3

As far as I undestood, JpaRepository save() method should update my entity in database.

I have a table in MySQL called REF_PERIOD with two columns only: code_id, which is INT and Primary Key, and code_name, which is VARCHAR.

This is my Entity:

@Data
@Entity
@Table(name = "REF_PERIOD")
public class PayRefPeriod {

    @Id
    @Column(name = "code_id")
    private int codeId;

    @Column(name = "code_name", length = 254, nullable = false)
    private String codeName;
}

My Repository:

@Repository
public interface PayRefPeriodRepository extends JpaRepository<PayRefPeriod, Integer> {

}

And the Controller:

@Slf4j
@RestController
@RequestMapping("/api")
public class PayRefPeriodController {

    @Autowired
    private PayRefPeriodRepository payRefPeriodRepository;

    // Get all pay reference periods
    @GetMapping("/payrefperiods")
    public List<PayRefPeriod> getAllPayRefPeriod() {
        return payRefPeriodRepository.findAll();
    }

    // Create a new pay reference period
    @PostMapping("/payrefperiods")
    public PayRefPeriod createPayRefPeriod(@Valid @RequestBody PayRefPeriod payRefPeriod) {
        return payRefPeriodRepository.save(payRefPeriod);
    }

    // Get a single pay reference period
    @GetMapping("/payrefperiods/{id}")
    public PayRefPeriod PayRefPeriod(@PathVariable(value = "id") int payRefPeriodId) {
        return payRefPeriodRepository.findById(payRefPeriodId)
                .orElseThrow(() -> new ResourceNotFoundException("PayRefPeriod", "id", payRefPeriodId));
    }

    // Update a pay reference period
    @PutMapping("/payrefperiods/{id}")
    public PayRefPeriod updatePayRefPeriod(@PathVariable(value = "id") int payRefPeriodId,
                                      @Valid @RequestBody PayRefPeriod payRefPeriodDetails) {

        PayRefPeriod payRefPeriod = payRefPeriodRepository.findById(payRefPeriodId)
                .orElseThrow(() -> new ResourceNotFoundException("PayRefPeriod", "id", payRefPeriodId));

        payRefPeriod.setCodeName(payRefPeriodDetails.getCodeName());

        log.debug(payRefPeriod.toString());

        return payRefPeriodRepository.save(payRefPeriod);
    }

    // Delete a pay reference period
    @DeleteMapping("/payrefperiods/{id}")
    public ResponseEntity<?> deletePayRefPeriod(@PathVariable(value = "id") int payRefPeriodId) {
        PayRefPeriod payRefPeriod = payRefPeriodRepository.findById(payRefPeriodId)
                .orElseThrow(() -> new ResourceNotFoundException("PayRefPeriod", "id", payRefPeriodId));

        payRefPeriodRepository.delete(payRefPeriod);

        return ResponseEntity.ok().build();
    }
}

I expect the updatePayRefPeriod method to update my entity (which has Id 0 in MySQL database), however it throws an exception: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '0' for key 'PRIMARY'.

What I'm doing wrong?

abarazal
  • 369
  • 6
  • 19
  • Seems like your I’d is not working, there is already an element with id 0. When you save an entity without any id then you need to have a sequence which increases that id for you. Which Database are you using? – arnonuem Jul 04 '19 at 22:00
  • Please check your ids in the database and in the debugger – arnonuem Jul 04 '19 at 22:28
  • Instead of using the save() method, you should use update() method – vatsal gosar Jul 04 '19 at 23:55
  • You shouldn't need that `@Repository` annotation. I don't know tho if that causes your problem. – Mirko Brandt Jul 05 '19 at 08:33
  • @arnonuem Yes, there's already an element with id 0. But I modified the "codeName" value, entity has change so save method should update the record... Database is MySQL – abarazal Jul 05 '19 at 16:41
  • @vatsalgosar There's no update() method for JpaRepository interface. – abarazal Jul 05 '19 at 17:27

2 Answers2

2

I suppose it might be a mysql driver specific limitation that for java primitive type int when we use it for identifier. I suggest you change the type of the codeId to its boxed object type Integer.

@Id
@Column(name = "code_id")
private Integer codeId;

Thus the underlying hibernate can understand the difference between a null identifier and not null but 0 valued identifier when it generates the corresponding update queries.

Yavuz Tas
  • 344
  • 3
  • 16
-2

Try adding sequenceGenerator and GeneratedValue to your id column.

@Data
@Entity
@Table(name = "REF_PERIOD")
public class PayRefPeriod {

@SequenceGenerator(name = "generator", sequenceName = "REF_PERIOD_ID_SEQ")
@GeneratedValue(strategy = GenerationType.AUTO, generator = "generator")
@Id
@Column(name = "code_id")
private int codeId;

@Column(name = "code_name", length = 254, nullable = false)
private String codeName;

}

kraskixxx
  • 89
  • 8
  • I don't want to add an auto generated value for my id column. I just want to modify the "codeName" value of an existing record. – abarazal Jul 05 '19 at 16:25