BAEL-7509: An example with optimized referenceBy (#15988)
* BAEL-7509: An example with optimized referenceBy * BAEL-7509: Added query counting tests * BAEL-7509: Formatting fix
This commit is contained in:
parent
c1fe1fd285
commit
f7bd3d50f5
@ -76,6 +76,16 @@
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>${logback.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.hypersistence</groupId>
|
||||
<artifactId>hypersistence-utils-hibernate-62</artifactId>
|
||||
<version>${hypersistence-utils.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.vladmihalcea</groupId>
|
||||
<artifactId>db-util</artifactId>
|
||||
<version>${db.util.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@ -130,6 +140,8 @@
|
||||
<properties>
|
||||
<hypersistance-utils-hibernate-55.version>3.7.0</hypersistance-utils-hibernate-55.version>
|
||||
<postgresql.version>42.7.1</postgresql.version>
|
||||
<db.util.version>1.0.7</db.util.version>
|
||||
<hypersistence-utils.version>3.7.0</hypersistence-utils.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -0,0 +1,51 @@
|
||||
package com.baeldung.spring.data.persistence.findvsget.entity;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "group")
|
||||
public class Group {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
private String name;
|
||||
@OneToOne
|
||||
private User administrator;
|
||||
@OneToMany(mappedBy = "id")
|
||||
private Set<User> users = new HashSet<>();
|
||||
public void addUser(User user) {
|
||||
users.add(user);
|
||||
}
|
||||
public Set<User> getUsers() {
|
||||
return users;
|
||||
}
|
||||
public void setUsers(Set<User> users) {
|
||||
this.users = users;
|
||||
}
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public User getAdministrator() {
|
||||
return administrator;
|
||||
}
|
||||
public void setAdministrator(User administrator) {
|
||||
this.administrator = administrator;
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package com.baeldung.spring.data.persistence.findvsget.repository;
|
||||
|
||||
import com.baeldung.spring.data.persistence.findvsget.entity.Group;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface GroupRepository extends JpaRepository<Group, Long> {
|
||||
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
package com.baeldung.spring.data.persistence.findvsget;
|
||||
|
||||
import static com.vladmihalcea.sql.SQLStatementCountValidator.assertInsertCount;
|
||||
import static com.vladmihalcea.sql.SQLStatementCountValidator.assertSelectCount;
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
|
||||
|
||||
import com.baeldung.spring.data.persistence.findvsget.entity.Group;
|
||||
import com.baeldung.spring.data.persistence.findvsget.entity.User;
|
||||
import com.baeldung.spring.data.persistence.findvsget.repository.GroupRepository;
|
||||
import com.baeldung.spring.data.persistence.findvsget.repository.SimpleUserRepository;
|
||||
import io.hypersistence.utils.jdbc.validator.SQLStatementCountValidator;
|
||||
import java.util.Optional;
|
||||
import org.hibernate.LazyInitializationException;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
|
||||
class AdditionalLookupIntegrationTest extends DatabaseConfigurationBaseIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private SimpleUserRepository userRepository;
|
||||
@Autowired
|
||||
private GroupRepository groupRepository;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
SQLStatementCountValidator.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenEmptyGroup_whenAssigningAdministratorWithGetByReference_thenNoAdditionalLookupHappens() {
|
||||
User user = userRepository.getReferenceById(1L);
|
||||
Group group = new Group();
|
||||
group.setAdministrator(user);
|
||||
groupRepository.save(group);
|
||||
assertSelectCount(0);
|
||||
assertInsertCount(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenEmptyGroup_whenAssigningIncorrectAdministratorWithGetByReference_thenErrorIsThrown() {
|
||||
User user = userRepository.getReferenceById(-1L);
|
||||
Group group = new Group();
|
||||
group.setAdministrator(user);
|
||||
assertThatExceptionOfType(DataIntegrityViolationException.class)
|
||||
.isThrownBy(() -> {
|
||||
groupRepository.save(group);
|
||||
});
|
||||
assertSelectCount(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenEmptyGroup_whenAssigningAdministratorWithFindBy_thenAdditionalLookupHappens() {
|
||||
Optional<User> optionalUser = userRepository.findById(1L);
|
||||
assertThat(optionalUser).isPresent();
|
||||
User user = optionalUser.get();
|
||||
Group group = new Group();
|
||||
group.setAdministrator(user);
|
||||
groupRepository.save(group);
|
||||
assertSelectCount(2);
|
||||
assertInsertCount(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenEmptyGroup_whenAddingUserWithGetByReference_thenTryToAccessInternalsAndThrowError() {
|
||||
User user = userRepository.getReferenceById(1L);
|
||||
Group group = new Group();
|
||||
assertThatExceptionOfType(LazyInitializationException.class)
|
||||
.isThrownBy(() -> {
|
||||
group.addUser(user);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenEmptyGroup_whenAddingUserWithFindBy_thenAdditionalLookupHappens() {
|
||||
Optional<User> optionalUser = userRepository.findById(1L);
|
||||
assertThat(optionalUser).isPresent();
|
||||
User user = optionalUser.get();
|
||||
Group group = new Group();
|
||||
group.addUser(user);
|
||||
groupRepository.save(group);
|
||||
assertSelectCount(1);
|
||||
assertInsertCount(1);
|
||||
}
|
||||
}
|
@ -4,7 +4,9 @@ import static com.baeldung.spring.data.persistence.findvsget.UserProvider.userSo
|
||||
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.GroupRepository;
|
||||
import com.baeldung.spring.data.persistence.findvsget.repository.SimpleUserRepository;
|
||||
import com.baeldung.spring.data.persistence.util.TestConfig;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@ -13,7 +15,7 @@ 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 = {
|
||||
@SpringBootTest(classes = {ApplicationConfig.class, TestConfig.class}, properties = {
|
||||
"spring.jpa.generate-ddl=true",
|
||||
"spring.jpa.show-sql=false"
|
||||
})
|
||||
@ -22,7 +24,10 @@ abstract class DatabaseConfigurationBaseIntegrationTest {
|
||||
private static final int NUMBER_OF_USERS = 10;
|
||||
|
||||
@Autowired
|
||||
private SimpleUserRepository repository;
|
||||
private SimpleUserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private GroupRepository groupRepository;
|
||||
|
||||
@BeforeEach
|
||||
void populateDatabase() {
|
||||
@ -30,13 +35,14 @@ abstract class DatabaseConfigurationBaseIntegrationTest {
|
||||
.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);
|
||||
userRepository.saveAll(users);
|
||||
assumeThat(userRepository.findAll()).hasSize(NUMBER_OF_USERS);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void clearDatabase() {
|
||||
repository.deleteAll();
|
||||
groupRepository.deleteAll();
|
||||
userRepository.deleteAll();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,36 @@
|
||||
package com.baeldung.spring.data.persistence.util;
|
||||
|
||||
import io.hypersistence.utils.logging.InlineQueryLogEntryCreator;
|
||||
import javax.sql.DataSource;
|
||||
import net.ttddyy.dsproxy.listener.ChainListener;
|
||||
import net.ttddyy.dsproxy.listener.DataSourceQueryCountListener;
|
||||
import net.ttddyy.dsproxy.listener.logging.SLF4JQueryLoggingListener;
|
||||
import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class DataSourceWrapper implements BeanPostProcessor {
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (bean instanceof DataSource) {
|
||||
DataSource originalDataSource = ((DataSource) bean);
|
||||
ChainListener listener = new ChainListener();
|
||||
SLF4JQueryLoggingListener loggingListener = new SLF4JQueryLoggingListener();
|
||||
loggingListener.setQueryLogEntryCreator(new InlineQueryLogEntryCreator());
|
||||
listener.addListener(loggingListener);
|
||||
listener.addListener(new DataSourceQueryCountListener());
|
||||
return ProxyDataSourceBuilder
|
||||
.create(originalDataSource)
|
||||
.name("DS-Proxy")
|
||||
.listener(listener)
|
||||
.build();
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.baeldung.spring.data.persistence.util;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class TestConfig {
|
||||
|
||||
@Bean
|
||||
public DataSourceWrapper dataSourceWrapper() {
|
||||
return new DataSourceWrapper();
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user