To be honest if this is a very large batch you are better off with
JDBC. This is not the type of thing ORM's excel at. You might look and see if your database has some sort of
Upsert functionality.
Otherwise if you are set on using an ORM for this you will find in the documentation (assuming hibernate here) recommendations for improving performance and memory usage. This includes disabling 2nd level cache and setting the hibernate.jdbc.batch_size to the same size as your procedure batch size.
The code you posted is fine for a batch insert but you have updates too. This is not going to be efficient by just changing it to merge. If you see the documentation they recommend loading database records into memory one by one using a cursor (you are not going to accomplish this with JPA) and flushing the batch and clearing the context at set intervals similarly to what you do above (except above you do not have the need to load the object) . You can also think about using a stored procedure.
Remember merge will look in the persistence context for the object if it does not exist it goes to the database. This results in an extra select as well. You can't just change persist to merge and expect things to be performant.