I have a domain object in Spring which I am saving using JpaRepository.save method and using Sequence generator from Postgres to generate id automatically.
@SequenceGenerator(initialValue = 1, name = "device_metric_gen", sequenceName = "device_metric_seq")
public class DeviceMetric extends BaseTimeModel {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "device_metric_gen")
@Column(nullable = false, updatable = false)
private Long id;
///// extra fields
My use-case requires to do an upsert
instead of normal save
operation (which I am aware will update if the id is present). I want to update an existing row if a combination of three columns (assume a composite unique) is present or else create a new row.
This is something similar to this:
INSERT INTO customers (name, email)
VALUES
(
'Microsoft',
'hotline@microsoft.com'
)
ON CONFLICT (name)
DO
UPDATE
SET email = EXCLUDED.email || ';' || customers.email;
One way of achieving the same in Spring-data that I can think of is:
- Write a custom save operation in the service layer that
- Does a get for the three-column and if a row is present
- Set the same id in current object and do a repository.save
- If no row present, do a normal repository.save
Problem with the above approach is that every insert
now does a select
and then save
which makes two database calls whereas the same can be achieved by postgres insert on conflict
feature with just one db call.
Any pointers on how to implement this in Spring Data?
One way is to write a native query insert into values (all fields here)
. The object in question has around 25 fields so I am looking for an another better way to achieve the same.