<file_sep>package edu.javacourse.register.business;

// класс, исполняющий бизнес-логику
// Вызывается классом MarriageController, вызывает MarriageDao

import edu.javacourse.register.dao.MarriageDao;
import edu.javacourse.register.dao.PersonDao;
import edu.javacourse.register.domain.MarriageCertificate;
import edu.javacourse.register.domain.Person;
import edu.javacourse.register.domain.PersonFemale;
import edu.javacourse.register.domain.PersonMale;
import edu.javacourse.register.view.MarriageRequest;
import edu.javacourse.register.view.MarriageResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.List;

@Service("marriageService") //(специализация @Component) обычно используется если класс предостовляет какой-то бизнес-функционал
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON) // область видимости бинов (singleton или prototype)
public class MarriageManager {

    private static final Logger LOGGER = LoggerFactory.getLogger(MarriageManager.class);

    // при запуске MarriageManager, создается MarriageDao и PersonDao (оба в одном экземпляре)
    @Autowired // механизм автоматического связывания бинов
    private MarriageDao marriageDao;
    @Autowired // механизм автоматического связывания бинов
    private PersonDao personDao;


    // с помощью данных, пришедших в request, необходимо проверить, зарегистрирован ли брак
    @Transactional // Определение области действия одной транзакции БД (метод findMarriageCertificate)
    public MarriageResponse findMarriageCertificate(MarriageRequest request) {
        LOGGER.info("findMarriageCertificate called");

        // добавление 3 персон
        personDao.addPerson(getPerson(1));
        personDao.addPerson(getPerson(2));

        // получение свидетельства о браке
        MarriageCertificate mc = getMarriageCertificate();

        // сохранить полученное свидетельство о браке
        marriageDao.saveAndFlush(mc);

        // найти все сертификаты
//        marriageDao.findAll();

        // найти сертификаты по Id
//        marriageDao.findById(1L);

        // поиск по номеру, используя findByNumber
        List<MarriageCertificate> list = marriageDao.findByNumber("12345");
        // показать на экране, с помощью лямбда
        list.forEach(m -> LOGGER.info("MC:{}", m.getMarriageCertificateId()));

        LOGGER.info("----------------");

        // поиск по номеру, используя findByNum
        List<MarriageCertificate> list2 = marriageDao.findByNum("98765");
        list2.forEach(m -> LOGGER.info("MC:{}", m.getMarriageCertificateId()));

        LOGGER.info("----------------");

        // поиск по номеру, используя findSomething
        List<MarriageCertificate> list3 = marriageDao.findSomething("01928");
        list3.forEach(m -> LOGGER.info("MC:{}", m.getMarriageCertificateId()));

        return new MarriageResponse();
    }

    // создание MarriageCertificate
    private MarriageCertificate getMarriageCertificate() {

        MarriageCertificate mc = new MarriageCertificate();
        mc.setIssueDate(LocalDate.now());
        mc.setNumber("98765");
        mc.setActive(true);

        // нужно найти всех персон
        List<Person> persons = personDao.findPersons();

        for(Person person : persons) {
            if (person instanceof PersonMale) {
                mc.setHusband((PersonMale)person);
            } else {
                mc.setWife((PersonFemale)person);
            }
        }

        return mc;
    }

    // создание новой персоны
    private Person getPerson(int sex) {
        Person m = sex == 1 ? new PersonMale() : new PersonFemale();
        m.setFirstName("1_" + sex);
        m.setLastName("2_" + sex);
        m.setPatronymic("3_" + sex);
        m.setDateOfBirth(LocalDate.of(1991, 3, 12));
        return m;
    }

}
<file_sep>package edu.javacourse.register.dao;

// класс, который вызывает EntityManager (класс, который работает непостредственно с БД)

import edu.javacourse.register.domain.MarriageCertificate;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository // класс - хранилие данных (при использовании Spring Data)
// JpaRepository принимает два класса: сущность, с которой MarriageDao будет работать (MarriageCertificate)
// и тип идентификатора, который используется в dao (Long)
public interface MarriageDao extends JpaRepository<MarriageCertificate, Long> {

    // Spring Data сгенерирует выдачу, по правилам именования метода,
    // номер содержит какую-то подстроку
    List<MarriageCertificate> findByNumber(String number);

    // findByNum объявлен как NamedQuery, обращение к запросу в другом месте
    // в аннотации @Param указывается имя параметра из именованного запроса
    List<MarriageCertificate> findByNum(@Param("number") String number);

    // у метода имеется только Query, необходимо написать запрос
    @Query("SELECT mc FROM MarriageCertificate mc WHERE mc.number = :number")
    List<MarriageCertificate> findSomething(@Param("number") String number);

//    private static final Logger LOGGER = LoggerFactory.getLogger(MarriageCertificate.class);
//
//    private EntityManager entityManager;
//    // пример инициализации какого-то поля
//    @Value("${test.value}") // установка значения поля, используя property файл
//    private String test;
//
//    public void setTest(String test) {
//        this.test = test;
//    }
//
//    public MarriageCertificate findMarriageCertificate(MarriageRequest request){
//        LOGGER.info("findMarriageCertificate called:{}", test);
//
//        return null;
//    }
}
<file_sep>package edu.javacourse.register;

import edu.javacourse.register.rest.MarriageController;
import edu.javacourse.register.view.MarriageRequest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Starter {
    public static void main(String[] args) {
        // создание контекста
        // интерфейс верхнего уровня ApplicationContext
        // принимает на вход список файлов с описанием контекста
        ApplicationContext context = new ClassPathXmlApplicationContext(
                new String[]{"springContext.xml"}
        );

//        // получение бина, с указанием конкретного класса
//        MarriageController controller = context.getBean(MarriageController.class);
////        MarriageController controller = context.getBean("controller", MarriageController.class);
//        // передача реквеста (пока пустой)
//        controller.findMarriageCertificate(new MarriageRequest());
    }
}
<file_sep>package edu.javacourse.register.config;

import edu.javacourse.register.dao.PersonDao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration // класс - источник определения бинов (аналог конфигурации в xml)
// необходимо прописать property файл, для его загрузки. Обычно в Configuration классе
@PropertySource(value = {"classpath:/register.properties"})
public class MarriageConfig {

    @Bean // метод создает, настраивает и инициализирует новый объект, управляемый Spring IoC контейнером
    public PersonDao buildPersonDao(){

        System.out.println("PersonDao is created");

        return new PersonDao();
    }
}
<file_sep>package edu.javacourse.register.dao;

// класс, для того, чтобы вытащить список персон

import edu.javacourse.register.domain.Person;

import javax.persistence.*;
import java.util.List;

public class PersonDao {

    // необходимо создать Entity Manager
    @PersistenceContext // автоматическое связывание менеджера сущностей с бином (прописано в springContext.xml)
    private EntityManager entityManager;

    // получение списка персон
    public List<Person> findPersons() {
        // будет возвращен список объектов класса Person (используется язык JPAQL/HQL)
        // named query (именованные запросы), экономия времени на компиляцию
        Query query = entityManager.createNamedQuery("Person.findPersons");
        return  query.getResultList();
    }

    // добавление персоны в БД
    public Long addPerson(Person person){

//        // получение транзакции
//        EntityTransaction tr = entityManager.getTransaction();
//        // начало транзакции
//        tr.begin();
//        try{

            // сохраняем персону в БД
            entityManager.persist(person);
            // запись сохраненных данных непосредственно в БД
            entityManager.flush();

//            // завершение транзакции
//            tr.commit();
//        } catch (Exception ex) {
//            // отмена транзакции
//            tr.rollback();
//            throw new RuntimeException(ex);
//        }

        // возвращается Id персоны
        return person.getPersonId();
    }

}
