mirror of
https://github.com/OtusTeam/Spring.git
synced 2026-05-30 10:50:42 +00:00
2019-08 spring-07 examples finished
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
target/
|
||||
+33
-17
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
-3
@@ -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) {
|
||||
|
||||
+1
-1
@@ -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"))
|
||||
|
||||
-1
@@ -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);
|
||||
|
||||
+20
-11
@@ -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);
|
||||
|
||||
|
||||
+15
-8
@@ -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:
|
||||
|
||||
@@ -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>
|
||||
+16
@@ -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
-1
@@ -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;
|
||||
+21
@@ -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;
|
||||
}
|
||||
+21
@@ -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;
|
||||
}
|
||||
+22
@@ -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;
|
||||
}
|
||||
+42
@@ -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;
|
||||
}
|
||||
+17
@@ -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);
|
||||
|
||||
}
|
||||
+49
@@ -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)
|
||||
);
|
||||
+94
@@ -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);
|
||||
+4
-1
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user