Reputation: 10956
Given a table:
CREATE TABLE mytable (
some_id BIGINT PRIMARY KEY NOT NULL,
timestamp TIMESTAMP WITH TIME ZONE NOT NULL
);
An entity:
@Entity
@Table(name = "mytable")
class Thing(
@Id
var some_id: Long,
var timestamp = ZonedDateTime.now()
)
A repository:
interface MyRepo : JpaRepository<Thing, Long>
And this loop:
val myRepo: MyRepo
while (True) {
val some_id: Long = ComesFromSomewhere()
if (myRepo.findById(some_id) == null) {
myRepo.save(Thing(some_id))
}
}
The intention is to only store a timestamp for an ID the first time this ID occurs.
The code above works, but results in over 100 save
transactions per second in my use case, which puts heavy load on the DB. So I'd like to optimize, accumulate a batch of Thing
s and then use something like saveAll
to have everything in one transaction.
Just using saveAll
however would also overwrite the timestamps of the IDs already present in the table, which is not intended.
How can this be solved, ideally without too much low-level code?
Upvotes: 0
Views: 70
Reputation: 1221
If you put the above loop within a @Transactional method, you should have only 1 transaction - with lots of INSERT-s and SELECT-s, of course, but 1 transaction. This would relieve the burden on the DB.
Also, save() is the proper method to call in this case. There's also a method called saveAndFlush() which is the opposite of what you want.
You could also limit the number of SELECTs by doing repo.findAllById() instead of lots of findById().
Upvotes: 1