Bael 7281 (#15494)
* BAEL-7281: When use getOne and findOne methods Spring Data JPA * BAEL-7281: Cleanup * BAEL-7281: Test rename * BAEL-7281: Fix not updated name
This commit is contained in:
parent
cf80b7c3d4
commit
e316c193a0
|
@ -0,0 +1,8 @@
|
|||
package com.baeldung.spring.data.persistence.findvsget;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class ApplicationConfig {
|
||||
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
package com.baeldung.spring.data.persistence.findvsget.entity;
|
||||
|
||||
import java.util.Objects;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "users")
|
||||
public class User {
|
||||
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
@Column(name = "first_name")
|
||||
private String firstName;
|
||||
@Column(name = "second_name")
|
||||
private String secondName;
|
||||
|
||||
public User() {
|
||||
}
|
||||
|
||||
public User(final Long id, final String firstName, final String secondName) {
|
||||
this.id = id;
|
||||
this.firstName = firstName;
|
||||
this.secondName = secondName;
|
||||
}
|
||||
|
||||
public void setId(final Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(final String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getSecondName() {
|
||||
return secondName;
|
||||
}
|
||||
|
||||
public void setSecondName(final String secondName) {
|
||||
this.secondName = secondName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final User user = (User) o;
|
||||
|
||||
if (!Objects.equals(id, user.id)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(firstName, user.firstName)) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(secondName, user.secondName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = id != null ? id.hashCode() : 0;
|
||||
result = 31 * result + (firstName != null ? firstName.hashCode() : 0);
|
||||
result = 31 * result + (secondName != null ? secondName.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "User{" +
|
||||
"id=" + id +
|
||||
", firstName='" + firstName + '\'' +
|
||||
", secondName='" + secondName + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.baeldung.spring.data.persistence.findvsget.repository;
|
||||
|
||||
import com.baeldung.spring.data.persistence.findvsget.entity.User;
|
||||
import java.util.Optional;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Repository
|
||||
public interface NewTransactionUserRepository extends JpaRepository<User, Long> {
|
||||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
User getReferenceById(Long id);
|
||||
|
||||
@Override
|
||||
Optional<User> findById(Long id);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.baeldung.spring.data.persistence.findvsget.repository;
|
||||
|
||||
import com.baeldung.spring.data.persistence.findvsget.entity.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface SimpleUserRepository extends JpaRepository<User, Long> {
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.baeldung.spring.data.persistence.findvsget.service;
|
||||
|
||||
import com.baeldung.spring.data.persistence.findvsget.entity.User;
|
||||
import com.baeldung.spring.data.persistence.findvsget.repository.SimpleUserRepository;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class NonTransactionalUserReferenceService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(NonTransactionalUserReferenceService.class);
|
||||
private SimpleUserRepository repository;
|
||||
|
||||
public User findUserReference(final long id) {
|
||||
log.info("Before requesting a user");
|
||||
final User user = repository.getReferenceById(id);
|
||||
log.info("After requesting a user");
|
||||
return user;
|
||||
}
|
||||
|
||||
public User findAndUseUserReference(final long id) {
|
||||
final User user = repository.getReferenceById(id);
|
||||
log.info("Before accessing a username");
|
||||
final String firstName = user.getFirstName();
|
||||
log.info("This message shouldn't be displayed because of the thrown exception: {}", firstName);
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setRepository(final SimpleUserRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.baeldung.spring.data.persistence.findvsget.service;
|
||||
|
||||
import com.baeldung.spring.data.persistence.findvsget.entity.User;
|
||||
import com.baeldung.spring.data.persistence.findvsget.repository.SimpleUserRepository;
|
||||
import java.util.Optional;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class SimpleUserService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SimpleUserService.class);
|
||||
private final SimpleUserRepository repository;
|
||||
|
||||
public SimpleUserService(final SimpleUserRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
public User findUser(final long id) {
|
||||
log.info("Before requesting a user in a findUser method");
|
||||
final Optional<User> optionalUser = repository.findById(id);
|
||||
log.info("After requesting a user in a findUser method");
|
||||
final User user = optionalUser.orElse(null);
|
||||
log.info("After unwrapping an optional in a findUser method");
|
||||
return user;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.baeldung.spring.data.persistence.findvsget.service;
|
||||
|
||||
import com.baeldung.spring.data.persistence.findvsget.entity.User;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class TransactionalUserReferenceService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(TransactionalUserReferenceService.class);
|
||||
private JpaRepository<User, Long> repository;
|
||||
|
||||
@Transactional
|
||||
public User findUserReference(final long id) {
|
||||
log.info("Before requesting a user");
|
||||
final User user = repository.getReferenceById(id);
|
||||
log.info("After requesting a user");
|
||||
return user;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public User findAndUseUserReference(final long id) {
|
||||
final User user = repository.getReferenceById(id);
|
||||
log.info("Before accessing a username");
|
||||
final String firstName = user.getFirstName();
|
||||
log.info("After accessing a username: {}", firstName);
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setRepository(final JpaRepository<User, Long> repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package com.baeldung.spring.data.persistence.findvsget;
|
||||
|
||||
import static com.baeldung.spring.data.persistence.findvsget.UserProvider.userSource;
|
||||
import static org.assertj.core.api.Assumptions.assumeThat;
|
||||
|
||||
import com.baeldung.spring.data.persistence.findvsget.entity.User;
|
||||
import com.baeldung.spring.data.persistence.findvsget.repository.SimpleUserRepository;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
@SpringBootTest(classes = ApplicationConfig.class, properties = {
|
||||
"spring.jpa.generate-ddl=true",
|
||||
"spring.jpa.show-sql=false"
|
||||
})
|
||||
abstract class DatabaseConfigurationBaseIntegrationTest {
|
||||
|
||||
private static final int NUMBER_OF_USERS = 10;
|
||||
|
||||
@Autowired
|
||||
private SimpleUserRepository repository;
|
||||
|
||||
@BeforeEach
|
||||
void populateDatabase() {
|
||||
final List<User> users = userSource()
|
||||
.map(Arguments::get)
|
||||
.map(s -> new User(((Long) s[0]), s[1].toString(), s[2].toString()))
|
||||
.collect(Collectors.toList());
|
||||
repository.saveAll(users);
|
||||
assumeThat(repository.findAll()).hasSize(NUMBER_OF_USERS);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void clearDatabase() {
|
||||
repository.deleteAll();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package com.baeldung.spring.data.persistence.findvsget;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.baeldung.spring.data.persistence.findvsget.entity.User;
|
||||
import com.baeldung.spring.data.persistence.findvsget.service.SimpleUserService;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ArgumentsSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@DisplayName("findBy test:")
|
||||
class FindUserIntegrationIntegrationTest extends DatabaseConfigurationBaseIntegrationTest {
|
||||
|
||||
|
||||
@Autowired
|
||||
private SimpleUserService service;
|
||||
|
||||
@ParameterizedTest
|
||||
@ArgumentsSource(UserProvider.class)
|
||||
@DisplayName("when looking for a user by an existing ID returns a user")
|
||||
void whenGettingUserByCorrectIdThenReturnUser(Long id, String firstName, String lastName) {
|
||||
final User expected = new User(id, firstName, lastName);
|
||||
final User actual = service.findUser(id);
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@DisplayName("when looking for a user by a non-existing ID returns null")
|
||||
@ValueSource(longs = {11, 12, 13})
|
||||
void whenGettingUserByIncorrectIdThenReturnNull(Long id) {
|
||||
assertThat(service.findUser(id)).isNull();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
package com.baeldung.spring.data.persistence.findvsget;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
import com.baeldung.spring.data.persistence.findvsget.entity.User;
|
||||
import com.baeldung.spring.data.persistence.findvsget.repository.NewTransactionUserRepository;
|
||||
import com.baeldung.spring.data.persistence.findvsget.repository.SimpleUserRepository;
|
||||
import com.baeldung.spring.data.persistence.findvsget.service.NonTransactionalUserReferenceService;
|
||||
import com.baeldung.spring.data.persistence.findvsget.service.TransactionalUserReferenceService;
|
||||
import org.hibernate.LazyInitializationException;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ArgumentsSource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
|
||||
@DisplayName("getReferenceBy test:")
|
||||
class GetReferenceIntegrationIntegrationTest extends DatabaseConfigurationBaseIntegrationTest {
|
||||
|
||||
private static final long EXISTING_ID = 1L;
|
||||
|
||||
@Nested
|
||||
@DisplayName("given non-transactional service, even if user exists")
|
||||
class GivenNonTransactionalService {
|
||||
|
||||
@Autowired
|
||||
private NonTransactionalUserReferenceService nonTransactionalService;
|
||||
|
||||
@BeforeEach
|
||||
void configureService(@Autowired SimpleUserRepository repository) {
|
||||
nonTransactionalService.setRepository(repository);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenFindUserReferenceUsingOutsideServiceThenThrowsException() {
|
||||
final User user = nonTransactionalService.findUserReference(EXISTING_ID);
|
||||
assertThatExceptionOfType(LazyInitializationException.class)
|
||||
.isThrownBy(user::getFirstName);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenFindUserReferenceNotUsingOutsideServiceThenDontThrowException() {
|
||||
final User user = nonTransactionalService.findUserReference(EXISTING_ID);
|
||||
assertThat(user).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenFindUserReferenceUsingInsideServiceThenThrowsException() {
|
||||
assertThatExceptionOfType(LazyInitializationException.class)
|
||||
.isThrownBy(() -> nonTransactionalService.findAndUseUserReference(EXISTING_ID));
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("given transactional service with simple repository, even if user exists")
|
||||
class GivenTransactionalService {
|
||||
|
||||
@Autowired
|
||||
private TransactionalUserReferenceService transactionalService;
|
||||
|
||||
@BeforeEach
|
||||
void configureService(@Autowired SimpleUserRepository repository) {
|
||||
transactionalService.setRepository(repository);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenFindUserReferenceUsingOutsideServiceThenThrowsException() {
|
||||
final User user = transactionalService.findUserReference(EXISTING_ID);
|
||||
assertThatExceptionOfType(LazyInitializationException.class)
|
||||
.isThrownBy(user::getFirstName);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenFindUserReferenceNotUsingOutsideServiceThenDontThrowException() {
|
||||
final User user = transactionalService.findUserReference(EXISTING_ID);
|
||||
assertThat(user).isNotNull();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ArgumentsSource(UserProvider.class)
|
||||
void whenFindUserReferenceUsingInsideServiceThenReturnsUser(Long id, String firstName, String lastName) {
|
||||
final User expected = new User(id, firstName, lastName);
|
||||
final User actual = transactionalService.findAndUseUserReference(id);
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("given transactional service with new transaction repository, even if user exists")
|
||||
class GivenTransactionalServiceWithNewTransactionRepository {
|
||||
|
||||
@Autowired
|
||||
private TransactionalUserReferenceService transactionalServiceWithNewTransactionRepository;
|
||||
|
||||
@BeforeEach
|
||||
void configureService(@Autowired NewTransactionUserRepository repository) {
|
||||
transactionalServiceWithNewTransactionRepository.setRepository(repository);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenFindUserReferenceUsingOutsideServiceThenThrowsException() {
|
||||
final User user = transactionalServiceWithNewTransactionRepository
|
||||
.findUserReference(EXISTING_ID);
|
||||
assertThatExceptionOfType(LazyInitializationException.class)
|
||||
.isThrownBy(user::getFirstName);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenFindUserReferenceNotUsingOutsideServiceThenDontThrowException() {
|
||||
final User user = transactionalServiceWithNewTransactionRepository.findUserReference(EXISTING_ID);
|
||||
assertThat(user).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenFindUserReferenceUsingInsideServiceThenThrowsExceptionDueToSeparateTransactions() {
|
||||
assertThatExceptionOfType(LazyInitializationException.class)
|
||||
.isThrownBy(() -> transactionalServiceWithNewTransactionRepository
|
||||
.findAndUseUserReference(EXISTING_ID));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package com.baeldung.spring.data.persistence.findvsget;
|
||||
|
||||
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.ArgumentsProvider;
|
||||
|
||||
public class UserProvider implements ArgumentsProvider {
|
||||
|
||||
@Override
|
||||
public Stream<? extends Arguments> provideArguments(final ExtensionContext context) {
|
||||
return userSource();
|
||||
}
|
||||
|
||||
static Stream<Arguments> userSource() {
|
||||
return Stream.of(
|
||||
Arguments.of(1L, "Saundra", "Krystek"),
|
||||
Arguments.of(2L, "Korey", "Venners"),
|
||||
Arguments.of(3L, "Lory", "Daffey"),
|
||||
Arguments.of(4L, "Michail", "Spinella"),
|
||||
Arguments.of(5L, "Emanuel", "Geertje"),
|
||||
Arguments.of(6L, "Jervis", "Waugh"),
|
||||
Arguments.of(7L, "Chantal", "Soldan"),
|
||||
Arguments.of(8L, "Darnall", "Fanner"),
|
||||
Arguments.of(9L, "Cordelia", "Hindge"),
|
||||
Arguments.of(10L, "Lem", "Pitcock")
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue