Иванов Максим

Младший Java программист

Или рецепт по приготовлению своего салата «Простенький парсер»

Источник - http://memesmix.net/meme/95ipef
Источник - http://memesmix.net/meme/95ipef

Всем привет, данная статья является - маленьким туториалом, для примера были взяты XML данные с сайта Центр Банка.

В статье будут использованы - Spring Boot, PostgreSQL и Hibernate.

Ингредиенты:

  1. Создание Spring Boot проект, проще всего это сделать через Spring Initializr. (в качестве системы сборки будет использоваться Gradle).

  2. PostgreSQL (для комфортной работы, я использую - DBeaver).

  3. Postman - для отправки запросов на сервер.

Если возникнут сложности с воссозданием туториала

Прошу пишите в комментариях возникшие проблемы, на всякий случай - вот мой git и ТГ

Начинаем с чистки ингредиентов:

Первостепенно нужно настроить build.gradle со всеми зависимостями.

build.gradle
buildscript {
	repositories {
		mavenCentral()
	}
}

plugins {
	id 'org.springframework.boot' version '2.5.2'
	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
	id 'java'
}

group = 'com.parsing'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web:2.6.2'
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5'
	implementation 'org.postgresql:postgresql:42.3.1'
	implementation 'org.projectlombok:lombok:1.18.22'

	compileOnly 'org.projectlombok:lombok:1.18.22'
	annotationProcessor 'org.projectlombok:lombok:1.18.22'

	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
	useJUnitPlatform()
}

Теперь настройки application.properties

application.properties
# connected to JDBC
# setup spring.datasource
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/change-me
spring.datasource.username=change-me
spring.datasource.password=change-me
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.idle-timeout=60000
spring.datasource.hikari.maximum-pool-size=120

# setup hibernate
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.proc.param_null_passing=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL94Dialect

Хорошо, после настроек нашего проекта, давайте обговорим его структуру:

Структура проекта
Структура проекта

Пакеты:

  • controller - обрабатывает запрос пользователя;

  • model - описывает модель данных;

  • repository - логика работы с БД;

  • service - основная бизнес логика проекта.

Нарезаем овощи и смешиваем:

Перед описанием моделей, посмотрим на фрагмент данных:

<ValCurs Date="22.01.2022" name="Foreign Currency Market">
	<Valute ID="R01010">
		<NumCode>036</NumCode>
		<CharCode>AUD</CharCode>
		<Nominal>1</Nominal>
		<Name>Австралийский доллар</Name>
		<Value>55,1633</Value>
	</Valute>
	<Valute ID="R01020A">
		<NumCode>944</NumCode>
		<CharCode>AZN</CharCode>
		<Nominal>1</Nominal>
		<Name>Азербайджанский манат</Name>
		<Value>45,1385</Value>
	</Valute>
	<Valute ID="R01035">
		<NumCode>826</NumCode>
		<CharCode>GBP</CharCode>
		<Nominal>1</Nominal>
		<Name>Фунт стерлингов Соединенного королевства</Name>
		<Value>103,9997</Value>
	</Valute>
</ValCurs>

- Сначала опишем общую модель курса валют, так как по схеме XML видно, что у нас должен быть общий список элементов валют (ValCurs), внутри которого элементы (Valute)

CourseDto
@XmlRootElement(name = "ValCurs")
@XmlAccessorType(XmlAccessType.FIELD)
public class CourseDto implements Serializable {

    @XmlElement(name = "Valute")
    private List<CourseDtoOnce> valute;
    @XmlElement(name = "Date")
    private LocalDate date;

    public List<CourseDtoOnce> getValute() {
        return valute;
    }

    @Override
    public String toString() {
        return "CourseDto{" +
                "valute=" + valute +
                ", date=" + date +
                '}';
    }
}

- Теперь опишем модель единичных элементов списка валют.

CourseDtoOnce
@Entity
@XmlRootElement(name = "Valute")
@XmlAccessorType(XmlAccessType.FIELD)
public class CourseDtoOnce implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @XmlElement(name = "NumCode")
    private String numCode;

    @XmlElement(name = "CharCode")
    private String charCode;

    @XmlElement(name = "Nominal")
    private int nominal;

    @XmlElement(name = "Name")
    private String name;

    @XmlElement(name = "Value")
    @JsonIgnore
    @Transient
    private String _Value;

    private double value;

    public String get_Value() {
        return _Value;
    }

    public void setValue(double value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "\n" + name + " (" +
                "numCode = " + numCode + ", " +
                "charCode = " + charCode + ", " +
                "nominal = " + nominal + ", " +
                "value = " + value + ")";
    }
}

