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"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
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">
|
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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>spring-data-jpa-query-4</artifactId>
|
<artifactId>spring-data-jpa-query-4</artifactId>
|
||||||
<name>spring-data-jpa-query-4</name>
|
<name>spring-data-jpa-query-4</name>
|
||||||
@ -27,6 +27,11 @@
|
|||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.gavlyukovskiy</groupId>
|
||||||
|
<artifactId>datasource-proxy-spring-boot-starter</artifactId>
|
||||||
|
<version>${datasource-proxy.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.h2database</groupId>
|
<groupId>com.h2database</groupId>
|
||||||
<artifactId>h2</artifactId>
|
<artifactId>h2</artifactId>
|
||||||
@ -37,9 +42,20 @@
|
|||||||
<version>${postgresql.version}</version>
|
<version>${postgresql.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</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>
|
<properties>
|
||||||
<postgresql.version>42.7.1</postgresql.version>
|
<postgresql.version>42.7.1</postgresql.version>
|
||||||
|
<datasource-proxy.version>1.9.1</datasource-proxy.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</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.url=jdbc:postgresql://localhost:5432/postgres
|
||||||
spring.datasource.username=postgres
|
spring.datasource.username=postgres
|
||||||
spring.datasource.password=
|
spring.datasource.password=
|
||||||
@ -7,4 +9,4 @@ spring.jpa.show-sql=true
|
|||||||
|
|
||||||
logging.level.org.hibernate.SQL=DEBUG
|
logging.level.org.hibernate.SQL=DEBUG
|
||||||
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
|
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…
x
Reference in New Issue
Block a user