Введени бла бла бла
Идем на сайт start.spring.io и генерируем пустой проект. Необходимые зависимости: Web, H2, JPA, Security, Thymeleaf. Качаем распаковываем архив, открываем проект в idea, ждем пока maven все скачает.
Результат: git checkout 8fa267
Создадим наше первое приложение. Пока что не нужно ничего понимать и не в чем разбираться. Главная задача - запустить приложение без ошибок, чтобы проверить что все норм. Главное правило урока:
не пытайся ничего понять, оно просто должно рабоать
...Находим этот файл в src/main/resources, переименовываем его в application.yml и вставляем вот это:
server:
port: 5000
security:
user:
name: user
password: 123
###
# Database Settings
###
spring:
datasource:
url: jdbc:h2:mem:example-app;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
platform: h2
username: sa
password:
driverClassName: org.h2.Driver
jpa:
database-platform: org.hibernate.dialect.H2Dialect
hibernate:
ddl-auto: update
properties:
hibernate:
show_sql: true
use_sql_comments: true
format_sql: trueВ происходящее пока не вникаем.
Для нашего приложения мы развернем встроенную(embedded) базу данных h2 в inmemory режиме. Источником данных будут служить два файла в папке src/main/resources: schema.sql и data.sql . Первый содержит ddl базы второй dml. Создадим первую таблицу с очень простой структурой.
(Если ваша таблица называется не PERSONS, то далее вам везде нужно подставлять вместо Person название своей таблицы)
CREATE TABLE PERSONS(
ID BIGINT IDENTITY NOT NULL PRIMARY KEY,
FIRST_NAME VARCHAR(100),
SECOND_NAME VARCHAR(100)
);INSERT INTO PERSONS (FIRST_NAME, SECOND_NAME) VALUES('Stupid', 'Student');В происходящее все еще не вникаем
Настало время Java) Идем в папку с кодом: src/main/java/com/tutorial/tutorial. Создаем пакет entities. В пакете создаем класс Person. Это будет Entity класс. Когда наше приложение будет обращаться к бд, оно будет возвращать результат в виде Entity классов. Поля Entity класса соответствуют полям соответствующей таблицы в бд. Код:
@Entity // По этой анотации spring понимает, что это Entity класс
@Table(name = "PERSONS") // По этой - с каокй таблице в бд связан этот Entity
public class Person {
@Id @GeneratedValue // Данное поле является AUTO INCREMENT PRIMARY KEY
private Long id;
@Column(name = "FIRST_NAME") // Данное поле соответствует столбцу FIRST_NAME
private String firstName;
@Column(name = "SECOND_NAME")
private String secondName;
// Constructor, getters and setters
}Теперь необходимо создать интерфейс для работы с бд. Создаем папку Repositories, а в ней класс PersonRepository. Вставляем туда этот код (сейчас максимально не вникаем):
@Repository
public interface PersonRepository extends CrudRepository<Person, Long>{}Если все таки хочется вникнуть, то вот repositories.
Последний штрих. Создаем папку Controllers. Внутри нее - класс Test. В него вставляем этот код:
@RestController
public class TestController {
@Autowired
PersonRepository personRepository;
@GetMapping("/")
public Iterable<Person> test(){
return personRepository.findAll();
}
}Идем на 127.0.0.1:5000, вводим user 123, получаем:
[{"firstName":"Stupid","secondName":"Student"}]Результат: git checkout e09d0d
Немного усложним структуру базы данных
CREATE TABLE PERSONS(
ID BIGINT IDENTITY NOT NULL PRIMARY KEY,
FIRST_NAME VARCHAR(100),
SECOND_NAME VARCHAR(100),
BIRTHDAY DATE
);
CREATE TABLE PHONES(
ID BIGINT IDENTITY NOT NULL PRIMARY KEY,
NUMBER VARCHAR(20),
PERSON_ID BIGINT NOT NULL,
FOREIGN KEY (PERSON_ID) REFERENCES PERSONS(ID)
);
CREATE TABLE PROFESSIONS(
ID BIGINT IDENTITY NOT NULL PRIMARY KEY,
TITLE VARCHAR(100)
);
CREATE TABLE PERSONS_PROFESSIONS(
PERSON_ID BIGINT,
PROFESSION_ID BIGINT,
FOREIGN KEY (PERSON_ID) REFERENCES PERSONS(ID),
FOREIGN KEY (PROFESSION_ID) REFERENCES PROFESSIONS(ID)
);INSERT INTO PERSONS (ID, FIRST_NAME, SECOND_NAME, BIRTHDAY)
VALUES
(1, 'Stupid', 'Student', '2018-01-20'),
(2, 'Nikita', 'Zubetch', '1997-01-10'),
(3, 'Stas', 'Pochipov', '1996-12-10');
INSERT INTO PHONES(ID, NUMBER, PERSON_ID)
VALUES
(1, '00000000000', 1),
(2, '11111111111', 2),
(3, '22222222222', 3);
INSERT INTO PROFESSIONS(ID, TITLE)
VALUES
(1, 'Po professii'),
(2, 'Ne po professii');
INSERT INTO PERSONS_PROFESSIONS(PERSON_ID, PROFESSION_ID)
VALUES
(1, 1),
(2, 2),
(3, 1);Между таблицами появились отношения и это надо отразить в Entity. Класс Phone:
@Entity
@Table(name = "PHONES")
public class Phone {
@Id @GeneratedValue
private long id;
private String number;
@ManyToOne // Много Phone относятся к одному Person
@JoinColumn(name = "PERSON_ID") // Имя FK столбца
@JsonBackReference // Пока даже не задумываемся что это
private Person person;
// Constructor, getters and setters
}И соответственно в классе Person появилось новое поле:
@OneToMany(mappedBy = "person")
@JsonManagedReference
private List<Phone> phones;Главное не путать @OneToMany и @ManyToOne местами.
Теперь посмотрим на класс Profession:
@Entity
@Table(name = "PROFESSIONS")
public class Profession {
@Id
@GeneratedValue
private long id;
private String title;
@ManyToMany
@JoinTable(name = "PERSONS_PROFESSIONS", // Имя соединительной таблицы
joinColumns = @JoinColumn(name = "PROFESSION_ID"), // FK на Profession,
// т.е. на себя
inverseJoinColumns = @JoinColumn(name = "PERSON_ID")) // Ссылка на Person
@JsonBackReference
private List<Person> persons;
// Constructor, getters and setters
}Соответствующее поле в Person:
@ManyToMany(mappedBy = "persons")
@JsonManagedReference
private List<Profession> professions;Проверяем:
[{
"id": 1,
"firstName": "Stupid",
"secondName": "Student",
"birthday": "2018-01-19",
"phones": [{"id":1,"number":"00000000000"}],
"professions":[{"title":"По профессии"}]
}, {
"id": 2,
"firstName":"Nikita",
"secondName":"Zubetch",
"birthday":"1997-01-09",
"phones":[{"id":2,"number":"11111111111"}],
"professions":[{"title":"Ne po professii"}]
}, {
"id":3,
"firstName":"Stas",
"secondName":"Pochipov",
"birthday":"1996-12-09",
"phones":[{"id":3,"number":"22222222222"}],
"professions":[{"title":"По профессии"}]
}]Результат: git checkout 59da03