diff --git a/2023-01/spring-09-jdbc/jdbc-demo-exercise/.gitignore b/2023-01/spring-09-jdbc/jdbc-demo-exercise/.gitignore new file mode 100644 index 00000000..e62c33c2 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-exercise/.gitignore @@ -0,0 +1,4 @@ +.idea/ +*.iml + +target/ diff --git a/2023-01/spring-09-jdbc/jdbc-demo-exercise/pom.xml b/2023-01/spring-09-jdbc/jdbc-demo-exercise/pom.xml new file mode 100644 index 00000000..36acd2ec --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-exercise/pom.xml @@ -0,0 +1,65 @@ + + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + + 3.0.2 + + + + ru.otus + jdbc-demo-exercise + 1.0-SNAPSHOT + + + + + 17 + 17 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-jdbc + + + com.h2database + h2 + 2.1.212 + + + org.projectlombok + lombok + provided + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/main/java/ru/otus/spring/Main.java b/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/main/java/ru/otus/spring/Main.java new file mode 100644 index 00000000..8916eb04 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/main/java/ru/otus/spring/Main.java @@ -0,0 +1,20 @@ +package ru.otus.spring; + +import org.h2.tools.Console; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ApplicationContext; +import ru.otus.spring.dao.PersonDao; + +@SpringBootApplication +public class Main { + + public static void main(String[] args) throws Exception { + + ApplicationContext context = SpringApplication.run(Main.class); + + PersonDao dao = context.getBean(PersonDao.class); + + Console.main(args); + } +} diff --git a/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/main/java/ru/otus/spring/dao/PersonDao.java b/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/main/java/ru/otus/spring/dao/PersonDao.java new file mode 100644 index 00000000..9fa01df3 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/main/java/ru/otus/spring/dao/PersonDao.java @@ -0,0 +1,17 @@ +package ru.otus.spring.dao; + +import ru.otus.spring.domain.Person; + +import java.util.List; + +public interface PersonDao { + int count(); + + void insert(Person person); + + Person getById(long id); + + List getAll(); + + void deleteById(long id); +} diff --git a/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/main/java/ru/otus/spring/dao/PersonDaoJdbc.java b/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/main/java/ru/otus/spring/dao/PersonDaoJdbc.java new file mode 100644 index 00000000..836b737f --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/main/java/ru/otus/spring/dao/PersonDaoJdbc.java @@ -0,0 +1,42 @@ +package ru.otus.spring.dao; + +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.stereotype.Repository; +import ru.otus.spring.domain.Person; + +import java.util.List; + +@Repository +public class PersonDaoJdbc implements PersonDao { + private final JdbcOperations jdbc; + + public PersonDaoJdbc(JdbcOperations jdbcOperations) + { + this.jdbc = jdbcOperations; + } + + @Override + public int count() { + return 0; + } + + @Override + public void insert(Person person) { + + } + + @Override + public Person getById(long id) { + return null; + } + + @Override + public List getAll() { + return null; + } + + @Override + public void deleteById(long id) { + + } +} diff --git a/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/main/java/ru/otus/spring/domain/Person.java b/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/main/java/ru/otus/spring/domain/Person.java new file mode 100644 index 00000000..a78f21e5 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/main/java/ru/otus/spring/domain/Person.java @@ -0,0 +1,11 @@ +package ru.otus.spring.domain; + +import lombok.Data; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Data +public class Person { + private final long id; + private final String name; +} diff --git a/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/main/resources/application.yml b/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/main/resources/application.yml new file mode 100644 index 00000000..8f40ea4e --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/main/resources/application.yml @@ -0,0 +1,16 @@ +spring: + datasource: + url: jdbc:h2:mem:testdb + #initialization-mode: always + #schema: schema.sql + #data: data.sql + sql: + init: + mode: always + data-locations: data.sql + schema-locations: schema.sql + h2: + console: + path: /h2-console + settings: + web-allow-others: true \ No newline at end of file diff --git a/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/main/resources/data.sql b/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/main/resources/data.sql new file mode 100644 index 00000000..240a5b4e --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/main/resources/data.sql @@ -0,0 +1 @@ +insert into persons (id, `name`) values (1, 'masha'); diff --git a/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/main/resources/schema.sql b/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/main/resources/schema.sql new file mode 100644 index 00000000..87aadc44 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/main/resources/schema.sql @@ -0,0 +1,2 @@ +DROP TABLE IF EXISTS PERSONS; +CREATE TABLE PERSONS(ID BIGINT PRIMARY KEY, NAME VARCHAR(255)); diff --git a/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/test/java/ru/otus/spring/dao/PersonDaoJdbcTest.java b/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/test/java/ru/otus/spring/dao/PersonDaoJdbcTest.java new file mode 100644 index 00000000..874b7904 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/test/java/ru/otus/spring/dao/PersonDaoJdbcTest.java @@ -0,0 +1,93 @@ +package ru.otus.spring.dao; + +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 org.springframework.dao.EmptyResultDataAccessException; +import ru.otus.spring.domain.Person; + +import java.util.List; + +import static org.assertj.core.api.Assertions.*; + +@DisplayName("Dao для работы с пёрсонами должно") +@JdbcTest +@Import(PersonDaoJdbc.class) +class PersonDaoJdbcTest { + + private static final int EXPECTED_PERSONS_COUNT = 1; + private static final int EXISTING_PERSON_ID = 1; + private static final String EXISTING_PERSON_NAME = "Ivan"; + + @Autowired + private PersonDaoJdbc personDao; + + @DisplayName("возвращать ожидаемое количество пёрсонов в БД") + @Test + void shouldReturnExpectedPersonCount() { + int actualPersonsCount = personDao.count(); + assertThat(actualPersonsCount).isEqualTo(EXPECTED_PERSONS_COUNT); + } + + @DisplayName("добавлять пёрсона в БД") + @Test + void shouldInsertPerson() { + int countBeforeInsert = personDao.count(); + assertThat(countBeforeInsert).isEqualTo(EXPECTED_PERSONS_COUNT); + + Person expectedPerson = new Person(2, "Igor"); + personDao.insert(expectedPerson); + + // Ошибка! Сейчас так проверяем т.к. больше нет других способов, + // когда появится getById, будем использовать его + int countAfterInsert = personDao.count(); + assertThat(countAfterInsert).isEqualTo(countBeforeInsert + 1); +/* + Person actualPerson = personDao.getById(expectedPerson.getId()); + assertThat(actualPerson).usingRecursiveComparison().isEqualTo(expectedPerson); +*/ + } + + @DisplayName("возвращать ожидаемого пёрсона по его id") + @Test + void shouldReturnExpectedPersonById() { + Person expectedPerson = new Person(EXISTING_PERSON_ID, EXISTING_PERSON_NAME); + Person actualPerson = personDao.getById(expectedPerson.getId()); + assertThat(actualPerson).usingRecursiveComparison().isEqualTo(expectedPerson); + } + + @DisplayName("удалять заданного пёрсона по его id") + @Test + void shouldCorrectDeletePersonById() { + // Ошибка! Сейчас так проверяем т.к. больше нет других способов, + // когда появится getById, тест будет выглядеть, как закомментированный блок ниже + int countBeforeDelete = personDao.count(); + assertThat(countBeforeDelete).isEqualTo(EXPECTED_PERSONS_COUNT); + + personDao.deleteById(EXISTING_PERSON_ID); + + int countAfterDelete = personDao.count(); + assertThat(countAfterDelete).isEqualTo(countBeforeDelete - 1); + + /* + assertThatCode(() -> personDao.getById(EXISTING_PERSON_ID)) + .doesNotThrowAnyException(); + + personDao.deleteById(EXISTING_PERSON_ID); + + assertThatThrownBy(() -> personDao.getById(EXISTING_PERSON_ID)) + .isInstanceOf(EmptyResultDataAccessException.class); + */ + } + + @DisplayName("возвращать ожидаемый список пёрсонов") + @Test + void shouldReturnExpectedPersonsList() { + Person expectedPerson = new Person(EXISTING_PERSON_ID, EXISTING_PERSON_NAME); + List actualPersonList = personDao.getAll(); + assertThat(actualPersonList) + .containsExactlyInAnyOrder(expectedPerson); + } +} \ No newline at end of file diff --git a/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/test/resources/application.yml b/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/test/resources/application.yml new file mode 100644 index 00000000..f7de231a --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/test/resources/application.yml @@ -0,0 +1,10 @@ +spring: + datasource: + url: jdbc:h2:mem:testdb + #initialization-mode: always + #data: data.sql + sql: + init: + mode: always + data-locations: data.sql + #schema-locations: schema.sql diff --git a/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/test/resources/data.sql b/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/test/resources/data.sql new file mode 100644 index 00000000..32d79cd1 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-exercise/src/test/resources/data.sql @@ -0,0 +1 @@ +insert into persons (id, `name`) values (1, 'Ivan'); diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-3/.gitignore b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/.gitignore new file mode 100644 index 00000000..e62c33c2 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/.gitignore @@ -0,0 +1,4 @@ +.idea/ +*.iml + +target/ diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-3/pom.xml b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/pom.xml new file mode 100644 index 00000000..d240349d --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/pom.xml @@ -0,0 +1,65 @@ + + + 4.0.0 + + ru.otus + jdbc-demo-solution-3 + 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + + 3.0.2 + + + + + + 17 + 17 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-jdbc + + + com.h2database + h2 + 2.1.212 + + + org.projectlombok + lombok + provided + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/main/java/ru/otus/spring/Main.java b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/main/java/ru/otus/spring/Main.java new file mode 100644 index 00000000..6c08834b --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/main/java/ru/otus/spring/Main.java @@ -0,0 +1,23 @@ +package ru.otus.spring; + +import org.h2.tools.Console; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ApplicationContext; +import ru.otus.spring.dao.PersonDao; +import ru.otus.spring.domain.Person; + +@SpringBootApplication +public class Main { + + public static void main(String[] args) throws Exception { + + ApplicationContext context = SpringApplication.run(Main.class); + + PersonDao dao = context.getBean(PersonDao.class); + + System.out.println("All count " + dao.count()); + + Console.main(args); + } +} diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/main/java/ru/otus/spring/dao/PersonDao.java b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/main/java/ru/otus/spring/dao/PersonDao.java new file mode 100644 index 00000000..f2c30f7c --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/main/java/ru/otus/spring/dao/PersonDao.java @@ -0,0 +1,18 @@ +package ru.otus.spring.dao; + +import ru.otus.spring.domain.Person; + +import java.util.List; + +public interface PersonDao { + + int count(); + + void insert(Person person); + + Person getById(long id); + + List getAll(); + + void deleteById(long id); +} diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/main/java/ru/otus/spring/dao/PersonDaoJdbc.java b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/main/java/ru/otus/spring/dao/PersonDaoJdbc.java new file mode 100644 index 00000000..87974d75 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/main/java/ru/otus/spring/dao/PersonDaoJdbc.java @@ -0,0 +1,45 @@ +package ru.otus.spring.dao; + +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.stereotype.Repository; +import ru.otus.spring.domain.Person; + +import java.util.List; + +@Repository +public class PersonDaoJdbc implements PersonDao { + + private final JdbcOperations jdbc; + + public PersonDaoJdbc(JdbcOperations jdbcOperations) + { + this.jdbc = jdbcOperations; + } + + @Override + public int count() { + Integer count = jdbc.queryForObject("select count(*) from persons", Integer.class); + return count == null? 0: count; + } + + @Override + public void insert(Person person) { + + } + + @Override + public Person getById(long id) { + return null; + } + + @Override + public List getAll() { + return null; + } + + @Override + public void deleteById(long id) { + + } + +} diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/main/java/ru/otus/spring/domain/Person.java b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/main/java/ru/otus/spring/domain/Person.java new file mode 100644 index 00000000..a78f21e5 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/main/java/ru/otus/spring/domain/Person.java @@ -0,0 +1,11 @@ +package ru.otus.spring.domain; + +import lombok.Data; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Data +public class Person { + private final long id; + private final String name; +} diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/main/resources/application.yml b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/main/resources/application.yml new file mode 100644 index 00000000..8f40ea4e --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/main/resources/application.yml @@ -0,0 +1,16 @@ +spring: + datasource: + url: jdbc:h2:mem:testdb + #initialization-mode: always + #schema: schema.sql + #data: data.sql + sql: + init: + mode: always + data-locations: data.sql + schema-locations: schema.sql + h2: + console: + path: /h2-console + settings: + web-allow-others: true \ No newline at end of file diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/main/resources/data.sql b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/main/resources/data.sql new file mode 100644 index 00000000..240a5b4e --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/main/resources/data.sql @@ -0,0 +1 @@ +insert into persons (id, `name`) values (1, 'masha'); diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/main/resources/schema.sql b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/main/resources/schema.sql new file mode 100644 index 00000000..87aadc44 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/main/resources/schema.sql @@ -0,0 +1,2 @@ +DROP TABLE IF EXISTS PERSONS; +CREATE TABLE PERSONS(ID BIGINT PRIMARY KEY, NAME VARCHAR(255)); diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/test/java/ru/otus/spring/dao/PersonDaoJdbcTest.java b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/test/java/ru/otus/spring/dao/PersonDaoJdbcTest.java new file mode 100644 index 00000000..31426b0a --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/test/java/ru/otus/spring/dao/PersonDaoJdbcTest.java @@ -0,0 +1,27 @@ +package ru.otus.spring.dao; + +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("Dao для работы с пёрсонами должно") +@JdbcTest +@Import(PersonDaoJdbc.class) +class PersonDaoJdbcTest { + + private static final int EXPECTED_PERSONS_COUNT = 1; + + @Autowired + private PersonDaoJdbc personDao; + + @DisplayName("возвращать ожидаемое количество пёрсонов в БД") + @Test + void shouldReturnExpectedPersonCount() { + int actualPersonsCount = personDao.count(); + assertThat(actualPersonsCount).isEqualTo(EXPECTED_PERSONS_COUNT); + } +} \ No newline at end of file diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/test/resources/application.yml b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/test/resources/application.yml new file mode 100644 index 00000000..f7de231a --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/test/resources/application.yml @@ -0,0 +1,10 @@ +spring: + datasource: + url: jdbc:h2:mem:testdb + #initialization-mode: always + #data: data.sql + sql: + init: + mode: always + data-locations: data.sql + #schema-locations: schema.sql diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/test/resources/data.sql b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/test/resources/data.sql new file mode 100644 index 00000000..32d79cd1 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-3/src/test/resources/data.sql @@ -0,0 +1 @@ +insert into persons (id, `name`) values (1, 'Ivan'); diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-4/.gitignore b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/.gitignore new file mode 100644 index 00000000..e62c33c2 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/.gitignore @@ -0,0 +1,4 @@ +.idea/ +*.iml + +target/ diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-4/pom.xml b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/pom.xml new file mode 100644 index 00000000..2415ad1c --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/pom.xml @@ -0,0 +1,65 @@ + + + 4.0.0 + + ru.otus + jdbc-demo-solution-4 + 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + + 3.0.2 + + + + + + 17 + 17 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-jdbc + + + com.h2database + h2 + 2.1.212 + + + org.projectlombok + lombok + provided + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/main/java/ru/otus/spring/Main.java b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/main/java/ru/otus/spring/Main.java new file mode 100644 index 00000000..2bc8e898 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/main/java/ru/otus/spring/Main.java @@ -0,0 +1,27 @@ +package ru.otus.spring; + +import org.h2.tools.Console; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ApplicationContext; +import ru.otus.spring.dao.PersonDao; +import ru.otus.spring.domain.Person; + +@SpringBootApplication +public class Main { + + public static void main(String[] args) throws Exception { + + ApplicationContext context = SpringApplication.run(Main.class); + + PersonDao dao = context.getBean(PersonDao.class); + + System.out.println("All count " + dao.count()); + + dao.insert(new Person(2, "ivan")); + + System.out.println("All count " + dao.count()); + + Console.main(args); + } +} diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/main/java/ru/otus/spring/dao/PersonDao.java b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/main/java/ru/otus/spring/dao/PersonDao.java new file mode 100644 index 00000000..f2c30f7c --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/main/java/ru/otus/spring/dao/PersonDao.java @@ -0,0 +1,18 @@ +package ru.otus.spring.dao; + +import ru.otus.spring.domain.Person; + +import java.util.List; + +public interface PersonDao { + + int count(); + + void insert(Person person); + + Person getById(long id); + + List getAll(); + + void deleteById(long id); +} diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/main/java/ru/otus/spring/dao/PersonDaoJdbc.java b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/main/java/ru/otus/spring/dao/PersonDaoJdbc.java new file mode 100644 index 00000000..eb2dabbb --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/main/java/ru/otus/spring/dao/PersonDaoJdbc.java @@ -0,0 +1,46 @@ +package ru.otus.spring.dao; + +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.stereotype.Repository; +import ru.otus.spring.domain.Person; + +import java.util.List; + + +@Repository +public class PersonDaoJdbc implements PersonDao { + + private final JdbcOperations jdbc; + + public PersonDaoJdbc(JdbcOperations jdbcOperations) + { + this.jdbc = jdbcOperations; + } + + @Override + public int count() { + Integer count = jdbc.queryForObject("select count(*) from persons", Integer.class); + return count == null? 0: count; + } + + @Override + public void insert(Person person) { + jdbc.update("insert into persons (id, name) values (?, ?)", person.getId(), person.getName()); + } + + @Override + public Person getById(long id) { + return null; + } + + @Override + public List getAll() { + return null; + } + + @Override + public void deleteById(long id) { + jdbc.update("delete from persons where id = ?", id); + } + +} diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/main/java/ru/otus/spring/domain/Person.java b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/main/java/ru/otus/spring/domain/Person.java new file mode 100644 index 00000000..a78f21e5 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/main/java/ru/otus/spring/domain/Person.java @@ -0,0 +1,11 @@ +package ru.otus.spring.domain; + +import lombok.Data; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Data +public class Person { + private final long id; + private final String name; +} diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/main/resources/application.yml b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/main/resources/application.yml new file mode 100644 index 00000000..8f40ea4e --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/main/resources/application.yml @@ -0,0 +1,16 @@ +spring: + datasource: + url: jdbc:h2:mem:testdb + #initialization-mode: always + #schema: schema.sql + #data: data.sql + sql: + init: + mode: always + data-locations: data.sql + schema-locations: schema.sql + h2: + console: + path: /h2-console + settings: + web-allow-others: true \ No newline at end of file diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/main/resources/data.sql b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/main/resources/data.sql new file mode 100644 index 00000000..240a5b4e --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/main/resources/data.sql @@ -0,0 +1 @@ +insert into persons (id, `name`) values (1, 'masha'); diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/main/resources/schema.sql b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/main/resources/schema.sql new file mode 100644 index 00000000..87aadc44 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/main/resources/schema.sql @@ -0,0 +1,2 @@ +DROP TABLE IF EXISTS PERSONS; +CREATE TABLE PERSONS(ID BIGINT PRIMARY KEY, NAME VARCHAR(255)); diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/test/java/ru/otus/spring/dao/PersonDaoJdbcTest.java b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/test/java/ru/otus/spring/dao/PersonDaoJdbcTest.java new file mode 100644 index 00000000..505a1bb0 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/test/java/ru/otus/spring/dao/PersonDaoJdbcTest.java @@ -0,0 +1,73 @@ +package ru.otus.spring.dao; + +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 ru.otus.spring.domain.Person; + +import static org.assertj.core.api.Assertions.assertThat; + +@DisplayName("Dao для работы с пёрсонами должно") +@JdbcTest +@Import(PersonDaoJdbc.class) +class PersonDaoJdbcTest { + + private static final int EXPECTED_PERSONS_COUNT = 1; + private static final int EXISTING_PERSON_ID = 1; + private static final String EXISTING_PERSON_NAME = "Ivan"; + + @Autowired + private PersonDaoJdbc personDao; + + @DisplayName("возвращать ожидаемое количество пёрсонов в БД") + @Test + void shouldReturnExpectedPersonCount() { + int actualPersonsCount = personDao.count(); + assertThat(actualPersonsCount).isEqualTo(EXPECTED_PERSONS_COUNT); + } + + @DisplayName("добавлять пёрсона в БД") + @Test + void shouldInsertPerson() { + int countBeforeInsert = personDao.count(); + assertThat(countBeforeInsert).isEqualTo(EXPECTED_PERSONS_COUNT); + + Person expectedPerson = new Person(2, "Igor"); + personDao.insert(expectedPerson); + + // Ошибка! Сейчас так проверяем т.к. больше нет других способов, + // когда появится getById, будем использовать его + int countAfterInsert = personDao.count(); + assertThat(countAfterInsert).isEqualTo(countBeforeInsert + 1); +/* + Person actualPerson = personDao.getById(expectedPerson.getId()); + assertThat(actualPerson).usingRecursiveComparison().isEqualTo(expectedPerson); +*/ + } + + @DisplayName("удалять заданного пёрсона по его id") + @Test + void shouldCorrectDeletePersonById() { + // Ошибка! Сейчас так проверяем т.к. больше нет других способов, + // когда появится getById, тест будет выглядеть, как закомментированный блок ниже + int countBeforeDelete = personDao.count(); + assertThat(countBeforeDelete).isEqualTo(EXPECTED_PERSONS_COUNT); + + personDao.deleteById(EXISTING_PERSON_ID); + + int countAfterDelete = personDao.count(); + assertThat(countAfterDelete).isEqualTo(countBeforeDelete - 1); + + /* + assertThatCode(() -> personDao.getById(EXISTING_PERSON_ID)) + .doesNotThrowAnyException(); + + personDao.deleteById(EXISTING_PERSON_ID); + + assertThatThrownBy(() -> personDao.getById(EXISTING_PERSON_ID)) + .isInstanceOf(EmptyResultDataAccessException.class); + */ + } +} \ No newline at end of file diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/test/resources/application.yml b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/test/resources/application.yml new file mode 100644 index 00000000..f7de231a --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/test/resources/application.yml @@ -0,0 +1,10 @@ +spring: + datasource: + url: jdbc:h2:mem:testdb + #initialization-mode: always + #data: data.sql + sql: + init: + mode: always + data-locations: data.sql + #schema-locations: schema.sql diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/test/resources/data.sql b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/test/resources/data.sql new file mode 100644 index 00000000..32d79cd1 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-4/src/test/resources/data.sql @@ -0,0 +1 @@ +insert into persons (id, `name`) values (1, 'Ivan'); diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-5/.gitignore b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/.gitignore new file mode 100644 index 00000000..e62c33c2 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/.gitignore @@ -0,0 +1,4 @@ +.idea/ +*.iml + +target/ diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-5/pom.xml b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/pom.xml new file mode 100644 index 00000000..288e3289 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/pom.xml @@ -0,0 +1,66 @@ + + + 4.0.0 + + ru.otus + jdbc-demo-solution-5 + 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + + 3.0.2 + + + + + + 17 + 17 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-jdbc + + + com.h2database + h2 + 2.1.212 + + + org.projectlombok + lombok + provided + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/main/java/ru/otus/spring/Main.java b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/main/java/ru/otus/spring/Main.java new file mode 100644 index 00000000..4bc2aca8 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/main/java/ru/otus/spring/Main.java @@ -0,0 +1,31 @@ +package ru.otus.spring; + +import org.h2.tools.Console; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ApplicationContext; +import ru.otus.spring.dao.PersonDao; +import ru.otus.spring.domain.Person; + +@SpringBootApplication +public class Main { + + public static void main(String[] args) throws Exception { + + ApplicationContext context = SpringApplication.run(Main.class); + + PersonDao dao = context.getBean(PersonDao.class); + + System.out.println("All count " + dao.count()); + + dao.insert(new Person(2, "ivan")); + + System.out.println("All count " + dao.count()); + + Person ivan = dao.getById(2); + + System.out.println("Ivan id: " + ivan.getId() + " name: " + ivan.getName()); + + Console.main(args); + } +} diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/main/java/ru/otus/spring/dao/PersonDao.java b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/main/java/ru/otus/spring/dao/PersonDao.java new file mode 100644 index 00000000..9fa01df3 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/main/java/ru/otus/spring/dao/PersonDao.java @@ -0,0 +1,17 @@ +package ru.otus.spring.dao; + +import ru.otus.spring.domain.Person; + +import java.util.List; + +public interface PersonDao { + int count(); + + void insert(Person person); + + Person getById(long id); + + List getAll(); + + void deleteById(long id); +} diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/main/java/ru/otus/spring/dao/PersonDaoJdbc.java b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/main/java/ru/otus/spring/dao/PersonDaoJdbc.java new file mode 100644 index 00000000..425ce000 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/main/java/ru/otus/spring/dao/PersonDaoJdbc.java @@ -0,0 +1,58 @@ +package ru.otus.spring.dao; + +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Repository; +import ru.otus.spring.domain.Person; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +@Repository +public class PersonDaoJdbc implements PersonDao { + + private final JdbcOperations jdbc; + + public PersonDaoJdbc(JdbcOperations jdbcOperations) + { + this.jdbc = jdbcOperations; + } + + @Override + public int count() { + Integer count = jdbc.queryForObject("select count(*) from persons", Integer.class); + return count == null? 0: count; + } + + @Override + public void insert(Person person) { + jdbc.update("insert into persons (id, name) values (?, ?)", person.getId(), person.getName()); + } + + @Override + public Person getById(long id) { + return jdbc.queryForObject("select id, name from persons where id = ?", new PersonMapper(), id); + } + + @Override + public List getAll() { + return jdbc.query("select id, name from persons", new PersonMapper()); + } + + @Override + public void deleteById(long id) { + jdbc.update("delete from persons where id = ?", id); + } + + + private static class PersonMapper implements RowMapper { + + @Override + public Person mapRow(ResultSet resultSet, int i) throws SQLException { + long id = resultSet.getLong("id"); + String name = resultSet.getString("name"); + return new Person(id, name); + } + } +} diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/main/java/ru/otus/spring/domain/Person.java b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/main/java/ru/otus/spring/domain/Person.java new file mode 100644 index 00000000..a78f21e5 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/main/java/ru/otus/spring/domain/Person.java @@ -0,0 +1,11 @@ +package ru.otus.spring.domain; + +import lombok.Data; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Data +public class Person { + private final long id; + private final String name; +} diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/main/resources/application.yml b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/main/resources/application.yml new file mode 100644 index 00000000..8f40ea4e --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/main/resources/application.yml @@ -0,0 +1,16 @@ +spring: + datasource: + url: jdbc:h2:mem:testdb + #initialization-mode: always + #schema: schema.sql + #data: data.sql + sql: + init: + mode: always + data-locations: data.sql + schema-locations: schema.sql + h2: + console: + path: /h2-console + settings: + web-allow-others: true \ No newline at end of file diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/main/resources/data.sql b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/main/resources/data.sql new file mode 100644 index 00000000..240a5b4e --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/main/resources/data.sql @@ -0,0 +1 @@ +insert into persons (id, `name`) values (1, 'masha'); diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/main/resources/schema.sql b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/main/resources/schema.sql new file mode 100644 index 00000000..87aadc44 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/main/resources/schema.sql @@ -0,0 +1,2 @@ +DROP TABLE IF EXISTS PERSONS; +CREATE TABLE PERSONS(ID BIGINT PRIMARY KEY, NAME VARCHAR(255)); diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/test/java/ru/otus/spring/dao/PersonDaoJdbcTest.java b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/test/java/ru/otus/spring/dao/PersonDaoJdbcTest.java new file mode 100644 index 00000000..3f76df0e --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/test/java/ru/otus/spring/dao/PersonDaoJdbcTest.java @@ -0,0 +1,71 @@ +package ru.otus.spring.dao; + +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 org.springframework.dao.EmptyResultDataAccessException; +import ru.otus.spring.domain.Person; + +import java.util.List; + +import static org.assertj.core.api.Assertions.*; + +@DisplayName("Dao для работы с пёрсонами должно") +@JdbcTest +@Import(PersonDaoJdbc.class) +class PersonDaoJdbcTest { + + private static final int EXPECTED_PERSONS_COUNT = 1; + private static final int EXISTING_PERSON_ID = 1; + private static final String EXISTING_PERSON_NAME = "Ivan"; + + @Autowired + private PersonDaoJdbc personDao; + + @DisplayName("возвращать ожидаемое количество пёрсонов в БД") + @Test + void shouldReturnExpectedPersonCount() { + int actualPersonsCount = personDao.count(); + assertThat(actualPersonsCount).isEqualTo(EXPECTED_PERSONS_COUNT); + } + + @DisplayName("добавлять пёрсона в БД") + @Test + void shouldInsertPerson() { + Person expectedPerson = new Person(2, "Igor"); + personDao.insert(expectedPerson); + Person actualPerson = personDao.getById(expectedPerson.getId()); + assertThat(actualPerson).usingRecursiveComparison().isEqualTo(expectedPerson); + } + + @DisplayName("возвращать ожидаемого пёрсона по его id") + @Test + void shouldReturnExpectedPersonById() { + Person expectedPerson = new Person(EXISTING_PERSON_ID, EXISTING_PERSON_NAME); + Person actualPerson = personDao.getById(expectedPerson.getId()); + assertThat(actualPerson).usingRecursiveComparison().isEqualTo(expectedPerson); + } + + @DisplayName("удалять заданного пёрсона по его id") + @Test + void shouldCorrectDeletePersonById() { + assertThatCode(() -> personDao.getById(EXISTING_PERSON_ID)) + .doesNotThrowAnyException(); + + personDao.deleteById(EXISTING_PERSON_ID); + + assertThatThrownBy(() -> personDao.getById(EXISTING_PERSON_ID)) + .isInstanceOf(EmptyResultDataAccessException.class); + } + + @DisplayName("возвращать ожидаемый список пёрсонов") + @Test + void shouldReturnExpectedPersonsList() { + Person expectedPerson = new Person(EXISTING_PERSON_ID, EXISTING_PERSON_NAME); + List actualPersonList = personDao.getAll(); + assertThat(actualPersonList) + .containsExactlyInAnyOrder(expectedPerson); + } +} \ No newline at end of file diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/test/resources/application.yml b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/test/resources/application.yml new file mode 100644 index 00000000..f7de231a --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/test/resources/application.yml @@ -0,0 +1,10 @@ +spring: + datasource: + url: jdbc:h2:mem:testdb + #initialization-mode: always + #data: data.sql + sql: + init: + mode: always + data-locations: data.sql + #schema-locations: schema.sql diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/test/resources/data.sql b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/test/resources/data.sql new file mode 100644 index 00000000..32d79cd1 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-5/src/test/resources/data.sql @@ -0,0 +1 @@ +insert into persons (id, `name`) values (1, 'Ivan'); diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-final/.gitignore b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/.gitignore new file mode 100644 index 00000000..e62c33c2 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/.gitignore @@ -0,0 +1,4 @@ +.idea/ +*.iml + +target/ diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-final/pom.xml b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/pom.xml new file mode 100644 index 00000000..923ba287 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/pom.xml @@ -0,0 +1,65 @@ + + + 4.0.0 + + ru.otus + jdbc-demo-solution-final + 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + + 3.0.2 + + + + + + 17 + 17 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-jdbc + + + com.h2database + h2 + 2.1.212 + + + org.projectlombok + lombok + provided + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/main/java/ru/otus/spring/Main.java b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/main/java/ru/otus/spring/Main.java new file mode 100644 index 00000000..05636811 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/main/java/ru/otus/spring/Main.java @@ -0,0 +1,33 @@ +package ru.otus.spring; + +import org.h2.tools.Console; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ApplicationContext; +import ru.otus.spring.dao.PersonDao; +import ru.otus.spring.domain.Person; + +@SpringBootApplication +public class Main { + + public static void main(String[] args) throws Exception { + + ApplicationContext context = SpringApplication.run(Main.class); + + PersonDao dao = context.getBean(PersonDao.class); + + System.out.println("All count " + dao.count()); + + dao.insert(new Person(2, "ivan")); + + System.out.println("All count " + dao.count()); + + Person ivan = dao.getById(2); + + System.out.println("Ivan id: " + ivan.getId() + " name: " + ivan.getName()); + + System.out.println(dao.getAll()); + + Console.main(args); + } +} diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/main/java/ru/otus/spring/dao/PersonDao.java b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/main/java/ru/otus/spring/dao/PersonDao.java new file mode 100644 index 00000000..f2c30f7c --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/main/java/ru/otus/spring/dao/PersonDao.java @@ -0,0 +1,18 @@ +package ru.otus.spring.dao; + +import ru.otus.spring.domain.Person; + +import java.util.List; + +public interface PersonDao { + + int count(); + + void insert(Person person); + + Person getById(long id); + + List getAll(); + + void deleteById(long id); +} diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/main/java/ru/otus/spring/dao/PersonDaoJdbc.java b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/main/java/ru/otus/spring/dao/PersonDaoJdbc.java new file mode 100644 index 00000000..e703d4f6 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/main/java/ru/otus/spring/dao/PersonDaoJdbc.java @@ -0,0 +1,71 @@ +package ru.otus.spring.dao; + +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; +import org.springframework.stereotype.Repository; +import ru.otus.spring.domain.Person; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +@Repository +public class PersonDaoJdbc implements PersonDao { + + private final JdbcOperations jdbc; + private final NamedParameterJdbcOperations namedParameterJdbcOperations; + + public PersonDaoJdbc(NamedParameterJdbcOperations namedParameterJdbcOperations) + { + // Это просто оставили, чтобы не переписывать код + // В идеале всё должно быть на NamedParameterJdbcOperations + this.jdbc = namedParameterJdbcOperations.getJdbcOperations(); + this.namedParameterJdbcOperations = namedParameterJdbcOperations; + } + + @Override + public int count() { + Integer count = jdbc.queryForObject("select count(*) from persons", Integer.class); + return count == null? 0: count; + } + + @Override + public void insert(Person person) { + namedParameterJdbcOperations.update("insert into persons (id, name) values (:id, :name)", + Map.of("id", person.getId(), "name", person.getName())); + } + + @Override + public Person getById(long id) { + Map params = Collections.singletonMap("id", id); + return namedParameterJdbcOperations.queryForObject( + "select id, name from persons where id = :id", params, new PersonMapper() + ); + } + + @Override + public List getAll() { + return jdbc.query("select id, name from persons", new PersonMapper()); + } + + @Override + public void deleteById(long id) { + Map params = Collections.singletonMap("id", id); + namedParameterJdbcOperations.update( + "delete from persons where id = :id", params + ); + } + + private static class PersonMapper implements RowMapper { + + @Override + public Person mapRow(ResultSet resultSet, int i) throws SQLException { + long id = resultSet.getLong("id"); + String name = resultSet.getString("name"); + return new Person(id, name); + } + } +} diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/main/java/ru/otus/spring/domain/Person.java b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/main/java/ru/otus/spring/domain/Person.java new file mode 100644 index 00000000..a78f21e5 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/main/java/ru/otus/spring/domain/Person.java @@ -0,0 +1,11 @@ +package ru.otus.spring.domain; + +import lombok.Data; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Data +public class Person { + private final long id; + private final String name; +} diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/main/resources/application.yml b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/main/resources/application.yml new file mode 100644 index 00000000..50b6c632 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/main/resources/application.yml @@ -0,0 +1,17 @@ +spring: + datasource: + url: jdbc:h2:mem:testdb + #initialization-mode: always + #schema: schema.sql + #data: data.sql + sql: + init: + mode: always + data-locations: data.sql + schema-locations: schema.sql + h2: + console: + path: /h2-console + settings: + web-allow-others: true + diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/main/resources/data.sql b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/main/resources/data.sql new file mode 100644 index 00000000..240a5b4e --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/main/resources/data.sql @@ -0,0 +1 @@ +insert into persons (id, `name`) values (1, 'masha'); diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/main/resources/schema.sql b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/main/resources/schema.sql new file mode 100644 index 00000000..87aadc44 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/main/resources/schema.sql @@ -0,0 +1,2 @@ +DROP TABLE IF EXISTS PERSONS; +CREATE TABLE PERSONS(ID BIGINT PRIMARY KEY, NAME VARCHAR(255)); diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/test/java/ru/otus/spring/dao/PersonDaoJdbcTest.java b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/test/java/ru/otus/spring/dao/PersonDaoJdbcTest.java new file mode 100644 index 00000000..87e83148 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/test/java/ru/otus/spring/dao/PersonDaoJdbcTest.java @@ -0,0 +1,90 @@ +package ru.otus.spring.dao; + +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 org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.test.annotation.Commit; +import org.springframework.test.annotation.Rollback; +import org.springframework.test.context.transaction.AfterTransaction; +import org.springframework.test.context.transaction.BeforeTransaction; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; +import ru.otus.spring.domain.Person; + +import java.util.List; + +import static org.assertj.core.api.Assertions.*; + +@DisplayName("Dao для работы с пёрсонами должно") +@JdbcTest +@Import(PersonDaoJdbc.class) +//@Transactional(propagation = Propagation.NOT_SUPPORTED) +class PersonDaoJdbcTest { + + private static final int EXPECTED_PERSONS_COUNT = 1; + private static final int EXISTING_PERSON_ID = 1; + private static final String EXISTING_PERSON_NAME = "Ivan"; + + @Autowired + private PersonDaoJdbc personDao; + + @BeforeTransaction + void beforeTransaction(){ + System.out.println("beforeTransaction"); + } + + @AfterTransaction + void afterTransaction(){ + System.out.println("afterTransaction"); + } + + @DisplayName("возвращать ожидаемое количество пёрсонов в БД") + @Test + void shouldReturnExpectedPersonCount() { + int actualPersonsCount = personDao.count(); + assertThat(actualPersonsCount).isEqualTo(EXPECTED_PERSONS_COUNT); + } + + //@Rollback(value = false) + //@Commit + @DisplayName("добавлять пёрсона в БД") + @Test + void shouldInsertPerson() { + Person expectedPerson = new Person(2, "Igor"); + personDao.insert(expectedPerson); + Person actualPerson = personDao.getById(expectedPerson.getId()); + assertThat(actualPerson).usingRecursiveComparison().isEqualTo(expectedPerson); + } + + @DisplayName("возвращать ожидаемого пёрсона по его id") + @Test + void shouldReturnExpectedPersonById() { + Person expectedPerson = new Person(EXISTING_PERSON_ID, EXISTING_PERSON_NAME); + Person actualPerson = personDao.getById(expectedPerson.getId()); + assertThat(actualPerson).usingRecursiveComparison().isEqualTo(expectedPerson); + } + + @DisplayName("удалять заданного пёрсона по его id") + @Test + void shouldCorrectDeletePersonById() { + assertThatCode(() -> personDao.getById(EXISTING_PERSON_ID)) + .doesNotThrowAnyException(); + + personDao.deleteById(EXISTING_PERSON_ID); + + assertThatThrownBy(() -> personDao.getById(EXISTING_PERSON_ID)) + .isInstanceOf(EmptyResultDataAccessException.class); + } + + @DisplayName("возвращать ожидаемый список пёрсонов") + @Test + void shouldReturnExpectedPersonsList() { + Person expectedPerson = new Person(EXISTING_PERSON_ID, EXISTING_PERSON_NAME); + List actualPersonList = personDao.getAll(); + assertThat(actualPersonList) + .containsExactlyInAnyOrder(expectedPerson); + } +} \ No newline at end of file diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/test/resources/application.yml b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/test/resources/application.yml new file mode 100644 index 00000000..f7de231a --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/test/resources/application.yml @@ -0,0 +1,10 @@ +spring: + datasource: + url: jdbc:h2:mem:testdb + #initialization-mode: always + #data: data.sql + sql: + init: + mode: always + data-locations: data.sql + #schema-locations: schema.sql diff --git a/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/test/resources/data.sql b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/test/resources/data.sql new file mode 100644 index 00000000..32d79cd1 --- /dev/null +++ b/2023-01/spring-09-jdbc/jdbc-demo-solution-final/src/test/resources/data.sql @@ -0,0 +1 @@ +insert into persons (id, `name`) values (1, 'Ivan'); diff --git a/2023-01/spring-09-jdbc/pom.xml b/2023-01/spring-09-jdbc/pom.xml new file mode 100644 index 00000000..1c941227 --- /dev/null +++ b/2023-01/spring-09-jdbc/pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + + ru.otus + jdbc-class-work + 1.0 + + pom + + + jdbc-demo-exercise + jdbc-demo-solution-3 + jdbc-demo-solution-4 + jdbc-demo-solution-5 + jdbc-demo-solution-final + +