Теперь для работы с БД, напишем repository

- Создадим интерфейс, который наследует от JpaRepository методы, для работы с записями в БД.

CourseEntityRepository
public interface CourseEntityRepository extends JpaRepository<CourseDtoOnce, Long> {
}

Переходим к созданию бизнес логики приложения

- CourseClient - работа с внешним ресурсом, обработка и выдача результата.

CourseClient
@Component
public class CourseClient {
    public static final String URL = "https://cbr.ru/scripts/XML_daily.asp?date_req=23/01/2022.xml";

    final RestTemplate restTemplate = new RestTemplate();


    public List<CourseDtoOnce> getCourses() {
        CourseDto response = restTemplate.getForObject(URL, CourseDto.class);

        if (response != null) {
            response
                    .getValute()
                    .forEach(x -> {
                        x.setValue(Double.parseDouble(x.get_Value().replace(",", ".")));
                        System.out.println(x);
                    });

            return response.getValute();
        }

        return null;
    }
}

- CourseService - бизнес логика проекта.

CourseService
@Service
@RequiredArgsConstructor
public class CourseService {

    private final CourseEntityRepository courseEntityRepository;
    private final CourseClient courseClient;

    public List<CourseDtoOnce> findCourseInfo(){
        return courseEntityRepository.saveAll(courseClient.getCourses());
    }
}

Теперь создадим путь, для обращения к сервису из вне

- Пишем контроллер, который используется, для получения списка сохраненных в БД записей

CourseParsingController
@RestController
@RequiredArgsConstructor
public class CourseParsingController {

    private final CourseService courseService;

    /**
     * Возвращает список курсов валют
     *
     * @return список курсов валют
     */
    @GetMapping(value = "/getCourse")
    public String getListInformation() {
        return courseService.findCourseInfo().toString();
    }
}

В конце класс, который собственно и запускает все наше приложение

ParsingProjectApplication
@SpringBootApplication
public class ParsingProjectApplication {
	public static void main(String[] args) {
		SpringApplication.run(ParsingProjectApplication.class, args);
	}
}

Мы сделали салат, теперь заправляем его

- Запускаем сервис:

Логи запуска сервиса
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.5.2)

2022-01-24 04:46:48.318  INFO 42654 --- [           main] com.ParsingProjectApplication            : No active profile set, falling back to default profiles: default
2022-01-24 04:46:49.028  INFO 42654 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2022-01-24 04:46:49.174  INFO 42654 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 142 ms. Found 1 JPA repository interfaces.
2022-01-24 04:46:49.455  INFO 42654 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-01-24 04:46:49.460  INFO 42654 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-01-24 04:46:49.460  INFO 42654 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.48]
2022-01-24 04:46:49.514  INFO 42654 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-01-24 04:46:49.514  INFO 42654 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1158 ms
2022-01-24 04:46:49.677  INFO 42654 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2022-01-24 04:46:49.696  INFO 42654 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.4.32.Final
2022-01-24 04:46:49.746  INFO 42654 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
2022-01-24 04:46:49.790  WARN 42654 --- [           main] com.zaxxer.hikari.HikariConfig           : HikariPool-1 - idleTimeout has been set but has no effect because the pool is operating as a fixed size pool.
2022-01-24 04:46:49.790  INFO 42654 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2022-01-24 04:46:49.951  INFO 42654 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2022-01-24 04:46:49.960  INFO 42654 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.PostgreSQL94Dialect
Hibernate: 
    
    drop table if exists course_dto_once cascade
2022-01-24 04:46:50.236  WARN 42654 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Warning Code: 0, SQLState: 00000
2022-01-24 04:46:50.236  WARN 42654 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : table "course_dto_once" does not exist, skipping
Hibernate: 
    
    drop sequence if exists hibernate_sequence
2022-01-24 04:46:50.237  WARN 42654 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Warning Code: 0, SQLState: 00000
2022-01-24 04:46:50.237  WARN 42654 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : sequence "hibernate_sequence" does not exist, skipping
Hibernate: create sequence hibernate_sequence start 1 increment 1
Hibernate: 
    
    create table course_dto_once (
       id int8 not null,
        char_code varchar(255),
        name varchar(255),
        nominal int4 not null,
        num_code varchar(255),
        value float8 not null,
        primary key (id)
    )
