* bael-7718

* feedback updates

* PR feedback

---------

Co-authored-by: technoddy <mail.technoddy@gmail.com>
This commit is contained in:
Sam 2024-04-20 11:55:29 -04:00 committed by GitHub
parent 9e0ad0a0c7
commit 8012a0a62a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 307 additions and 5 deletions

View File

@ -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>

View File

@ -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 + '}';
}
}

View File

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

View File

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

View File

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

View File

@ -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

View File

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

View File

@ -0,0 +1 @@
logging.level.net.ttddyy.dsproxy.listener=debug

View File

@ -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