bael-7718 (#16256)
* bael-7718 * feedback updates * PR feedback --------- Co-authored-by: technoddy <mail.technoddy@gmail.com>
This commit is contained in:
parent
9e0ad0a0c7
commit
8012a0a62a
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-data-jpa-query-4</artifactId>
|
||||
<name>spring-data-jpa-query-4</name>
|
||||
|
@ -27,6 +27,11 @@
|
|||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.gavlyukovskiy</groupId>
|
||||
<artifactId>datasource-proxy-spring-boot-starter</artifactId>
|
||||
<version>${datasource-proxy.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
|
@ -37,9 +42,20 @@
|
|||
<version>${postgresql.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<properties>
|
||||
<postgresql.version>42.7.1</postgresql.version>
|
||||
<datasource-proxy.version>1.9.1</datasource-proxy.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,58 @@
|
|||
package com.baeldung.spring.data.jpa.upsert;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
@Entity
|
||||
@Table(name = "credit_card")
|
||||
public class CreditCard {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "credit_card_id_seq")
|
||||
@SequenceGenerator(name = "credit_card_id_seq", sequenceName = "credit_card_id_seq", allocationSize = 1)
|
||||
private Long id;
|
||||
private String cardNumber;
|
||||
private String expiryDate;
|
||||
|
||||
private Long customerId;
|
||||
|
||||
public Long getCustomerId() {
|
||||
return customerId;
|
||||
}
|
||||
|
||||
public void setCustomerId(Long customerId) {
|
||||
this.customerId = customerId;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getCardNumber() {
|
||||
return cardNumber;
|
||||
}
|
||||
|
||||
public void setCardNumber(String cardNumber) {
|
||||
this.cardNumber = cardNumber;
|
||||
}
|
||||
|
||||
public String getExpiryDate() {
|
||||
return expiryDate;
|
||||
}
|
||||
|
||||
public void setExpiryDate(String expiryDate) {
|
||||
this.expiryDate = expiryDate;
|
||||
}
|
||||
|
||||
public CreditCard() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CreditCard{" + "id=" + id + ", cardNumber='" + cardNumber + '\'' + ", expiryDate='" + expiryDate + '\'' + ", customerId=" + customerId + '}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package com.baeldung.spring.data.jpa.upsert;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class CreditCardLogic {
|
||||
|
||||
@Autowired
|
||||
private CreditCardRepository creditCardRepository;
|
||||
|
||||
@Autowired
|
||||
private EntityManager em;
|
||||
|
||||
public void updateOrInsertUsingCustomLogic(CreditCard creditCard) {
|
||||
CreditCard existingCard = creditCardRepository.findByCardNumber(creditCard.getCardNumber());
|
||||
if (existingCard != null) {
|
||||
existingCard.setExpiryDate(creditCard.getExpiryDate());
|
||||
creditCardRepository.save(creditCard);
|
||||
} else {
|
||||
creditCardRepository.save(creditCard);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void updateOrInsertUsingBuiltInFeature(CreditCard creditCard) {
|
||||
Long id = creditCard.getId();
|
||||
if (creditCard.getId() == null) {
|
||||
BigInteger nextVal = (BigInteger) em.createNativeQuery("SELECT nextval('credit_card_id_seq')")
|
||||
.getSingleResult();
|
||||
id = nextVal.longValue();
|
||||
}
|
||||
|
||||
String upsertQuery = """
|
||||
MERGE INTO credit_card (id, card_number, expiry_date, customer_id)
|
||||
KEY(card_number)
|
||||
VALUES (?, ?, ?, ?)
|
||||
""";
|
||||
|
||||
Query query = em.createNativeQuery(upsertQuery);
|
||||
query.setParameter(1, id);
|
||||
query.setParameter(2, creditCard.getCardNumber());
|
||||
query.setParameter(3, creditCard.getExpiryDate());
|
||||
query.setParameter(4, creditCard.getCustomerId());
|
||||
|
||||
query.executeUpdate();
|
||||
}
|
||||
|
||||
public void updateOrInsertUsingRepository(CreditCard creditCard) {
|
||||
creditCardRepository.updateOrInsert(creditCard);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.spring.data.jpa.upsert;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
public interface CreditCardRepository extends JpaRepository<CreditCard, Long> {
|
||||
@Transactional
|
||||
default CreditCard updateOrInsert(CreditCard entity) {
|
||||
return save(entity);
|
||||
}
|
||||
|
||||
CreditCard findByCardNumber(String cardNumber);
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package com.baeldung.spring.data.jpa.upsert;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class UpsertApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(UpsertApplication.class, args);
|
||||
}
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
spring.jpa.defer-datasource-initialization=true
|
||||
logging.level.net.ttddyy.dsproxy.listener=debug
|
||||
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
|
||||
spring.datasource.username=postgres
|
||||
spring.datasource.password=
|
||||
|
@ -7,4 +9,4 @@ spring.jpa.show-sql=true
|
|||
|
||||
logging.level.org.hibernate.SQL=DEBUG
|
||||
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
|
||||
spring.jpa.properties.hibernate.format_sql=true
|
||||
spring.jpa.properties.hibernate.format_sql=true
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
package com.baeldung.spring.data.jpa.upsert;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@SpringBootTest(classes = UpsertApplication.class)
|
||||
public class UpdateOrInsertUnitTest {
|
||||
|
||||
@Autowired
|
||||
private CreditCardRepository creditCardRepository;
|
||||
|
||||
@Autowired
|
||||
private CreditCardLogic creditCardLogic;
|
||||
|
||||
private CreditCard existingCard = null;
|
||||
|
||||
@BeforeEach
|
||||
public void create() {
|
||||
existingCard = createAndReturnCreditCards();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void clean() {
|
||||
creditCardRepository.deleteAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenCreditCards_whenUpdateOrInsertUsingRepositoryExecuted_thenUpserted() {
|
||||
// insert test
|
||||
CreditCard newCreditCard = buildCreditCard();
|
||||
CreditCard existingCardByCardNumber = creditCardRepository.findByCardNumber(newCreditCard.getCardNumber());
|
||||
assertNull(existingCardByCardNumber);
|
||||
|
||||
creditCardLogic.updateOrInsertUsingRepository(newCreditCard);
|
||||
|
||||
existingCardByCardNumber = creditCardRepository.findByCardNumber(newCreditCard.getCardNumber());
|
||||
assertNotNull(existingCardByCardNumber);
|
||||
|
||||
// update test
|
||||
CreditCard cardForUpdate = existingCard;
|
||||
String beforeExpiryDate = cardForUpdate.getExpiryDate();
|
||||
cardForUpdate.setExpiryDate("2029-08-29");
|
||||
existingCardByCardNumber = creditCardRepository.findByCardNumber(cardForUpdate.getCardNumber());
|
||||
assertNotNull(existingCardByCardNumber);
|
||||
|
||||
creditCardLogic.updateOrInsertUsingRepository(cardForUpdate);
|
||||
|
||||
assertNotEquals("2029-08-29", beforeExpiryDate);
|
||||
CreditCard updatedCard = creditCardRepository.findById(cardForUpdate.getId()).get();
|
||||
assertEquals("2029-08-29", updatedCard.getExpiryDate());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenCreditCards_whenUpdateOrInsertUsingCustomLogicExecuted_thenUpserted() {
|
||||
// insert test
|
||||
CreditCard newCreditCard = buildCreditCard();
|
||||
CreditCard existingCardByCardNumber = creditCardRepository.findByCardNumber(newCreditCard.getCardNumber());
|
||||
assertNull(existingCardByCardNumber);
|
||||
|
||||
creditCardLogic.updateOrInsertUsingCustomLogic(newCreditCard);
|
||||
|
||||
existingCardByCardNumber = creditCardRepository.findByCardNumber(newCreditCard.getCardNumber());
|
||||
assertNotNull(existingCardByCardNumber);
|
||||
|
||||
// update test
|
||||
CreditCard cardForUpdate = existingCard;
|
||||
String beforeExpiryDate = cardForUpdate.getExpiryDate();
|
||||
cardForUpdate.setExpiryDate("2029-08-29");
|
||||
|
||||
creditCardLogic.updateOrInsertUsingCustomLogic(cardForUpdate);
|
||||
|
||||
assertNotEquals("2029-08-29", beforeExpiryDate);
|
||||
CreditCard updatedCard = creditCardRepository.findById(cardForUpdate.getId()).get();
|
||||
assertEquals("2029-08-29", updatedCard.getExpiryDate());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenCreditCards_whenUpdateOrInsertUsingBuiltInFeatureExecuted_thenUpserted() {
|
||||
// insert test
|
||||
CreditCard newCreditCard = buildCreditCard();
|
||||
CreditCard existingCardByCardNumber = creditCardRepository.findByCardNumber(newCreditCard.getCardNumber());
|
||||
assertNull(existingCardByCardNumber);
|
||||
|
||||
creditCardLogic.updateOrInsertUsingBuiltInFeature(newCreditCard);
|
||||
|
||||
existingCardByCardNumber = creditCardRepository.findByCardNumber(newCreditCard.getCardNumber());
|
||||
assertNotNull(existingCardByCardNumber);
|
||||
|
||||
// update test
|
||||
CreditCard cardForUpdate = existingCard;
|
||||
String beforeExpiryDate = cardForUpdate.getExpiryDate();
|
||||
cardForUpdate.setExpiryDate("2029-08-29");
|
||||
|
||||
creditCardLogic.updateOrInsertUsingBuiltInFeature(cardForUpdate);
|
||||
|
||||
assertNotEquals("2029-08-29", beforeExpiryDate);
|
||||
CreditCard updatedCard = creditCardRepository.findById(cardForUpdate.getId()).get();
|
||||
assertEquals("2029-08-29", updatedCard.getExpiryDate());
|
||||
}
|
||||
|
||||
private CreditCard buildCreditCard() {
|
||||
CreditCard card = new CreditCard();
|
||||
card.setCardNumber("9994323432112222");
|
||||
card.setExpiryDate("2024-06-21");
|
||||
card.setCustomerId(10L);
|
||||
|
||||
return card;
|
||||
}
|
||||
|
||||
private CreditCard createAndReturnCreditCards() {
|
||||
CreditCard card = new CreditCard();
|
||||
card.setCardNumber("3494323432112222");
|
||||
card.setExpiryDate("2024-06-21");
|
||||
card.setCustomerId(10L);
|
||||
return creditCardRepository.save(card);
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
logging.level.net.ttddyy.dsproxy.listener=debug
|
|
@ -0,0 +1,8 @@
|
|||
jdbc.driverClassName=org.h2.Driver
|
||||
jdbc.url=jdbc:h2:mem:test
|
||||
jdbc.user=sa
|
||||
jdbc.pass=
|
||||
|
||||
hibernate.dialect=org.hibernate.dialect.H2Dialect
|
||||
hibernate.show_sql=false
|
||||
hibernate.hbm2ddl.auto=create-drop
|
Loading…
Reference in New Issue