2022-01-24 04:46:50.318  INFO 42654 --- [           main] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2022-01-24 04:46:50.322  INFO 42654 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2022-01-24 04:46:50.480  WARN 42654 --- [           main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2022-01-24 04:46:50.661  INFO 42654 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-01-24 04:46:50.668  INFO 42654 --- [           main] com.ParsingProjectApplication            : Started ParsingProjectApplication in 2.682 seconds (JVM running for 3.006)

- Запускаем DBeaver, после запуска приложения, создастся таблица с полями:

Автоматически создаваемая таблица
Автоматически создаваемая таблица

- Запускаем Postman, прописываем в поле для url - http://localhost:8080/getCourse:

GETзапрос на url - http://localhost:8080/getCourse
GETзапрос на url - http://localhost:8080/getCourse

- Нажимаем синию кнопку "Send" и получаем в ответ данные о курсе валют, на 23/01/2022:

Курс валют на 23/01/2022
Курс валют на 23/01/2022

- Так же курсами валют заполнилась и БД:

Заполненная курсами валют БД
Заполненная курсами валют БД
Логи сервиса, после отправки запроса
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.5.2)

2022-01-24 04:46:48.318  INFO 42654 --- [           main] com.ParsingProjectApplication            : No active profile set, falling back to default profiles: default
2022-01-24 04:46:49.028  INFO 42654 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2022-01-24 04:46:49.174  INFO 42654 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 142 ms. Found 1 JPA repository interfaces.
2022-01-24 04:46:49.455  INFO 42654 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-01-24 04:46:49.460  INFO 42654 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-01-24 04:46:49.460  INFO 42654 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.48]
2022-01-24 04:46:49.514  INFO 42654 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-01-24 04:46:49.514  INFO 42654 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1158 ms
2022-01-24 04:46:49.677  INFO 42654 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2022-01-24 04:46:49.696  INFO 42654 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.4.32.Final
2022-01-24 04:46:49.746  INFO 42654 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
2022-01-24 04:46:49.790  WARN 42654 --- [           main] com.zaxxer.hikari.HikariConfig           : HikariPool-1 - idleTimeout has been set but has no effect because the pool is operating as a fixed size pool.
2022-01-24 04:46:49.790  INFO 42654 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2022-01-24 04:46:49.951  INFO 42654 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2022-01-24 04:46:49.960  INFO 42654 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.PostgreSQL94Dialect
Hibernate: 
    
    drop table if exists course_dto_once cascade
2022-01-24 04:46:50.236  WARN 42654 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Warning Code: 0, SQLState: 00000
2022-01-24 04:46:50.236  WARN 42654 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : table "course_dto_once" does not exist, skipping
Hibernate: 
    
    drop sequence if exists hibernate_sequence
2022-01-24 04:46:50.237  WARN 42654 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Warning Code: 0, SQLState: 00000
2022-01-24 04:46:50.237  WARN 42654 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : sequence "hibernate_sequence" does not exist, skipping
Hibernate: create sequence hibernate_sequence start 1 increment 1
Hibernate: 
    
    create table course_dto_once (
       id int8 not null,
        char_code varchar(255),
        name varchar(255),
        nominal int4 not null,
        num_code varchar(255),
        value float8 not null,
        primary key (id)
    )
