I want to save a lot of Spring JPA entities by importing them in batches to the database. Some entities have ManyToOne relations to other Entities. As there is a large amount of data, I'd prefer not to keep track of all of the related entities in memory to be set as ManyToOne relations for other entities. I just have the id of the relation, not a persisted entity.
I've encountered the following suggestion a few times as a solution for setting the relation anyway:
{
@ManyToOne
@JoinColumn(name = "author_id")
private Author author;
...
public void setAuthorId(Long authorId) {
Author author = new Author();
author.setId(authorId);
this.author = author;
}
So using a transient object as a placeholder for relating one entity to another. (assuming the related object gets saved as one of the other objects passed to the saveAll() call)
I see no reference of this approach at all in the official Spring documentation.
Is this considered a supported way to save relations based on just the id or would you say it's just a dirty hack?
Using a transient object as a placeholder
My team was using such approach in production a lot working with Hibernate (without Spring Data). Didn't have any issues with it.
Drawbacks
Spring-data uses
merge()inside repositorysave()method. Hibernate will generate additional (unnecessary) databaseSELECTquery, to update a transient object state.You can use a custom repository with
persist()/update()methods to avoid an additionalSELECTquery. Described here:The best Spring Data JpaRepository
Using getReferenceById() (since 2.7) / getReference() methods
We are using this approach a lot. It doesn't cause any additional database queries, if you get a reference and save an entity using the same persistent context (
@Transactionalscope).Drawbacks
We need a repository to use
getReferenceById()method. For example, you can't use this approach in a transient utility method of entity, likesetAuthorId().Using stateless session
Hibernate’s StatelessSession – What it is and how to use it
Using a custom repository with JdbcTemplate
To insert a lot of records better to use low level batch with SQL. We are using this approach a lot in production. Don't forget to add
rewriteBatchedStatements=trueto the connection URL, if you use MySQL.