2019-08 spring-07 examples finished

This commit is contained in:
stvort
2019-09-20 18:30:40 +04:00
parent 1f2a956f5c
commit 76c0896f06
26 changed files with 574 additions and 62 deletions
+4
View File
@@ -0,0 +1,4 @@
.idea/
*.iml
target/
@@ -16,6 +16,21 @@ import static org.assertj.core.api.Assertions.assertThat;
@Transactional
public class OtusStudentRepositoryTest {
private static final String FIELD_ID = "id";
private static final String FIELD_PHOTO_URL = "photoUrl";
private static final String FIELD_NAME = "name";
private static final long FIRST_STUDENT_ID = 1L;
private static final long FIRST_AVATAR_ID = 1L;
private static final String FIRST_STUDENT_NAME = "student_01";
private static final String FIRST_AVATAR_URL = "photoUrl_01";
private static final String STUDENT_NEW_NAME = "Висусуалий";
private static final int EXPECTED_NUMBER_OF_STUDENTS = 10;
private static final long INSERTED_STUDENT_ID = 11L;
private static final int EXPECTED_EMAILS_COUNT = 2;
private static final int EXPECTED_COURSES_COUNT = 3;
@Autowired
private OtusStudentRepository studentRepositoryMyBatis;
@@ -23,7 +38,8 @@ public class OtusStudentRepositoryTest {
@Test
void shouldReturnCorrectStudentsListWithAllInfo() {
val students = studentRepositoryMyBatis.findAllWithAllInfo();
assertThat(students).isNotNull().hasSize(10).allMatch(s -> !s.getName().equals(""))
assertThat(students).isNotNull().hasSize(EXPECTED_NUMBER_OF_STUDENTS)
.allMatch(s -> !s.getName().equals(""))
.allMatch(s -> s.getCourses() != null && s.getCourses().size() > 0)
.allMatch(s -> s.getAvatar() != null)
.allMatch(s -> s.getEmails() != null && s.getEmails().size() > 0);
@@ -33,52 +49,52 @@ public class OtusStudentRepositoryTest {
@Test
void shouldReturnCorrectStudentsCount() {
long studentsCount = studentRepositoryMyBatis.getStudentsCount();
assertThat(studentsCount).isEqualTo(10);
assertThat(studentsCount).isEqualTo(EXPECTED_NUMBER_OF_STUDENTS);
}
@DisplayName(" должен загружать информацию о нужном студенте")
@Test
void shouldFindExpectedStudentById(){
val actualStudent = studentRepositoryMyBatis.findById(1L);
val actualStudent = studentRepositoryMyBatis.findById(FIRST_STUDENT_ID);
assertThat(actualStudent).isNotNull();
assertThat(actualStudent.getName()).isEqualTo("student_01");
assertThat(actualStudent.getName()).isEqualTo(FIRST_STUDENT_NAME);
assertThat(actualStudent.getAvatar()).isNotNull()
.hasFieldOrPropertyWithValue("id", 1L)
.hasFieldOrPropertyWithValue("photoUrl", "photoUrl_01");
assertThat(actualStudent.getEmails()).isNotNull().hasSize(2);
assertThat(actualStudent.getCourses()).isNotNull().hasSize(3);
.hasFieldOrPropertyWithValue(FIELD_ID, FIRST_STUDENT_ID)
.hasFieldOrPropertyWithValue(FIELD_PHOTO_URL, FIRST_AVATAR_URL);
assertThat(actualStudent.getEmails()).isNotNull().hasSize(EXPECTED_EMAILS_COUNT);
assertThat(actualStudent.getCourses()).isNotNull().hasSize(EXPECTED_COURSES_COUNT);
}
@DisplayName(" должен сохранить, а потом загрузить информацию о нужном студенте")
@Test
void shouldSaveAndLoadCorrectStudent() {
val expectedStudent = new OtusStudent();
expectedStudent.setName("Vasya");
expectedStudent.setAvatar(new Avatar(1L, "photoUrl_01"));
expectedStudent.setName(STUDENT_NEW_NAME);
expectedStudent.setAvatar(new Avatar(FIRST_AVATAR_ID, FIRST_AVATAR_URL));
studentRepositoryMyBatis.insert(expectedStudent);
val actualStudent = studentRepositoryMyBatis.findById(11L);
val actualStudent = studentRepositoryMyBatis.findById(INSERTED_STUDENT_ID);
assertThat(actualStudent).isNotNull().isEqualToComparingOnlyGivenFields(expectedStudent, "name");
assertThat(actualStudent).isNotNull().isEqualToComparingOnlyGivenFields(expectedStudent, FIELD_NAME);
}
@DisplayName(" должен обновлять имя студента в БД")
@Test
void shouldUpdateStudentName() {
val student = studentRepositoryMyBatis.findById(1L);
student.setName("Висусуалий");
val student = studentRepositoryMyBatis.findById(FIRST_STUDENT_ID);
student.setName(STUDENT_NEW_NAME);
studentRepositoryMyBatis.updateName(student);
val actualStudent = studentRepositoryMyBatis.findById(1L);
val actualStudent = studentRepositoryMyBatis.findById(FIRST_STUDENT_ID);
assertThat(actualStudent).isNotNull().hasFieldOrPropertyWithValue("name", student.getName());
assertThat(actualStudent).isNotNull().hasFieldOrPropertyWithValue(FIELD_NAME, student.getName());
}
@DisplayName("должен удалять студента из БД по id")
@Test
void shouldDeleteStudentFromDbById() {
val studentsCountBefore = studentRepositoryMyBatis.getStudentsCount();
studentRepositoryMyBatis.deleteById(1L);
studentRepositoryMyBatis.deleteById(FIRST_STUDENT_ID);
val studentsCountAfter = studentRepositoryMyBatis.getStudentsCount();
assertThat(studentsCountBefore - studentsCountAfter).isEqualTo(1);
-18
View File
@@ -22,24 +22,6 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<!--
<exclusions>
<exclusion>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</exclusion>
<exclusion>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</exclusion>
</exclusions>
-->
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>2.7.4</version>
</dependency>
<dependency>
@@ -2,11 +2,8 @@ package ru.otus.example.ormdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;
import ru.otus.example.ormdemo.config.EclipseLinkJpaConfiguration;
@SpringBootApplication
//@Import(EclipseLinkJpaConfiguration.class)
public class OrmDemoApplication {
public static void main(String[] args) {
@@ -35,8 +35,8 @@ public class OtusStudentV2 {
@JoinColumn(name = "student_id")
private List<EMail> emails;
//@BatchSize(size = 5)
//@Fetch(FetchMode.SUBSELECT)
//@BatchSize(size = 5)
@ManyToMany(targetEntity = Course.class, fetch = FetchType.LAZY)
@JoinTable(name = "student_courses", joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id"))
@@ -28,7 +28,6 @@ public class OtusStudentRepositoryJpaImpl implements OtusStudentRepositoryJpa {
public OtusStudent save(OtusStudent student) {
if (student.getId() <= 0) {
em.persist(student);
//em.flush();
return student;
} else {
return em.merge(student);
@@ -1,8 +1,6 @@
package ru.otus.example.ormdemo.repositories;
import lombok.val;
import org.assertj.core.api.Assertions;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@@ -24,8 +22,16 @@ import static org.assertj.core.api.Assertions.assertThat;
@Import({OtusStudentRepositoryJpaImpl.class, CourseRepositoryJpaImpl.class})
class OtusStudentRepositoryJpaImplTest {
private static final int EXPECTED_NUMBER_OF_STUDENTS = 10;
private static final long FIRST_STUDENT_ID = 1L;
private static final int EXPECTED_QUERIES_COUNT = 31;
private static final String STUDENT_AVATAR_URL = "где-то там";
private static final String STUDENT_EMAIL = "any@mail.com";
private static final String COURSE_NAME = "Spring";
private static final String STUDENT_NAME = "Вася";
@Autowired
private OtusStudentRepositoryJpaImpl repositoryJpa;
@@ -38,21 +44,24 @@ class OtusStudentRepositoryJpaImplTest {
@DisplayName(" должен загружать информацию о нужном студенте")
@Test
void shouldFindExpectedStudentById() {
val optionalActualStudent = repositoryJpa.findById(1L);
val expectedStudent = em.find(OtusStudent.class, 1L);
assertThat(optionalActualStudent).isPresent().get().isEqualToComparingFieldByFieldRecursively(expectedStudent);
val optionalActualStudent = repositoryJpa.findById(FIRST_STUDENT_ID);
val expectedStudent = em.find(OtusStudent.class, FIRST_STUDENT_ID);
assertThat(optionalActualStudent).isPresent().get()
.isEqualToComparingFieldByFieldRecursively(expectedStudent);
}
@DisplayName("должен загружать список всех студентов с полной информацией о них")
@Test
void shouldReturnCorrectStudentsListWithAllInfo() {
SessionFactory sessionFactory = em.getEntityManager().getEntityManagerFactory().unwrap(SessionFactory.class);
SessionFactory sessionFactory = em.getEntityManager().getEntityManagerFactory()
.unwrap(SessionFactory.class);
sessionFactory.getStatistics().setStatisticsEnabled(true);
System.out.println("\n\n\n\n----------------------------------------------------------------------------------------------------------");
val students = repositoryJpa.findAll();
assertThat(students).isNotNull().hasSize(10).allMatch(s -> !s.getName().equals(""))
assertThat(students).isNotNull().hasSize(EXPECTED_NUMBER_OF_STUDENTS)
.allMatch(s -> !s.getName().equals(""))
.allMatch(s -> s.getCourses() != null && s.getCourses().size() > 0)
.allMatch(s -> s.getAvatar() != null)
.allMatch(s -> s.getEmails() != null && s.getEmails().size() > 0);
@@ -63,16 +72,16 @@ class OtusStudentRepositoryJpaImplTest {
@DisplayName(" должен корректно сохранять всю информацию о студенте")
@Test
void shouldSaveAllStudentInfo() {
val avatar = new Avatar(0, "где-то там");
val email = new EMail(0, "any@mail.com");
val avatar = new Avatar(0, STUDENT_AVATAR_URL);
val email = new EMail(0, STUDENT_EMAIL);
val emails = Collections.singletonList(email);
val course = new Course(0, "Spring");
val course = new Course(0, COURSE_NAME);
val courses = Collections.singletonList(course);
//courseRepositoryJpa.save(course);
val vasya = new OtusStudent(- 1, "Vasya", avatar, emails, courses);
val vasya = new OtusStudent(0, STUDENT_NAME, avatar, emails, courses);
repositoryJpa.save(vasya);
assertThat(vasya.getId()).isGreaterThan(0);
@@ -19,9 +19,11 @@ import static org.assertj.core.api.Assertions.assertThat;
@Import({OtusStudentV2RepositoryJpaImpl.class})
class OtusStudentV2RepositoryJpaImplTest {
private static final int EXPECTED_QUERIES_COUNT = 11;
//private static final int EXPECTED_QUERIES_COUNT = 2;
//private static final int EXPECTED_QUERIES_COUNT = 3;
private static final int EXPECTED_NUMBER_OF_STUDENTS = 10;
private static final int EXPECTED_QUERIES_COUNT = 11; // EntityGraph/join fetch
//private static final int EXPECTED_QUERIES_COUNT = 2; // EntityGraph/join fetch + @Fetch(FetchMode.SUBSELECT)
//private static final int EXPECTED_QUERIES_COUNT = 3; // EntityGraph/join fetch + @BatchSize(size = 5)
@Autowired
private OtusStudentV2RepositoryJpaImpl repositoryJpa;
@@ -33,7 +35,8 @@ class OtusStudentV2RepositoryJpaImplTest {
@BeforeEach
void setUp() {
sessionFactory = em.getEntityManager().getEntityManagerFactory().unwrap(SessionFactory.class);
sessionFactory = em.getEntityManager().getEntityManagerFactory()
.unwrap(SessionFactory.class);
sessionFactory.getStatistics().setStatisticsEnabled(true);
sessionFactory.getStatistics().clear();
}
@@ -43,12 +46,14 @@ class OtusStudentV2RepositoryJpaImplTest {
void usingEntityGraphShouldReturnCorrectStudentsListWithWithAllInfo() {
System.out.println("\n\n\n\n----------------------------------------------------------------------------------------------------------");
List<OtusStudentV2> students = repositoryJpa.findAllWithEntityGraph();
assertThat(students).isNotNull().hasSize(10).allMatch(s -> !s.getName().equals(""))
assertThat(students).isNotNull().hasSize(EXPECTED_NUMBER_OF_STUDENTS)
.allMatch(s -> !s.getName().equals(""))
.allMatch(s -> s.getCourses() != null && s.getCourses().size() > 0)
.allMatch(s -> s.getAvatar() != null)
.allMatch(s -> s.getEmails() != null && s.getEmails().size() > 0);
System.out.println("----------------------------------------------------------------------------------------------------------\n\n\n\n");
assertThat(sessionFactory.getStatistics().getPrepareStatementCount()).isEqualTo(EXPECTED_QUERIES_COUNT);
assertThat(sessionFactory.getStatistics().getPrepareStatementCount())
.isEqualTo(EXPECTED_QUERIES_COUNT);
}
@@ -57,11 +62,13 @@ class OtusStudentV2RepositoryJpaImplTest {
void usingJoinFetchShouldReturnCorrectStudentsListWithWithAllInfo() {
System.out.println("\n\n\n\n----------------------------------------------------------------------------------------------------------");
List<OtusStudentV2> students = repositoryJpa.findAllWithJoinFetch();
assertThat(students).isNotNull().hasSize(10).allMatch(s -> !s.getName().equals(""))
assertThat(students).isNotNull().hasSize(EXPECTED_NUMBER_OF_STUDENTS)
.allMatch(s -> !s.getName().equals(""))
.allMatch(s -> s.getCourses() != null && s.getCourses().size() > 0)
.allMatch(s -> s.getAvatar() != null)
.allMatch(s -> s.getEmails() != null && s.getEmails().size() > 0);
System.out.println("----------------------------------------------------------------------------------------------------------\n\n\n\n");
assertThat(sessionFactory.getStatistics().getPrepareStatementCount()).isEqualTo(EXPECTED_QUERIES_COUNT);
assertThat(sessionFactory.getStatistics().getPrepareStatementCount())
.isEqualTo(EXPECTED_QUERIES_COUNT);
}
}
@@ -4,7 +4,6 @@ spring:
initialization-mode: always
jpa:
show-sql: false
generate-ddl: false
#generate-ddl: true
hibernate:
+19
View File
@@ -0,0 +1,19 @@
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>ru.otus</groupId>
<artifactId>spring-07</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<modules>
<module>spring-jdbc-demo</module>
<module>orm-demo</module>
<module>replace-orm-provider-demo</module>
<module>mybatis-demo</module>
</modules>
</project>
@@ -0,0 +1,29 @@
HELP.md
/target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
/build/
### VS Code ###
.vscode/
@@ -0,0 +1,2 @@
# replace-orm-provider-demo
Пример замены ORM провайдера
@@ -0,0 +1,86 @@
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/>
</parent>
<groupId>ru.otus.example</groupId>
<artifactId>replace-orm-provider-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>replace-orm-provider-demo</name>
<description>Replace ORM provider demo</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</exclusion>
<exclusion>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>2.7.4</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--Тестирование-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,16 @@
package ru.otus.example.replaceormproviderdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;
import ru.otus.example.replaceormproviderdemo.config.EclipseLinkJpaConfiguration;
@SpringBootApplication
@Import(EclipseLinkJpaConfiguration.class)
public class ReplaceOrmProviderDemoApplication {
public static void main(String[] args) {
SpringApplication.run(ReplaceOrmProviderDemoApplication.class, args);
}
}
@@ -1,4 +1,4 @@
package ru.otus.example.ormdemo.config;
package ru.otus.example.replaceormproviderdemo.config;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.springframework.beans.factory.ObjectProvider;
@@ -0,0 +1,21 @@
package ru.otus.example.replaceormproviderdemo.models;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "avatars")
public class Avatar {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "photo_url", nullable = false, unique = true)
private String photoUrl;
}
@@ -0,0 +1,21 @@
package ru.otus.example.replaceormproviderdemo.models;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "courses")
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "name", nullable = false, unique = true)
private String name;
}
@@ -0,0 +1,22 @@
package ru.otus.example.replaceormproviderdemo.models;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "emails")
public class EMail {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "email", nullable = false, unique = true)
private String email;
}
@@ -0,0 +1,42 @@
package ru.otus.example.replaceormproviderdemo.models;
import lombok.*;
import org.eclipse.persistence.annotations.BatchFetch;
import org.eclipse.persistence.annotations.BatchFetchType;
import javax.persistence.*;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity // Указывает, что данный класс является сущностью
@Table(name = "otus_students") // Задает имя таблицы, на которую будет отображаться сущность
public class OtusStudent {
@Id // Позволяет указать какое поле является идентификатором
@GeneratedValue(strategy = GenerationType.IDENTITY) // Стратегия генерации идентификаторов
private long id;
// Задает имя и некоторые свойства поля таблицы, на которое будет отображаться поле сущности
@Column(name = "name", nullable = false, unique = true)
private String name;
// Указывает на связь между таблицами "один к одному"
@OneToOne(targetEntity = Avatar.class, cascade = CascadeType.ALL)
// Задает поле, по которому происходит объединение с таблицей для хранения связанной сущности
@JoinColumn(name = "avatar_id")
private Avatar avatar;
// Указывает на связь между таблицами "один ко многим"
@OneToMany(targetEntity = EMail.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "student_id")
private List<EMail> emails;
// Указывает на связь между таблицами "многие ко многим"
@BatchFetch(value = BatchFetchType.IN)
@ManyToMany(targetEntity = Course.class, cascade = CascadeType.ALL, fetch = FetchType.LAZY)
// Задает таблицу связей между таблицами для хранения родительской и связанной сущностью
@JoinTable(name = "student_courses", joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id"))
private List<Course> courses;
}
@@ -0,0 +1,17 @@
package ru.otus.example.replaceormproviderdemo.repositories;
import ru.otus.example.replaceormproviderdemo.models.OtusStudent;
import java.util.List;
import java.util.Optional;
public interface OtusStudentRepositoryJpa {
Optional<OtusStudent> findById(long id);
List<OtusStudent> findAll();
List<OtusStudent> findAllWithJoinFetch();
OtusStudent save(OtusStudent student);
}
@@ -0,0 +1,49 @@
package ru.otus.example.replaceormproviderdemo.repositories;
import org.eclipse.persistence.config.QueryHints;
import org.springframework.stereotype.Repository;
import ru.otus.example.replaceormproviderdemo.models.OtusStudent;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import java.util.List;
import java.util.Optional;
@Repository
public class OtusStudentRepositoryJpaImpl implements OtusStudentRepositoryJpa {
private static final int DEFAULT_BATCH_SIZE = 5;
@PersistenceContext
private EntityManager em;
@Override
public Optional<OtusStudent> findById(long id) {
return Optional.ofNullable(em.find(OtusStudent.class, id));
}
@Override
public List<OtusStudent> findAll() {
return em.createQuery("select s from OtusStudent s", OtusStudent.class).getResultList();
}
@Override
public List<OtusStudent> findAllWithJoinFetch() {
TypedQuery<OtusStudent> query = em.createQuery("select distinct s from OtusStudent s join fetch s.avatar join fetch s.emails", OtusStudent.class);
query.setHint(QueryHints.BATCH_SIZE, DEFAULT_BATCH_SIZE);
return query.getResultList();
}
@Override
public OtusStudent save(OtusStudent student) {
if (student.getId() <= 0) {
em.persist(student);
//em.flush();
return student;
} else {
return em.merge(student);
}
}
}
@@ -0,0 +1,31 @@
create table avatars(
id bigserial,
photo_url varchar(8000),
primary key (id)
);
create table courses(
id bigserial,
name varchar(255),
primary key (id)
);
create table otus_students(
id bigserial,
name varchar(255),
avatar_id bigint references avatars (id),
primary key (id)
);
create table emails(
id bigserial,
student_id bigint references otus_students(id) on delete cascade,
email varchar(255),
primary key (id)
);
create table student_courses(
student_id bigint references otus_students(id) on delete cascade,
course_id bigint references courses(id),
primary key (student_id, course_id)
);
@@ -0,0 +1,94 @@
package ru.otus.example.replaceormproviderdemo.repositories;
import lombok.val;
import org.junit.jupiter.api.DisplayName;
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.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import org.springframework.context.annotation.Import;
import ru.otus.example.replaceormproviderdemo.models.OtusStudent;
import ru.otus.example.replaceormproviderdemo.models.Avatar;
import ru.otus.example.replaceormproviderdemo.models.Course;
import ru.otus.example.replaceormproviderdemo.models.EMail;
import java.util.Collections;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@DisplayName("Репозиторий на основе Jpa для работы со студентами ")
@DataJpaTest
@Import({OtusStudentRepositoryJpaImpl.class})
class OtusStudentRepositoryJpaImplTest {
private static final int EXPECTED_NUMBER_OF_STUDENTS = 10;
private static final long FIRST_STUDENT_ID = 1L;
private static final String STUDENT_AVATAR_URL = "где-то там";
private static final String STUDENT_EMAIL = "any@mail.com";
private static final String COURSE_NAME = "Spring";
private static final String STUDENT_NAME = "Вася";
@Autowired
private OtusStudentRepositoryJpaImpl repositoryJpa;
@Autowired
private TestEntityManager em;
@DisplayName(" должен загружать информацию о нужном студенте")
@Test
void shouldFindExpectedStudentById() {
val optionalActualStudent = repositoryJpa.findById(FIRST_STUDENT_ID);
val expectedStudent = em.find(OtusStudent.class, FIRST_STUDENT_ID);
assertThat(optionalActualStudent).isPresent().get()
.isEqualToComparingFieldByFieldRecursively(expectedStudent);
}
@DisplayName("должен загружать список всех студентов с полной информацией о них")
@Test
void shouldReturnCorrectStudentsListWithAllInfo() {
System.out.println("\n\n\n\n----------------------------------------------------------------------------------------------------------");
val students = repositoryJpa.findAll();
assertThat(students).isNotNull().hasSize(EXPECTED_NUMBER_OF_STUDENTS)
.allMatch(s -> !s.getName().equals(""))
.allMatch(s -> s.getCourses() != null && s.getCourses().size() > 0)
.allMatch(s -> s.getAvatar() != null)
.allMatch(s -> s.getEmails() != null && s.getEmails().size() > 0);
System.out.println("----------------------------------------------------------------------------------------------------------\n\n\n\n");
}
@DisplayName(" с помощью 'join fetch' должен загружать список всех студентов с полной информацией о них")
@Test
void usingJoinFetchShouldReturnCorrectStudentsListWithWithAllInfo() {
System.out.println("\n\n\n\n----------------------------------------------------------------------------------------------------------");
List<OtusStudent> students = repositoryJpa.findAllWithJoinFetch();
assertThat(students).isNotNull().hasSize(EXPECTED_NUMBER_OF_STUDENTS)
.allMatch(s -> !s.getName().equals(""))
.allMatch(s -> s.getCourses() != null && s.getCourses().size() > 0)
.allMatch(s -> s.getAvatar() != null)
.allMatch(s -> s.getEmails() != null && s.getEmails().size() > 0);
System.out.println("----------------------------------------------------------------------------------------------------------\n\n\n\n");
}
@DisplayName(" должен корректно сохранять всю информацию о студенте")
@Test
void shouldSaveAllStudentInfo() {
val avatar = new Avatar(0, STUDENT_AVATAR_URL);
val email = new EMail(0, STUDENT_EMAIL);
val emails = Collections.singletonList(email);
val course = new Course(0, COURSE_NAME);
val courses = Collections.singletonList(course);
val vasya = new OtusStudent(0, STUDENT_NAME, avatar, emails, courses);
repositoryJpa.save(vasya);
assertThat(vasya.getId()).isGreaterThan(0);
val actualStudent = em.find(OtusStudent.class, vasya.getId());
assertThat(actualStudent).isNotNull().matches(s -> !s.getName().equals(""))
.matches(s -> s.getCourses() != null && s.getCourses().size() > 0 && s.getCourses().get(0).getId() > 0)
.matches(s -> s.getAvatar() != null)
.matches(s -> s.getEmails() != null && s.getEmails().size() > 0);
}
}
@@ -0,0 +1,18 @@
spring:
datasource:
url: jdbc:h2:mem:testdb
initialization-mode: always
jpa:
show-sql: false
generate-ddl: false
#generate-ddl: true
hibernate:
ddl-auto: none
#ddl-auto: create-drop
#show-sql: true
logging:
level:
ROOT: ERROR
@@ -0,0 +1,29 @@
insert into avatars(photo_url)
values ('photoUrl_01'), ('photoUrl_02'), ('photoUrl_03'), ('photoUrl_04'), ('photoUrl_05'),
('photoUrl_06'), ('photoUrl_07'), ('photoUrl_08'), ('photoUrl_09'), ('photoUrl_10');
insert into courses(name)
values ('course_name_01'), ('course_name_02'), ('course_name_03'), ('course_name_04'), ('course_name_05'),
('course_name_06'), ('course_name_07'), ('course_name_08'), ('course_name_09'), ('course_name_10'), ('not_used_11');
insert into otus_students(name, avatar_id)
values ('student_01', 1), ('student_02', 2), ('student_03', 3), ('student_04', 4), ('student_05', 5),
('student_06', 6), ('student_07', 7), ('student_08', 8), ('student_09', 9), ('student_10', 10);
insert into emails(email, student_id)
values ('email_01', 1), ('email_02', 1), ('email_03', 2), ('email_04', 2), ('email_05', 3), ('email_06', 4),
('email_07', 5), ('email_08', 6), ('email_09', 7), ('email_10', 8), ('email_11', 9), ('email_12', 10);
insert into student_courses(student_id, course_id)
values (1, 1), (1, 2), (1, 3),
(2, 2), (2, 4), (2, 5),
(3, 3), (3, 6), (3, 7),
(4, 4), (4, 8), (4, 9),
(5, 5), (5, 10), (5, 1),
(6, 6), (6, 2), (6, 3),
(7, 7), (7, 4), (7, 5),
(8, 8), (8, 6), (8, 7),
(9, 9), (9, 8), (9, 10),
(10, 10), (10, 1), (10, 2);
@@ -15,6 +15,8 @@ import static org.assertj.core.api.Assertions.assertThat;
@Import({OtusStudentRepositoryJdbcImpl.class, CourseRepositoryJdbcImpl.class})
class OtusStudentRepositoryJdbcImplTest {
private static final int EXPECTED_NUMBER_OF_STUDENTS = 10;
@Autowired
private OtusStudentRepositoryJdbcImpl repositoryJdbc;
@@ -22,7 +24,8 @@ class OtusStudentRepositoryJdbcImplTest {
@Test
void shouldReturnCorrectStudentsListWithAllInfo() {
val students = repositoryJdbc.findAllWithAllInfo();
assertThat(students).isNotNull().hasSize(10).allMatch(s -> !s.getName().equals(""))
assertThat(students).isNotNull().hasSize(EXPECTED_NUMBER_OF_STUDENTS)
.allMatch(s -> !s.getName().equals(""))
.allMatch(s -> s.getCourses() != null && s.getCourses().size() > 0)
.allMatch(s -> s.getAvatar() != null)
.allMatch(s -> s.getEmails() != null && s.getEmails().size() > 0);