JAVA-66: New module spring-data-jpa-annotations

This commit is contained in:
sampadawagde
2020-07-19 14:29:41 +05:30
parent bf1e2c09f7
commit 92b1c62c1a
37 changed files with 1495 additions and 0 deletions
@@ -0,0 +1,72 @@
/**
*
*/
package com.baeldung.boot.ddd.event;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import com.baeldung.boot.ddd.event.Aggregate2;
import com.baeldung.boot.ddd.event.Aggregate2Repository;
import com.baeldung.boot.ddd.event.DomainEvent;
@SpringJUnitConfig
@SpringBootTest
class Aggregate2EventsIntegrationTest {
@MockBean
private TestEventHandler eventHandler;
@Autowired
private Aggregate2Repository repository;
// @formatter:off
@DisplayName("given aggregate with @AfterDomainEventPublication,"
+ " when do domain operation and save twice,"
+ " then an event is published only for the first time")
// @formatter:on
@Test
void afterDomainEvents() {
// given
Aggregate2 aggregate = new Aggregate2();
// when
aggregate.domainOperation();
repository.save(aggregate);
repository.save(aggregate);
// then
verify(eventHandler, times(1)).handleEvent(any(DomainEvent.class));
}
@BeforeEach
void beforeEach() {
repository.deleteAll();
}
// @formatter:off
@DisplayName("given aggregate with @DomainEvents,"
+ " when do domain operation and save,"
+ " then an event is published")
// @formatter:on
@Test
void domainEvents() {
// given
Aggregate2 aggregate = new Aggregate2();
// when
aggregate.domainOperation();
repository.save(aggregate);
// then
verify(eventHandler, times(1)).handleEvent(any(DomainEvent.class));
}
}
@@ -0,0 +1,67 @@
/**
*
*/
package com.baeldung.boot.ddd.event;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import com.baeldung.boot.ddd.event.Aggregate3;
import com.baeldung.boot.ddd.event.Aggregate3Repository;
import com.baeldung.boot.ddd.event.DomainEvent;
@SpringJUnitConfig
@SpringBootTest
class Aggregate3EventsIntegrationTest {
@MockBean
private TestEventHandler eventHandler;
@Autowired
private Aggregate3Repository repository;
// @formatter:off
@DisplayName("given aggregate extending AbstractAggregateRoot,"
+ " when do domain operation and save twice,"
+ " then an event is published only for the first time")
// @formatter:on
@Test
void afterDomainEvents() {
// given
Aggregate3 aggregate = new Aggregate3();
// when
aggregate.domainOperation();
repository.save(aggregate);
repository.save(aggregate);
// then
verify(eventHandler, times(1)).handleEvent(any(DomainEvent.class));
}
// @formatter:off
@DisplayName("given aggregate extending AbstractAggregateRoot,"
+ " when do domain operation and save,"
+ " then an event is published")
// @formatter:on
@Test
void domainEvents() {
// given
Aggregate3 aggregate = new Aggregate3();
// when
aggregate.domainOperation();
repository.save(aggregate);
// then
verify(eventHandler, times(1)).handleEvent(any(DomainEvent.class));
}
}
@@ -0,0 +1,87 @@
package com.baeldung.boot.ddd.event;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import com.baeldung.boot.ddd.event.Aggregate;
import com.baeldung.boot.ddd.event.AggregateRepository;
import com.baeldung.boot.ddd.event.DomainEvent;
import com.baeldung.boot.ddd.event.DomainService;
@SpringJUnitConfig
@SpringBootTest
class AggregateEventsIntegrationTest {
@Autowired
private DomainService domainService;
@MockBean
private TestEventHandler eventHandler;
@Autowired
private ApplicationEventPublisher eventPublisher;
@Autowired
private AggregateRepository repository;
// @formatter:off
@DisplayName("given existing aggregate,"
+ " when do domain operation directly on aggregate,"
+ " then domain event is NOT published")
// @formatter:on
@Test
void aggregateEventsTest() {
Aggregate existingDomainEntity = new Aggregate(0, eventPublisher);
repository.save(existingDomainEntity);
// when
repository.findById(existingDomainEntity.getId())
.get()
.domainOperation();
// then
verifyZeroInteractions(eventHandler);
}
@BeforeEach
void beforeEach() {
repository.deleteAll();
}
// @formatter:off
@DisplayName("given existing aggregate,"
+ " when do domain operation on service,"
+ " then domain event is published")
// @formatter:on
@Test
void serviceEventsTest() {
Aggregate existingDomainEntity = new Aggregate(1, eventPublisher);
repository.save(existingDomainEntity);
// when
domainService.serviceDomainOperation(existingDomainEntity.getId());
// then
verify(eventHandler, times(1)).handleEvent(any(DomainEvent.class));
}
@TestConfiguration
public static class TestConfig {
@Bean
public DomainService domainService(AggregateRepository repository, ApplicationEventPublisher eventPublisher) {
return new DomainService(repository, eventPublisher);
}
}
}
@@ -0,0 +1,14 @@
/**
*
*/
package com.baeldung.boot.ddd.event;
import org.springframework.transaction.event.TransactionalEventListener;
import com.baeldung.boot.ddd.event.DomainEvent;
interface TestEventHandler {
@TransactionalEventListener
void handleEvent(DomainEvent event);
}
@@ -0,0 +1,64 @@
package com.baeldung.composite.repository;
import com.baeldung.composite.BookApplication;
import com.baeldung.composite.entity.Book;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertEquals;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = BookApplication.class)
public class BookRepositoryIntegrationTest {
public static final String JAVA_101 = "Java101";
public static final String JANE = "Jane";
public static final String TECH = "Tech";
@Autowired
BookRepository repository;
@Before
public void setUp() {
Book book1 = new Book("John", JAVA_101, TECH, 20);
Book book2 = new Book(JANE, JAVA_101, "Arch", 25);
Book book3 = new Book(JANE, "Scala101", TECH, 23);
repository.saveAll(Arrays.asList(book1, book2, book3));
}
@After
public void tearDown() {
repository.deleteAll();
}
@Test
public void testFindByName() {
List<Book> books = repository.findByIdName(JAVA_101);
assertEquals(2, books.size());
}
@Test
public void testFindByAuthor() {
List<Book> books = repository.findByIdAuthor(JANE);
assertEquals(2, books.size());
}
@Test
public void testFindByGenre() {
List<Book> books = repository.findByGenre(TECH);
assertEquals(2, books.size());
}
}
@@ -0,0 +1,125 @@
package com.baeldung.embeddable;
import com.baeldung.Application;
import com.baeldung.embeddable.model.Company;
import com.baeldung.embeddable.model.ContactPerson;
import com.baeldung.embeddable.repositories.CompanyRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import static org.junit.Assert.assertEquals;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Application.class})
public class EmbeddableIntegrationTest {
@Autowired
private CompanyRepository companyRepository;
@Test
@Transactional
public void whenInsertingCompany_thenEmbeddedContactPersonDetailsAreMapped() {
ContactPerson contactPerson = new ContactPerson();
contactPerson.setFirstName("First");
contactPerson.setLastName("Last");
contactPerson.setPhone("123-456-789");
Company company = new Company();
company.setName("Company");
company.setAddress("1st street");
company.setPhone("987-654-321");
company.setContactPerson(contactPerson);
companyRepository.save(company);
Company result = companyRepository.getOne(company.getId());
assertEquals("Company", result.getName());
assertEquals("1st street", result.getAddress());
assertEquals("987-654-321", result.getPhone());
assertEquals("First", result.getContactPerson().getFirstName());
assertEquals("Last", result.getContactPerson().getLastName());
assertEquals("123-456-789", result.getContactPerson().getPhone());
}
@Test
@Transactional
public void whenFindingCompanyByContactPersonAttribute_thenCompanyIsReturnedProperly() {
ContactPerson contactPerson = new ContactPerson();
contactPerson.setFirstName("Name");
contactPerson.setLastName("Last");
contactPerson.setPhone("123-456-789");
Company company = new Company();
company.setName("Company");
company.setAddress("1st street");
company.setPhone("987-654-321");
company.setContactPerson(contactPerson);
companyRepository.save(company);
List<Company> result = companyRepository.findByContactPersonFirstName("Name");
assertEquals(1, result.size());
result = companyRepository.findByContactPersonFirstName("FirstName");
assertEquals(0, result.size());
}
@Test
@Transactional
public void whenFindingCompanyByContactPersonAttributeWithJPQL_thenCompanyIsReturnedProperly() {
ContactPerson contactPerson = new ContactPerson();
contactPerson.setFirstName("@QueryName");
contactPerson.setLastName("Last");
contactPerson.setPhone("123-456-789");
Company company = new Company();
company.setName("Company");
company.setAddress("1st street");
company.setPhone("987-654-321");
company.setContactPerson(contactPerson);
companyRepository.save(company);
List<Company> result = companyRepository.findByContactPersonFirstNameWithJPQL("@QueryName");
assertEquals(1, result.size());
result = companyRepository.findByContactPersonFirstNameWithJPQL("FirstName");
assertEquals(0, result.size());
}
@Test
@Transactional
public void whenFindingCompanyByContactPersonAttributeWithNativeQuery_thenCompanyIsReturnedProperly() {
ContactPerson contactPerson = new ContactPerson();
contactPerson.setFirstName("NativeQueryName");
contactPerson.setLastName("Last");
contactPerson.setPhone("123-456-789");
Company company = new Company();
company.setName("Company");
company.setAddress("1st street");
company.setPhone("987-654-321");
company.setContactPerson(contactPerson);
companyRepository.save(company);
List<Company> result = companyRepository.findByContactPersonFirstNameWithNativeQuery("NativeQueryName");
assertEquals(1, result.size());
result = companyRepository.findByContactPersonFirstNameWithNativeQuery("FirstName");
assertEquals(0, result.size());
}
}
@@ -0,0 +1,152 @@
package com.baeldung.tx;
import com.baeldung.tx.model.Payment;
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.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import javax.persistence.EntityManager;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.transaction.annotation.Propagation.NOT_SUPPORTED;
@DataJpaTest
@ActiveProfiles("test")
@Transactional(propagation = NOT_SUPPORTED)
class ManualTransactionIntegrationTest {
@Autowired
private PlatformTransactionManager transactionManager;
@Autowired
private EntityManager entityManager;
private TransactionTemplate transactionTemplate;
@BeforeEach
void setUp() {
transactionTemplate = new TransactionTemplate(transactionManager);
}
@AfterEach
void flushDb() {
transactionTemplate.execute(status -> entityManager
.createQuery("delete from Payment")
.executeUpdate());
}
@Test
void givenAPayment_WhenNotDuplicate_ThenShouldCommit() {
Long id = transactionTemplate.execute(status -> {
Payment payment = new Payment();
payment.setAmount(1000L);
payment.setReferenceNumber("Ref-1");
payment.setState(Payment.State.SUCCESSFUL);
entityManager.persist(payment);
return payment.getId();
});
Payment payment = entityManager.find(Payment.class, id);
assertThat(payment).isNotNull();
}
@Test
void givenAPayment_WhenMarkAsRollback_ThenShouldRollback() {
transactionTemplate.execute(status -> {
Payment payment = new Payment();
payment.setAmount(1000L);
payment.setReferenceNumber("Ref-1");
payment.setState(Payment.State.SUCCESSFUL);
entityManager.persist(payment);
status.setRollbackOnly();
return payment.getId();
});
assertThat(entityManager
.createQuery("select p from Payment p", Payment.class)
.getResultList()).isEmpty();
}
@Test
void givenTwoPayments_WhenRefIsDuplicate_ThenShouldRollback() {
try {
transactionTemplate.execute(s -> {
Payment first = new Payment();
first.setAmount(1000L);
first.setReferenceNumber("Ref-1");
first.setState(Payment.State.SUCCESSFUL);
Payment second = new Payment();
second.setAmount(2000L);
second.setReferenceNumber("Ref-1");
second.setState(Payment.State.SUCCESSFUL);
entityManager.persist(first);
entityManager.persist(second);
return "Ref-1";
});
} catch (Exception ignored) {
}
assertThat(entityManager
.createQuery("select p from Payment p", Payment.class)
.getResultList()).isEmpty();
}
@Test
void givenAPayment_WhenNotExpectingAnyResult_ThenShouldCommit() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
Payment payment = new Payment();
payment.setReferenceNumber("Ref-1");
payment.setState(Payment.State.SUCCESSFUL);
entityManager.persist(payment);
}
});
assertThat(entityManager
.createQuery("select p from Payment p", Payment.class)
.getResultList()).hasSize(1);
}
@Test
void givenAPayment_WhenUsingTxManager_ThenShouldCommit() {
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
definition.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
definition.setTimeout(3);
TransactionStatus status = transactionManager.getTransaction(definition);
try {
Payment payment = new Payment();
payment.setReferenceNumber("Ref-1");
payment.setState(Payment.State.SUCCESSFUL);
entityManager.persist(payment);
transactionManager.commit(status);
} catch (Exception ex) {
transactionManager.rollback(status);
}
assertThat(entityManager
.createQuery("select p from Payment p", Payment.class)
.getResultList()).hasSize(1);
}
}
@@ -0,0 +1,80 @@
package lifecycleevents;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.baeldung.lifecycleevents.SpringBootLifecycleEventApplication;
import com.baeldung.lifecycleevents.model.User;
import com.baeldung.lifecycleevents.repository.UserRepository;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringBootLifecycleEventApplication.class)
public class UserRepositoryIntegrationTest {
@Autowired
private UserRepository userRepository;
@Before
public void setup() {
User user = new User();
user.setFirstName("Jane");
user.setLastName("Smith");
user.setUserName("jsmith123");
userRepository.save(user);
}
@After
public void cleanup() {
userRepository.deleteAll();
}
@Test
public void whenNewUserProvided_userIsAdded() {
User user = new User();
user.setFirstName("John");
user.setLastName("Doe");
user.setUserName("jdoe123");
user = userRepository.save(user);
assertTrue(user.getId() > 0);
}
@Test
public void whenUserNameProvided_userIsLoaded() {
User user = userRepository.findByUserName("jsmith123");
assertNotNull(user);
assertEquals("jsmith123", user.getUserName());
}
@Test
public void whenExistingUserProvided_userIsUpdated() {
User user = userRepository.findByUserName("jsmith123");
user.setFirstName("Joe");
user = userRepository.save(user);
assertEquals("Joe", user.getFirstName());
}
@Test
public void whenExistingUserDeleted_userIsDeleted() {
User user = userRepository.findByUserName("jsmith123");
userRepository.delete(user);
user = userRepository.findByUserName("jsmith123");
assertNull(user);
}
@Test
public void whenExistingUserLoaded_fullNameIsAvailable() {
String expectedFullName = "Jane Smith";
User user = userRepository.findByUserName("jsmith123");
assertEquals(expectedFullName, user.getFullName());
}
}