У меня имеется такая вот сущность:
@Data
@Entity
public class Message {
@Id
private long id;
private String recipient;
private String subject;
private String text;
private boolean sent;
private String status;
@Column(name = "expire")
@CreationTimestamp
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss")
private Date expire;
@Column(name = "updated_at")
@CreationTimestamp
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss")
private Date updatedAt;
@Column(name = "created_at")
@CreationTimestamp
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss")
private Date createdAt;
@PreUpdate
protected void onUpdate() {
updatedAt = new Date();
}
}
И такой тестовый контроллер:
@RestController
public class MessageTestController {
@Autowired
private MessageService messageService;
@RequestMapping("/testMessage")
public Message testMessage(@RequestBody Message message) {
System.out.println(message.getId());
System.out.println(message.getRecipient());
System.out.println(message.getStatus());
System.out.println(message.getSubject());
messageService.save(message);
return messageService.findById(0);
}
}
Проблема в том, при отправке контроллеру json в таком формате
{
"id": 0,
"recipient": "samoilov.s@natalie-tours.ru",
"subject": "some subject",
"text": null,
"sent": false,
"status": "NOT NOW 2",
"expire": "2017-06-27 09:42:41",
"updatedAt": "2017-06-27 09:48:27",
"createdAt": "2017-06-27 09:42:41"
}
возникает такая ошибка
ERROR: duplicate key value violates unique constraint "message_pkey"
Но если я сделаю messageService.findById(0) и потом save полученного элемента, то update произойдет успешно. Почему так ?
Если над id поставить аннотацию @GeneratedValue(strategy=GenerationType.IDENTITY), то будет происходить insert новых записей с новым id, но не update. При этом в json я передаю id напрямую.
когда Вы делаете сначала messageService.save(message);, то объект message неперсистный, а new (или Transient) и HIBERNATE полагает, что Вы создали новый объект и в БД его нет. Поэтому Hibernate делает insert. Он не делает предварительную проверку есть ли объект с ID=0 в БД. А когда Вы сначала сделаете find, то HIBERNATE создаст в кэше персистный объект с ID=0 и при save будет понимать, что объект с id=0 уже есть и надо делать update.
Попробуйти использовать утилиту, для просмотра содержимого кэша перед и после вызовов этих двух методов в разных порядках.
Содержимое кэша
Как развивать веб-проекты в 2026 году: технологии, контент E-E-A-T и факторы доверия
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники