[JAVA] Spring Data JPA save select-insert n'est qu'une insertion

phénomène

Si vous spécifiez explicitement l'id dans spring-data-jpa et faites enregistrer '' '', sélectionnez-le comme indiqué dans le journal ci-dessous, puis insérez-le.

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 (?, ?)

C'est le comportement de jpa de sélectionner si l'id a déjà été persistant, puis de l'insérer. Cependant, dans certains traitements par lots, il peut être clair que l'identifiant n'existe pas en tant que spécification. Dans ce cas, select est juste inutile et je veux l'empêcher. Voici comment empêcher cette présélection.

Code source

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()
}

Ajoutez une propriété pour vérifier le SQL émis en interne.

src/main/resources/application.properties


spring.jpa.show-sql=true

Classe d'entité. `` Persistable '' '' sera décrit plus tard.

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);
	}

}

Journal d'exécution

Lorsque le code ci-dessus est exécuté, il passe au journal SQL suivant.

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

Commentaire

Le save``` de spring-data-jpa passe essentiellement par le `` SimpleJpaRepository # save '' suivant, et son implémentation est la suivante.

SimpleJpaRepository


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

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

Par défaut, isNew est `false```, donc il devient` `ʻem.merge```, résultant en une insertion sélective. Ce comportement peut être modifié en implémentant Persistable '' dans la classe d'entité. Cette fois, je veux empêcher la présélection, c'est-à-dire laisser JPA la reconnaître comme une nouvelle entité, donc j'essaye de renvoyer isNew à `` `true```.

Recommended Posts

Spring Data JPA save select-insert n'est qu'une insertion
[spring] Utilisons Spring Data JPA
[Comment installer Spring Data Jpa]
Sortie du journal Spring Data JPA SQL
Existe en utilisant la spécification dans Spring Data JPA
Jackson ne peut pas sérialiser JSON hibernateLazyInitializer dans Spring Data JPA entraîne une erreur
Référence mutuelle de l'entité de Spring Data JPA et ses notes
Trier par Spring Data JPA (avec tri par clé composée)
Création d'un référentiel commun avec Spring Data JPA
Spring Boot + Spring Data JPA À propos des jointures de table multiples
Un mémorandum lors de l'essai de Spring Data JPA avec STS
J'ai essayé de démarrer avec Spring Data JPA
Jusqu'à l'utilisation de Spring Data et JPA Part 2
Jusqu'à l'utilisation de Spring Data et JPA Part 1
Créer la variable de clause where dans Spring Data JPA