Frühjahr JpaRepositroy.save() nicht erscheinen zu werfen Ausnahme auf duplizieren spart
Ich bin derzeit spielen etwa auf Spring boot 1.4.2 in die ich gezogen haben, in Spring-boot-starter-web-und Spring-boot-starter-PPV.
Mein Hauptproblem ist dass ich beim speichern einer neuen Person funktioniert es einwandfrei (alle cool).
Aber wenn ich speichern eines neuen product-Entität mit der gleichen id (zB ein doppelter Eintrag), ist es nicht eine exception werfen. Ich hatte erwartet, ConstrintViolationException oder etwas ähnliches.
Gegeben, die folgenden eingerichtet:
Application.java
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
ProductRepository.java
@Repository
public interface ProductRepository extends JpaRepository<Product, String> {}
JpaConfig.java
@Configuration
@EnableJpaRepositories(basePackages = "com.verric.jpa.repository" )
@EntityScan(basePackageClasses ="com.verric.jpa")
@EnableTransactionManagement
public class JpaConfig {
@Bean
JpaTransactionManager transactionManager() {
return new JpaTransactionManager();
}
}
Hinweis JpaConfig.java und Application.java sind im gleichen Paket.
ProductController.java
@RestController
@RequestMapping(path = "/product")
public class ProductController {
@Autowired
ProductRepository productRepository;
@PostMapping("createProduct")
public void handle(@RequestBody @Valid CreateProductRequest request) {
Product product = new Product(request.getId(), request.getName(), request.getPrice(), request.isTaxable());
try {
productRepository.save(product);
} catch (DataAccessException ex) {
System.out.println(ex.getCause().getMessage());
}
}
}
und schließlich Product.java
@Entity(name = "product")
@Getter
@Setter
@AllArgsConstructor
@EqualsAndHashCode(of = "id")
public class Product {
protected Product() { /* jpa constructor*/ }
@Id
private String id;
@Column
private String name;
@Column
private Long price;
@Column
private Boolean taxable;
}
Den getter -, setter-und equalsHashcode.. sind lombok Anmerkungen.
Sonstiges:
Spring boot : 1.4.2
Hibernate ORM: 5.2.2.LETZTE
Dieses Problem tritt unabhängig davon, ob ich mit dem controller mit oder ohne @Transactional
Der zugrunde liegende db zeigt die Ausnahme klar
2016-11-15 18:03:49 AEDT [40794-1] verric@stuff ERROR: duplicate key value violates unique constraint "product_pkey"
2016-11-15 18:03:49 AEDT [40794-2] verric@stuff DETAIL: Key (id)=(test001) already exists
Ich weiß, dass ist besser (häufiger) zu brechen, die die data access Zeug in seine eigene service-Ebene statt dumping es in der Steuerung
Die Semantik der controller nicht ReST
Dinge, die ich versucht habe:
Frühjahr CrudRepository Ausnahmen
Habe ich versucht, die Umsetzung der Antwort aus diese Frage, leider ist mein code nie trifft die DataAccesException Ausnahme
Tut Spring JPA wirft einen Fehler wenn die Funktion speichern nicht erfolgreich ist?
Wieder ähnliche Antwort auf die obige Frage.
http://www.baeldung.com/spring-dataIntegrityviolationexception
Habe ich versucht, indem die Bohne, um meine JPAconfig.java Klasse:
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
return new PersistenceExceptionTranslationPostProcessor();
}
Aber nichts schien zu passieren.
Sorry für den langen post, ty im Voraus
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich denke, Sie sind bewusst
CrudRepository.save()
wird für insert-und update -. Wenn eine Id nicht vorhanden, dann wird es als eine Beilage, wenn Id vorhanden ist wird es als update. Erhalten Sie möglicherweise eine Ausnahme aus, wenn Ihre senden Sie die Id als null.Da Sie nicht über alle anderen Anmerkungen, abgesehen von
@Id
auf Ihreid
variable, um Die Eindeutige Id-Erzeugung behandelt werden müssen, von Ihrem code Oder was Sie brauchen, um machen Verwendung von@GeneratedValue
annotation.Meine Lösung ist viel sauberer. Spring Data bietet bereits einen schönen Weg für uns, um zu definieren, wie ein Unternehmen als neu. Dies kann leicht getan werden, indem die Umsetzung
Persistente
auf unser Unternehmen als dokumentiert in der Referenz.In meinem Fall, wie ist die OP ' s, die IDs aus einer externen Quelle stammen und nicht automatisch generiert. Also die Standard-Logik verwendet, die von Frühjahr Daten zu prüfen, die eine Entität als neu, wenn die ID null ist, hätte nicht funktioniert.
Hier habe ich einen Mechanismus für die Person zu äußern, ob es hält wird sich neue oder nicht mittels anderer vorübergehender Boolesche Eigenschaft namens
update
. Als Standard-Wert vonupdate
wirdfalse
alle Entitäten dieses Typs sind als neu und wird in einemDataIntegrityViolationException
geworfen, wenn Sie versuchen, rufenrepository.save(entity)
mit der gleichen ID.Wenn Sie möchten, führen Sie einen Seriendruck, können Sie immer legen Sie die
update
Eigenschafttrue
bevor Sie versuchen, speichern. Natürlich, wenn Sie Ihre use-case nie verlangt, Sie zu aktualisieren Entitäten, Sie können immer wiedertrue
von derisNew
Methode und loszuwerden, dieupdate
Feld.Die Vorteile dieses Ansatzes, der über die Prüfung, ob ein Unternehmen mit der gleichen ID existiert bereits in der Datenbank vor dem speichern gibt es viele:
Aufbauen Shazins zu beantworten und zu klären. die CrudRepositroy.save() oder JpaRespository.saveAndFlush() beide delegieren, um die folgende Methode
SimpleJpaRepository.java
Daher, wenn ein Benutzer versucht, erstellen ein neues Unternehmen, das so geschieht, haben die gleiche id wie eine bereits vorhandene Entität, Feder Daten nur aktualisieren, dass die Entität.
Zu erreichen, was ich ursprünglich wollte, das einzige, was ich finden konnte, war die fallen wieder nach unten zu JPA allein, das ist
Hier, wenn wir versuchen zu bestehen und neue Person mit einer id, die bereits in der Datenbank, die Sie werfen wird werfen werden die constraint-Verletzung Ausnahme, wie wir ursprünglich wollten.
repository.exists(id)
vor dem Aufrufsave()
funktionieren würde, aber ehrlich gesagt die einfachste Methode dürfte sein, ein zusätzliches automatisch generierte Schlüssel und fügt dann eine unique-Einschränkung auf Ihr domain-Typ-Taste.