2022-01-24 04:46:50.318  INFO 42654 --- [           main] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2022-01-24 04:46:50.322  INFO 42654 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2022-01-24 04:46:50.480  WARN 42654 --- [           main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2022-01-24 04:46:50.661  INFO 42654 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-01-24 04:46:50.668  INFO 42654 --- [           main] com.ParsingProjectApplication            : Started ParsingProjectApplication in 2.682 seconds (JVM running for 3.006)
2022-01-24 04:52:00.787  INFO 42654 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-01-24 04:52:00.788  INFO 42654 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2022-01-24 04:52:00.788  INFO 42654 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 0 ms

Австралийский доллар (numCode = 036, charCode = AUD, nominal = 1, value = 55.1633)

Азербайджанский манат (numCode = 944, charCode = AZN, nominal = 1, value = 45.1385)

Фунт стерлингов Соединенного королевства (numCode = 826, charCode = GBP, nominal = 1, value = 103.9997)

Армянских драмов (numCode = 051, charCode = AMD, nominal = 100, value = 15.9539)

Белорусский рубль (numCode = 933, charCode = BYN, nominal = 1, value = 29.8058)

Болгарский лев (numCode = 975, charCode = BGN, nominal = 1, value = 44.4607)

Бразильский реал (numCode = 986, charCode = BRL, nominal = 1, value = 14.1505)

Венгерских форинтов (numCode = 348, charCode = HUF, nominal = 100, value = 24.35)

Гонконгских долларов (numCode = 344, charCode = HKD, nominal = 10, value = 98.4699)

Датская крона (numCode = 208, charCode = DKK, nominal = 1, value = 11.6842)

Доллар США (numCode = 840, charCode = USD, nominal = 1, value = 76.6903)

Евро (numCode = 978, charCode = EUR, nominal = 1, value = 86.9054)

Индийских рупий (numCode = 356, charCode = INR, nominal = 10, value = 10.2985)

Казахстанских тенге (numCode = 398, charCode = KZT, nominal = 100, value = 17.5815)

Канадский доллар (numCode = 124, charCode = CAD, nominal = 1, value = 61.2102)

Киргизских сомов (numCode = 417, charCode = KGS, nominal = 100, value = 90.427)

Китайский юань (numCode = 156, charCode = CNY, nominal = 1, value = 12.0972)

Молдавских леев (numCode = 498, charCode = MDL, nominal = 10, value = 42.4055)

Норвежских крон (numCode = 578, charCode = NOK, nominal = 10, value = 86.796)

Польский злотый (numCode = 985, charCode = PLN, nominal = 1, value = 19.2264)

Румынский лей (numCode = 946, charCode = RON, nominal = 1, value = 17.5847)

СДР (специальные права заимствования) (numCode = 960, charCode = XDR, nominal = 1, value = 107.5497)

Сингапурский доллар (numCode = 702, charCode = SGD, nominal = 1, value = 56.9722)

Таджикских сомони (numCode = 972, charCode = TJS, nominal = 10, value = 67.8976)

Турецких лир (numCode = 949, charCode = TRY, nominal = 10, value = 57.1544)

Новый туркменский манат (numCode = 934, charCode = TMT, nominal = 1, value = 21.9429)

Узбекских сумов (numCode = 860, charCode = UZS, nominal = 10000, value = 70.7797)

Украинских гривен (numCode = 980, charCode = UAH, nominal = 10, value = 27.0692)

Чешских крон (numCode = 203, charCode = CZK, nominal = 10, value = 35.819)

Шведских крон (numCode = 752, charCode = SEK, nominal = 10, value = 83.537)

Швейцарский франк (numCode = 756, charCode = CHF, nominal = 1, value = 83.8787)

Южноафриканских рэндов (numCode = 710, charCode = ZAR, nominal = 10, value = 50.6156)

Вон Республики Корея (numCode = 410, charCode = KRW, nominal = 1000, value = 64.3418)

Японских иен (numCode = 392, charCode = JPY, nominal = 100, value = 67.3165)
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    select
        nextval ('hibernate_sequence')
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        course_dto_once
        (char_code, name, nominal, num_code, value, id) 
    values
        (?, ?, ?, ?, ?, ?)

Вот и все, надеюсь, что у всех получилось повторить туториал с первого
раза, в будущем будет еще много интересного, всем спасибо.

Комментарии (5)


  1. cry_san
    21.03.2022 03:09
    +7

    Стрельба из пушки по воробьям.

    Зачем для простейшей задачи были использованы Spring Boot, PostgreSQL и Hibernate ?

    Использование базы еще можно было бы оправдать, если бы в ней хранились исторические данные.

    В итоге "тонны" кода, вместо пары десятков строк.


  1. mmMike
    21.03.2022 05:39
    +4

    Какой кошмар. Пишете dto руками при наличии xsd (http://www.cbr.ru/development/sxml/).

    Ну а про использование такого набора для такой примитивной задачи уже написали.

    По моему это образец "как не надо делать". Разве что если Вам платят за количество строк исходного кода, а не за результат.


  1. panzerfaust
    21.03.2022 07:25
    +4

    Вы написали не парсер, а шаблонный микросервис по туториалам из гугла. Потом вы приходите на собес и говорите "посмотрите на мой пет-проект". Но это не пет-проект, а шаблонный микросервис по туториалам из гугла. Не делайте так.

    Называть это парсером - значит просто вводить в заблуждение. Парсер есть просто набор формальных правил. Ему ни БД ни IoC контейнер не нужны. Это просто чистая функция, которая гоняет один набор данных в другой. На 100% поддается юнит-тестированию. В вашем же сервисе о юнит-тестировании и речи не идет.


  1. denaie
    21.03.2022 09:55

    а разве это парсинг?, не ну просто открыть источник данных xml навряд-ли парсингом можно назвать, и да как сказано выше это забивание микроскопа гвоздями какое то

    Вот если бы все тоже самое но например на Camel, то было более полезно, я вот недавно искал хоть какой-нибудь внятный рабочий пример, примерно такой же. Перелопатил кучу инфы и все равно этой инфы очень мало. И как раз Camel заточен под вот такое перекладывание из одного в другое. Думаю в строчек 10 кода можно было уложиться правда под капотом было бы не меньше чем используемый тут спринг наверное:)


  1. MentalBlood
    21.03.2022 10:14
    +2

    Ентерпрайзненько