2020-11 spring-08-orm added

This commit is contained in:
Александр Оруджев
2020-12-21 23:45:04 +04:00
parent 664801a950
commit e5c553a5e9
93 changed files with 2465 additions and 0 deletions
@@ -0,0 +1,4 @@
.idea/
*.iml
target/
@@ -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 @@
# mybatis-demo
Пример работы с БД через MyBatis
@@ -0,0 +1,73 @@
<?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.4.1</version>
<relativePath/>
</parent>
<groupId>ru.otus.example</groupId>
<artifactId>mybatis-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mybatis-demo</name>
<description>MyBatis demo</description>
<properties>
<java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.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,14 @@
package ru.otus.example.mybatisdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class MyBatisDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MyBatisDemoApplication.class, args);
}
}
@@ -0,0 +1,13 @@
package ru.otus.example.mybatisdemo.models;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Avatar {
private long id;
private String photoUrl;
}
@@ -0,0 +1,13 @@
package ru.otus.example.mybatisdemo.models;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Course {
private long id;
private String name;
}
@@ -0,0 +1,13 @@
package ru.otus.example.mybatisdemo.models;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class EMail {
private long id;
private String email;
}
@@ -0,0 +1,18 @@
package ru.otus.example.mybatisdemo.models;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class OtusStudent {
private long id;
private String name;
private Avatar avatar;
private List<EMail> emails;
private List<Course> courses;
}
@@ -0,0 +1,18 @@
package ru.otus.example.mybatisdemo.repositories;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import ru.otus.example.mybatisdemo.models.Avatar;
@Mapper
public interface AvatarRepository {
@Select("select * from avatars where id = #{id}")
@Results(value = {
@Result(property = "id", column = "id"),
@Result(property = "photoUrl", column = "photo_url")
})
Avatar getAvatarById(long id);
}
@@ -0,0 +1,17 @@
package ru.otus.example.mybatisdemo.repositories;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import ru.otus.example.mybatisdemo.models.Course;
import java.util.List;
@Mapper
public interface CourseRepository {
@Select("select * " +
"from student_courses sc left join courses c on sc.course_id = c.id " +
"where sc.student_id = #{studentId}")
List<Course> getCoursesByStudentId(long studentId);
}
@@ -0,0 +1,14 @@
package ru.otus.example.mybatisdemo.repositories;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import ru.otus.example.mybatisdemo.models.EMail;
import java.util.List;
@Mapper
public interface EmailRepository {
@Select("select * from emails where student_id = #{studentId}")
List<EMail> getEmailsByStudentId(long studentId);
}
@@ -0,0 +1,42 @@
package ru.otus.example.mybatisdemo.repositories;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.FetchType;
import ru.otus.example.mybatisdemo.models.Avatar;
import ru.otus.example.mybatisdemo.models.OtusStudent;
import java.util.List;
@Mapper
public interface OtusStudentRepository {
@Select("select * from otus_students")
@Results(id = "studentAllMap", value = {
@Result(property = "id", column = "id"),
@Result(property = "name", column = "name"),
@Result(property = "avatar", column = "avatar_id", javaType = Avatar.class,
one = @One(select = "ru.otus.example.mybatisdemo.repositories.AvatarRepository.getAvatarById", fetchType = FetchType.EAGER)),
@Result(property = "emails", column = "id", javaType = List.class,
many = @Many(select = "ru.otus.example.mybatisdemo.repositories.EmailRepository.getEmailsByStudentId", fetchType = FetchType.EAGER)),
@Result(property = "courses", column = "id", javaType = List.class,
many = @Many(select = "ru.otus.example.mybatisdemo.repositories.CourseRepository.getCoursesByStudentId", fetchType = FetchType.EAGER))
})
List<OtusStudent> findAllWithAllInfo();
@Select("select * from otus_students where id = #{id}")
@ResultMap("studentAllMap")
OtusStudent findById(long id);
@Select("select count(*) as students_count from otus_students")
long getStudentsCount();
@Insert("insert into otus_students(name, avatar_id) values (#{name}, #{avatar.id})")
void insert(OtusStudent student);
@Update("update otus_students set name = #{name} where id = #{id}")
void updateName(OtusStudent student);
@Delete("delete from otus_students where id = #{id}")
void deleteById(long id);
}
@@ -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,103 @@
package ru.otus.example.mybatisdemo.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.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;
import ru.otus.example.mybatisdemo.models.Avatar;
import ru.otus.example.mybatisdemo.models.OtusStudent;
import static org.assertj.core.api.Assertions.assertThat;
@DisplayName("Репозиторий на основе MyBatis для работы со студентами ")
@SpringBootTest
@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;
@DisplayName("должен загружать список всех студентов с полной информацией о них")
@Test
void shouldReturnCorrectStudentsListWithAllInfo() {
val students = studentRepositoryMyBatis.findAllWithAllInfo();
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);
}
@DisplayName("должен загружать число студентов в БД")
@Test
void shouldReturnCorrectStudentsCount() {
long studentsCount = studentRepositoryMyBatis.getStudentsCount();
assertThat(studentsCount).isEqualTo(EXPECTED_NUMBER_OF_STUDENTS);
}
@DisplayName(" должен загружать информацию о нужном студенте")
@Test
void shouldFindExpectedStudentById(){
val actualStudent = studentRepositoryMyBatis.findById(FIRST_STUDENT_ID);
assertThat(actualStudent).isNotNull();
assertThat(actualStudent.getName()).isEqualTo(FIRST_STUDENT_NAME);
assertThat(actualStudent.getAvatar()).isNotNull()
.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(STUDENT_NEW_NAME);
expectedStudent.setAvatar(new Avatar(FIRST_AVATAR_ID, FIRST_AVATAR_URL));
studentRepositoryMyBatis.insert(expectedStudent);
val actualStudent = studentRepositoryMyBatis.findById(INSERTED_STUDENT_ID);
assertThat(actualStudent).isNotNull().isEqualToComparingOnlyGivenFields(expectedStudent, FIELD_NAME);
}
@DisplayName(" должен обновлять имя студента в БД")
@Test
void shouldUpdateStudentName() {
val student = studentRepositoryMyBatis.findById(FIRST_STUDENT_ID);
student.setName(STUDENT_NEW_NAME);
studentRepositoryMyBatis.updateName(student);
val actualStudent = studentRepositoryMyBatis.findById(FIRST_STUDENT_ID);
assertThat(actualStudent).isNotNull().hasFieldOrPropertyWithValue(FIELD_NAME, student.getName());
}
@DisplayName("должен удалять студента из БД по id")
@Test
void shouldDeleteStudentFromDbById() {
val studentsCountBefore = studentRepositoryMyBatis.getStudentsCount();
studentRepositoryMyBatis.deleteById(FIRST_STUDENT_ID);
val studentsCountAfter = studentRepositoryMyBatis.getStudentsCount();
assertThat(studentsCountBefore - studentsCountAfter).isEqualTo(1);
}
}
@@ -0,0 +1,8 @@
spring:
datasource:
url: jdbc:h2:mem:testdb
initialization-mode: always
logging:
level:
ru.otus.example.mybatisdemo.repositories: TRACE
@@ -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);
@@ -0,0 +1,17 @@
<?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>demo-projects</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<modules>
<module>spring-jdbc-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 @@
# spring-jdbc-demo
Пример работы с БД через jdbc
@@ -0,0 +1,71 @@
<?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.4.1</version>
<relativePath/>
</parent>
<groupId>ru.otus.example</groupId>
<artifactId>spring-jdbc-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-jdbc-demo</name>
<description>Spring jdbc demo</description>
<properties>
<java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</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,13 @@
package ru.otus.example.springjdbcdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringJdbcDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringJdbcDemoApplication.class, args);
}
}
@@ -0,0 +1,13 @@
package ru.otus.example.springjdbcdemo.models;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Avatar {
private long id;
private String photoUrl;
}
@@ -0,0 +1,13 @@
package ru.otus.example.springjdbcdemo.models;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Course {
private long id;
private String name;
}
@@ -0,0 +1,13 @@
package ru.otus.example.springjdbcdemo.models;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class EMail {
private long id;
private String email;
}
@@ -0,0 +1,18 @@
package ru.otus.example.springjdbcdemo.models;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class OtusStudent {
private long id;
private String name;
private Avatar avatar;
private List<EMail> emails;
private List<Course> courses;
}
@@ -0,0 +1,9 @@
package ru.otus.example.springjdbcdemo.repositories;
import ru.otus.example.springjdbcdemo.models.Course;
import java.util.List;
public interface CourseRepositoryJdbc {
List<Course> findAllUsed();
}
@@ -0,0 +1,36 @@
package ru.otus.example.springjdbcdemo.repositories;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import ru.otus.example.springjdbcdemo.models.Course;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
@Repository
@RequiredArgsConstructor
public class CourseRepositoryJdbcImpl implements CourseRepositoryJdbc {
@Autowired
private final JdbcOperations op;
@Override
public List<Course> findAllUsed() {
return op.query("select c.id, c.name " +
"from courses c inner join student_courses sc on c.id = sc.course_id " +
"group by c.id, c.name " +
"order by c.name", new CourseRowMapper());
}
private static class CourseRowMapper implements RowMapper<Course> {
@Override
public Course mapRow(ResultSet rs, int i) throws SQLException {
return new Course(rs.getLong(1), rs.getString(2));
}
}
}
@@ -0,0 +1,9 @@
package ru.otus.example.springjdbcdemo.repositories;
import ru.otus.example.springjdbcdemo.models.OtusStudent;
import java.util.List;
public interface OtusStudentRepositoryJdbc {
List<OtusStudent> findAllWithAllInfo();
}
@@ -0,0 +1,50 @@
package ru.otus.example.springjdbcdemo.repositories;
import lombok.RequiredArgsConstructor;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.stereotype.Repository;
import ru.otus.example.springjdbcdemo.models.Course;
import ru.otus.example.springjdbcdemo.models.OtusStudent;
import ru.otus.example.springjdbcdemo.repositories.ext.OtusStudentResultSetExtractor;
import ru.otus.example.springjdbcdemo.repositories.ext.StudentCourseRelation;
import java.util.*;
import java.util.stream.Collectors;
@Repository
@RequiredArgsConstructor
public class OtusStudentRepositoryJdbcImpl implements OtusStudentRepositoryJdbc {
private final CourseRepositoryJdbc courseRepository;
private final JdbcOperations op;
@Override
public List<OtusStudent> findAllWithAllInfo() {
List<Course> courses = courseRepository.findAllUsed();
List<StudentCourseRelation> relations = getAllRelations();
Map<Long, OtusStudent> students =
op.query("select os.id, os.name, a.id avatar_id, a.photo_url, e.id email_id, e.email " +
"from (otus_students os left join avatars a on " +
"os.avatar_id = a.id) left join emails e on os.id = e.student_id",
new OtusStudentResultSetExtractor());
mergeStudentsInfo(students, courses, relations);
return new ArrayList<>(Objects.requireNonNull(students).values());
}
private List<StudentCourseRelation> getAllRelations() {
return op.query("select student_id, course_id from student_courses sc order by student_id, course_id",
(rs, i) -> new StudentCourseRelation(rs.getLong(1), rs.getLong(2)));
}
private void mergeStudentsInfo(Map<Long, OtusStudent> students, List<Course> courses, List<StudentCourseRelation> relations) {
Map<Long, Course> coursesMap = courses.stream().collect(Collectors.toMap(Course::getId, c -> c));
relations.forEach(r -> {
if (students.containsKey(r.getStudentId()) && coursesMap.containsKey(r.getCourseId())) {
students.get(r.getStudentId()).getCourses().add(coursesMap.get(r.getCourseId()));
}
});
}
}
@@ -0,0 +1,37 @@
package ru.otus.example.springjdbcdemo.repositories.ext;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ResultSetExtractor;
import ru.otus.example.springjdbcdemo.models.Avatar;
import ru.otus.example.springjdbcdemo.models.EMail;
import ru.otus.example.springjdbcdemo.models.OtusStudent;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class OtusStudentResultSetExtractor implements
ResultSetExtractor<Map<Long, OtusStudent>> {
@Override
public Map<Long, OtusStudent> extractData(ResultSet rs) throws SQLException,
DataAccessException {
Map<Long, OtusStudent> students = new HashMap<>();
while (rs.next()) {
long id = rs.getLong("id");
OtusStudent student = students.get(id);
if (student == null) {
student = new OtusStudent(id, rs.getString("name"),
new Avatar(rs.getLong("avatar_id"), rs.getString("photo_url")),
new ArrayList<>(), new ArrayList<>());
students.put(student.getId(), student);
}
student.getEmails().add(new EMail(rs.getLong("email_id"),
rs.getString("email")));
}
return students;
}
}
@@ -0,0 +1,11 @@
package ru.otus.example.springjdbcdemo.repositories.ext;
import lombok.Data;
import lombok.RequiredArgsConstructor;
@Data
@RequiredArgsConstructor
public class StudentCourseRelation {
private final long studentId;
private final long courseId;
}
@@ -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,35 @@
package ru.otus.example.springjdbcdemo.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.jdbc.JdbcTest;
import org.springframework.context.annotation.Import;
import static org.assertj.core.api.Assertions.assertThat;
@DisplayName("Репозиторий на основе Jdbc для работы со студентами ")
@JdbcTest
@Import({OtusStudentRepositoryJdbcImpl.class, CourseRepositoryJdbcImpl.class})
class OtusStudentRepositoryJdbcImplTest {
private static final int EXPECTED_NUMBER_OF_STUDENTS = 10;
@Autowired
private OtusStudentRepositoryJdbcImpl repositoryJdbc;
@DisplayName("должен загружать список всех студентов с полной информацией о них")
@Test
void shouldReturnCorrectStudentsListWithAllInfo() {
val students = repositoryJdbc.findAllWithAllInfo();
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);
students.forEach(System.out::println);
}
}
@@ -0,0 +1,4 @@
spring:
datasource:
url: jdbc:h2:mem:testdb
initialization-mode: always
@@ -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);
@@ -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,71 @@
<?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.4.1</version>
<relativePath/>
</parent>
<groupId>ru.otus.example</groupId>
<artifactId>orm-exercise</artifactId>
<name>orm-exercise</name>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</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,17 @@
package ru.otus.example.ormdemo;
import org.h2.tools.Console;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.sql.SQLException;
@SpringBootApplication
public class OrmDemoApplication {
public static void main(String[] args) throws SQLException {
SpringApplication.run(OrmDemoApplication.class, args);
Console.main(args);
}
}
@@ -0,0 +1,15 @@
package ru.otus.example.ormdemo.models;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Avatar {
private long id;
private String photoUrl;
}
@@ -0,0 +1,15 @@
package ru.otus.example.ormdemo.models;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Course {
private long id;
private String name;
}
@@ -0,0 +1,15 @@
package ru.otus.example.ormdemo.models;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class EMail {
private long id;
private String email;
}
@@ -0,0 +1,18 @@
package ru.otus.example.ormdemo.models;
import lombok.*;
import javax.persistence.*;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OtusStudent {
private long id;
private String name;
//private Avatar avatar;
//private List<EMail> emails;
//private List<Course> courses;
}
@@ -0,0 +1,20 @@
spring:
datasource:
url: jdbc:h2:mem:testdb
initialization-mode: never
jpa:
generate-ddl: true
hibernate:
ddl-auto: create
properties:
hibernate:
format_sql: true
show-sql: true
logging:
level:
ROOT: ERROR
@@ -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,71 @@
<?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.4.1</version>
<relativePath/>
</parent>
<groupId>ru.otus.example</groupId>
<artifactId>orm-solution-01</artifactId>
<name>orm-solution-01</name>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</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,17 @@
package ru.otus.example.ormdemo;
import org.h2.tools.Console;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.sql.SQLException;
@SpringBootApplication
public class OrmDemoApplication {
public static void main(String[] args) throws SQLException {
SpringApplication.run(OrmDemoApplication.class, args);
Console.main(args);
}
}
@@ -0,0 +1,17 @@
package ru.otus.example.ormdemo.models;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class Avatar {
@Id
private long id;
private String photoUrl;
}
@@ -0,0 +1,17 @@
package ru.otus.example.ormdemo.models;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class Course {
@Id
private long id;
private String name;
}
@@ -0,0 +1,17 @@
package ru.otus.example.ormdemo.models;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class EMail {
@Id
private long id;
private String email;
}
@@ -0,0 +1,20 @@
package ru.otus.example.ormdemo.models;
import lombok.*;
import javax.persistence.*;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity // Указывает, что данный класс является сущностью
public class OtusStudent {
@Id // Позволяет указать какое поле является идентификатором
private long id;
private String name;
//private Avatar avatar;
//private List<EMail> emails;
//private List<Course> courses;
}
@@ -0,0 +1,20 @@
spring:
datasource:
url: jdbc:h2:mem:testdb
initialization-mode: never
jpa:
generate-ddl: true
hibernate:
ddl-auto: create
properties:
hibernate:
format_sql: true
show-sql: true
logging:
level:
ROOT: ERROR
@@ -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,71 @@
<?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.4.1</version>
<relativePath/>
</parent>
<groupId>ru.otus.example</groupId>
<artifactId>orm-solution-02</artifactId>
<name>orm-solution-02</name>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</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,17 @@
package ru.otus.example.ormdemo;
import org.h2.tools.Console;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.sql.SQLException;
@SpringBootApplication
public class OrmDemoApplication {
public static void main(String[] args) throws SQLException {
SpringApplication.run(OrmDemoApplication.class, args);
Console.main(args);
}
}
@@ -0,0 +1,20 @@
package ru.otus.example.ormdemo.models;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "avatars")
public class Avatar {
@Id
private long id;
@Column(name = "photo_url")
private String photoUrl;
}
@@ -0,0 +1,20 @@
package ru.otus.example.ormdemo.models;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "courses")
public class Course {
@Id
private long id;
@Column(name = "name")
private String name;
}
@@ -0,0 +1,21 @@
package ru.otus.example.ormdemo.models;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "emails")
public class EMail {
@Id
private long id;
@Column(name = "email")
private String email;
}
@@ -0,0 +1,24 @@
package ru.otus.example.ormdemo.models;
import lombok.*;
import javax.persistence.*;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity // Указывает, что данный класс является сущностью
@Table(name = "otus_students") // Задает имя таблицы, на которую будет отображаться сущность
public class OtusStudent {
@Id // Позволяет указать какое поле является идентификатором
private long id;
// Задает имя и некоторые свойства поля таблицы, на которое будет отображаться поле сущности
@Column(name = "name")
private String name;
//private Avatar avatar;
//private List<EMail> emails;
//private List<Course> courses;
}
@@ -0,0 +1,20 @@
spring:
datasource:
url: jdbc:h2:mem:testdb
initialization-mode: never
jpa:
generate-ddl: true
hibernate:
ddl-auto: create
properties:
hibernate:
format_sql: true
show-sql: true
logging:
level:
ROOT: ERROR
@@ -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,71 @@
<?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.4.1</version>
<relativePath/>
</parent>
<groupId>ru.otus.example</groupId>
<artifactId>orm-solution-03</artifactId>
<name>orm-solution-03</name>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</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,17 @@
package ru.otus.example.ormdemo;
import org.h2.tools.Console;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.sql.SQLException;
@SpringBootApplication
public class OrmDemoApplication {
public static void main(String[] args) throws SQLException {
SpringApplication.run(OrmDemoApplication.class, args);
Console.main(args);
}
}
@@ -0,0 +1,21 @@
package ru.otus.example.ormdemo.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")
private String photoUrl;
}
@@ -0,0 +1,21 @@
package ru.otus.example.ormdemo.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")
private String name;
}
@@ -0,0 +1,22 @@
package ru.otus.example.ormdemo.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")
private String email;
}
@@ -0,0 +1,25 @@
package ru.otus.example.ormdemo.models;
import lombok.*;
import javax.persistence.*;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity // Указывает, что данный класс является сущностью
@Table(name = "otus_students") // Задает имя таблицы, на которую будет отображаться сущность
public class OtusStudent {
@Id // Позволяет указать какое поле является идентификатором
@GeneratedValue(strategy = GenerationType.IDENTITY) // Позволяет указать стратегию генерации id
private long id;
// Задает имя и некоторые свойства поля таблицы, на которое будет отображаться поле сущности
@Column(name = "name")
private String name;
//private Avatar avatar;
//private List<EMail> emails;
//private List<Course> courses;
}
@@ -0,0 +1,20 @@
spring:
datasource:
url: jdbc:h2:mem:testdb
initialization-mode: never
jpa:
generate-ddl: true
hibernate:
ddl-auto: create
properties:
hibernate:
format_sql: true
show-sql: true
logging:
level:
ROOT: ERROR
@@ -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,71 @@
<?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.4.1</version>
<relativePath/>
</parent>
<groupId>ru.otus.example</groupId>
<artifactId>orm-solution-04</artifactId>
<name>orm-solution-04</name>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</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,17 @@
package ru.otus.example.ormdemo;
import org.h2.tools.Console;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.sql.SQLException;
@SpringBootApplication
public class OrmDemoApplication {
public static void main(String[] args) throws SQLException {
SpringApplication.run(OrmDemoApplication.class, args);
Console.main(args);
}
}
@@ -0,0 +1,21 @@
package ru.otus.example.ormdemo.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")
private String photoUrl;
}
@@ -0,0 +1,21 @@
package ru.otus.example.ormdemo.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")
private String name;
}
@@ -0,0 +1,22 @@
package ru.otus.example.ormdemo.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")
private String email;
}
@@ -0,0 +1,30 @@
package ru.otus.example.ormdemo.models;
import lombok.*;
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;
//private List<EMail> emails;
//private List<Course> courses;
}
@@ -0,0 +1,20 @@
spring:
datasource:
url: jdbc:h2:mem:testdb
initialization-mode: never
jpa:
generate-ddl: true
hibernate:
ddl-auto: create
properties:
hibernate:
format_sql: true
show-sql: true
logging:
level:
ROOT: ERROR
@@ -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,71 @@
<?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.4.1</version>
<relativePath/>
</parent>
<groupId>ru.otus.example</groupId>
<artifactId>orm-solution-05</artifactId>
<name>orm-solution-05</name>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</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,17 @@
package ru.otus.example.ormdemo;
import org.h2.tools.Console;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.sql.SQLException;
@SpringBootApplication
public class OrmDemoApplication {
public static void main(String[] args) throws SQLException {
SpringApplication.run(OrmDemoApplication.class, args);
Console.main(args);
}
}
@@ -0,0 +1,21 @@
package ru.otus.example.ormdemo.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")
private String photoUrl;
}
@@ -0,0 +1,21 @@
package ru.otus.example.ormdemo.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")
private String name;
}
@@ -0,0 +1,22 @@
package ru.otus.example.ormdemo.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")
private String email;
}
@@ -0,0 +1,34 @@
package ru.otus.example.ormdemo.models;
import lombok.*;
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;
//private List<Course> courses;
}
@@ -0,0 +1,20 @@
spring:
datasource:
url: jdbc:h2:mem:testdb
initialization-mode: never
jpa:
generate-ddl: true
hibernate:
ddl-auto: create
properties:
hibernate:
format_sql: true
show-sql: true
logging:
level:
ROOT: ERROR
@@ -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,71 @@
<?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.4.1</version>
<relativePath/>
</parent>
<groupId>ru.otus.example</groupId>
<artifactId>orm-solution-final</artifactId>
<name>orm-solution-final</name>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</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,17 @@
package ru.otus.example.ormdemo;
import org.h2.tools.Console;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.sql.SQLException;
@SpringBootApplication
public class OrmDemoApplication {
public static void main(String[] args) throws SQLException {
SpringApplication.run(OrmDemoApplication.class, args);
Console.main(args);
}
}
@@ -0,0 +1,21 @@
package ru.otus.example.ormdemo.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")
private String photoUrl;
}
@@ -0,0 +1,21 @@
package ru.otus.example.ormdemo.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")
private String name;
}
@@ -0,0 +1,22 @@
package ru.otus.example.ormdemo.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")
private String email;
}
@@ -0,0 +1,39 @@
package ru.otus.example.ormdemo.models;
import lombok.*;
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;
// Указывает на связь между таблицами "многие ко многим"
@ManyToMany(targetEntity = Course.class, fetch = FetchType.LAZY /*, cascade = CascadeType.ALL*/)
// Задает таблицу связей между таблицами для хранения родительской и связанной сущностью
@JoinTable(name = "student_courses", joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id"))
private List<Course> courses;
}
@@ -0,0 +1,20 @@
spring:
datasource:
url: jdbc:h2:mem:testdb
initialization-mode: never
jpa:
generate-ddl: true
hibernate:
ddl-auto: create
properties:
hibernate:
format_sql: true
show-sql: true
logging:
level:
ROOT: ERROR
@@ -0,0 +1,22 @@
<?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>orm-class-work</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<modules>
<module>orm-exercise</module>
<module>orm-solution-01</module>
<module>orm-solution-02</module>
<module>orm-solution-03</module>
<module>orm-solution-04</module>
<module>orm-solution-05</module>
<module>orm-solution-final</module>
</modules>
</project>