Spring Data JPA save select-insert is only insert

phenomenon

If you explicitly specify the id in spring-data-jpa and do `` `save```, select it as shown in the log below and then insert it.

Sample newEntity = new Sample(1L, "name");
repository.save(newEntity);
Hibernate: select sample0_.id as id1_0_0_, sample0_.name as name2_0_0_ from sample sample0_ where sample0_.id=?
Hibernate: insert into sample (name, id) values (?, ?)

It is the behavior of jpa to select whether the id has already been persisted and then insert it. However, in some batch processing etc., it may be clear that the id does not exist as a specification. In this case, select is just useless and I want to prevent it. Below is how to prevent this pre-select.

Source code

build.gradle


plugins {
  id 'org.springframework.boot' version '2.3.3.RELEASE'
  id 'io.spring.dependency-management' version '1.0.10.RELEASE'
  id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
  compileOnly {
    extendsFrom annotationProcessor
  }
}
repositories {
  mavenCentral()
}
dependencies {
  implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
  compileOnly 'org.projectlombok:lombok'
  runtimeOnly 'com.h2database:h2'
  annotationProcessor 'org.projectlombok:lombok'
  testImplementation('org.springframework.boot:spring-boot-starter-test') {
    exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
  }
}
test {
  useJUnitPlatform()
}

Add a property to check the internally issued SQL.

src/main/resources/application.properties


spring.jpa.show-sql=true

Entity class. `Persistable` will be described later.

import javax.persistence.Entity;
import javax.persistence.Id;

import org.springframework.data.domain.Persistable;

import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

@NoArgsConstructor
@AllArgsConstructor
@Entity
public class Sample implements Persistable<Long> {
	@Id
	Long id;

	String name;

	@Override
	public Long getId() {
		return id;
	}

	@Override
	public boolean isNew() {
		return true;
	}
}
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface SampleRepository extends JpaRepository<Sample, Long> {

}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.Transactional;

@EnableJpaRepositories
@SpringBootApplication
public class JpaSample implements CommandLineRunner {
	public static void main(String[] args) {
		SpringApplication.run(JpaSample.class, args);
	}

	@Autowired
	SampleRepository repository;
	
	@Transactional
	@Override
	public void run(String... args) throws Exception {
		Sample newEntity = new Sample(1L, "name");
		repository.save(newEntity);
	}

}

Execution log

When the above code is executed, it changes to the following SQL log.

Hibernate: insert into sample (name, id) values (?, ?)

Commentary

The save of spring-data-jpa basically passes through the following `` `SimpleJpaRepository # save```, and its implementation is as follows.

SimpleJpaRepository


	public <S extends T> S save(S entity) {

		if (entityInformation.isNew(entity)) {
			em.persist(entity);
			return entity;
		} else {
			return em.merge(entity);
		}
	}

By default, isNew is `false```, so it becomes ```em.merge```, resulting in select-insert. This behavior can be changed by implementing Persistable``` in the entity class. This time, I want to prevent pre-select, that is, let JPA recognize it as a new entity, so I am trying to return `` isNew to `` `true.

Recommended Posts

Spring Data JPA save select-insert is only insert
[spring] Let's use Spring Data JPA
[How to install Spring Data Jpa]
Spring Data JPA SQL log output
Exists using Specification in Spring Data JPA
Jackson is unable to JSON serialize hibernateLazyInitializer in Spring Data JPA with error
Spring Data JPA Entity cross-reference and its notes
Sort by Spring Data JPA (with compound key sort)
Creating a common repository with Spring Data JPA
Spring Boot + Spring Data JPA About multiple table joins
A memorandum when trying Spring Data JPA with STS
I tried to get started with Spring Data JPA
Until the use of Spring Data and JPA Part 2
Until the use of Spring Data and JPA Part 1
Make the where clause variable in Spring Data JPA