[JAVA] Mettre à jour périodiquement la base de données avec Spring Batch et My Batis

J'ai écrit le code en utilisant Spring Batch, qui est l'une des fonctions Spring Framework populaires en Java, au travail, donc je vais l'implémenter à la maison pour l'introduction et la révision. Le code final peut être trouvé sur GitHub.

environnement

Quoi faire

Je ne peux pas mettre le code que j'ai écrit dans les affaires, alors je vais faire un substitut. J'ai décidé de faire un lot qui corrige les données d'âge d'une certaine table personnelle à l'âge correct en regardant la date de naissance.

Les données

Préparez d'abord les données. Démarrez CentOS 7 dans Vagrant et installez MySQL là-bas. Créez une base de données appelée batch et préparez le tableau suivant. Cette fois, ce serait bien si j'avais l'âge et la date de naissance, mais je suis seul avec ça, alors j'ai préparé un nom. À propos, le lot est censé être exécuté quotidiennement.

mysql> use batch;
Database changed
mysql> desc person;
+----------+-------------+------+-----+---------+----------------+
| Field    | Type        | Null | Key | Default | Extra          |
+----------+-------------+------+-----+---------+----------------+
| id       | int(11)     | NO   | PRI | NULL    | auto_increment |
| name     | varchar(30) | NO   |     | NULL    |                |
| age      | int(3)      | NO   |     | NULL    |                |
| birthday | date        | NO   |     | NULL    |                |
+----------+-------------+------+-----+---------+----------------+

Entrez les données pour environ 4 personnes. Aujourd'hui, c'est le 29 août, je vais donc entrer les données d'anniversaire qui ne sont différentes que dans le calendrier occidental. Je préparerai un cas le jour de l'anniversaire d'un autre jour afin de voir s'il a été mis à jour en plus.

mysql> select * from person;
+----+-------+-----+------------+
| id | name  | age | birthday   |
+----+-------+-----+------------+
|  1 | Alice |  23 | 1995-08-29 |
|  2 | Bob   |  38 | 1980-08-29 |
|  3 | Carol |  29 | 1989-08-29 |
|  4 | Dave  |  23 | 1995-08-30 |
+----+-------+-----+------------+

Composant Java

Lorsque vous utilisez Spring Framework, il est plus rapide de télécharger le modèle à partir de Spring Initializr, utilisez donc ceci. Puisque Gradle est utilisé pour la construction, sélectionnez Projet Gradle et entrez-le de manière appropriée. image.png Dépendances

Sélectionnez la zone de manière appropriée, téléchargez-la avec "Générer le projet" et décompressez-la. Nous y ajouterons les fichiers nécessaires. L'architecture de Spring Batch est décrite en détail dans ici, donc je pense que vous devriez le lire. ..

Dans SpringBatch, l'unité d'exécution du lot est définie comme JOB et l'unité de traitement est définie comme STEP. En outre, deux concepts, ** modèle de tasklet ** et ** modèle de bloc **, sont fournis comme modèles pour le flux de traitement STEP. À l'origine, je pense que les tasklets sont suffisantes si vous n'avez besoin de vous référer et de mettre à jour qu'une seule table, mais cette fois nous oserons adopter et implémenter un modèle chunk.

Le modèle de bloc doit être implémenté en le divisant en trois flux "lecture-> traitement-> écriture", et des interfaces sont préparées pour chacun.

interface Détails d'implémentation
ItemReader Extraire les données personnelles du DB ayant la même date de naissance que la date d'exécution.
ItemProcessor Calculez l'âge à partir de la date de naissance et créez des données personnelles avec l'âge mis à jour.
ItemWriter Écrivez les données personnelles créées dans le DB.

Lire et écrire des données

Pour lire et écrire des données, connectez-vous au DB. La classe d'implémentation de chaque interface est fournie par la bibliothèque MyBatis, nous allons donc l'utiliser. Read (ItemReader) extrait les enregistrements personnels dont l'anniversaire est le même que la date d'exécution du lot. Je vais donc émettre le SQL suivant. La date du jour (aujourd'hui) sera transmise depuis l'application.

python


SELECT
    id,
    name,
    age,
    birthday
FROM
    person
WHERE
    Date_format(birthday, '%m%d') = Date_format(#{today}, '%m%d')

L'écriture (ItemWriter) ne met à jour que l'âge.

python


update
    person
set
    age = #{age}
where
    id = #{id}

Traitement de l'information

Dans le traitement des données (ItemProcessor), il est de la responsabilité de corriger correctement l'âge de l'objet de données personnelles extrait. Cela dit, il ne vous reste plus qu'à calculer la différence entre cette année et l'année de naissance et à créer un objet de mise à jour.

CorrectAgeProcessor.java


//importation omise
@Component
@Slf4j
public class CorrectAgeProcessor implements ItemProcessor<Person, Person> {
    @Override
    public Person process(Person person) throws Exception {
        log.info("Correct {}.", person.getName());
        return new Person(
                person.getId(),
                person.getName(),
                LocalDate.now().getYear() - person.getBirthday().getYear(),
                person.getBirthday());
    }
}

Définition de la configuration du travail

Définissez la configuration du travail. Cette fois, une étape suffit, alors préparez un haricot appelé étape. Spring Batch semble effectuer le traitement des transactions par défaut et s'engage à l'intervalle de nombre défini par chunk (n). Le but est de réduire les frais généraux au moment de l'engagement en s'engageant dans une certaine mesure ensemble. Cette fois, je vais m'engager un par un pour le moment.

BatchConfiguration.java


//importation omise
@Configuration
@EnableBatchProcessing
@RequiredArgsConstructor
public class BatchConfiguration {

    public final JobBuilderFactory jobBuilderFactory;

    public final StepBuilderFactory stepBuilderFactory;

    private final SqlSessionFactory sqlSessionFactory;

    private final CorrectAgeProcessor correctAgeProcessor;

    @Bean
    public MyBatisCursorItemReader<Person> reader() {
        Map<String, Object> params = new HashMap<>();
        params.put("today", LocalDate.now());
        return new MyBatisCursorItemReaderBuilder<Person>()
                .sqlSessionFactory(sqlSessionFactory)
                .queryId("com.github.hysrabbit.agecorrector.mybatis.mapper.PersonMapper.findByBirthday")
                .parameterValues(params)
                .build();
    }

    @Bean
    public MyBatisBatchItemWriter<Person> writer() {
        return new MyBatisBatchItemWriterBuilder<Person>()
                .sqlSessionFactory(sqlSessionFactory)
                .statementId("com.github.hysrabbit.agecorrector.mybatis.mapper.PersonMapper.save")
                .build();
    }

    @Bean
    public Job correctAge(JobListener jobListener, Step step) {
        return jobBuilderFactory.get("correctAge")
                .incrementer(new RunIdIncrementer())
                .listener(jobListener)
                .flow(step)
                .end()
                .build();
    }

    @Bean
    public Step step(ItemReader<Person> reader, ItemWriter<Person> writer) {
        return stepBuilderFactory.get("step")
                .<Person, Person> chunk(1)
                .reader(reader)
                .processor(correctAgeProcessor)
                .writer(writer)
                .build();
    }

}

J'ai implémenté tout le reste et j'ai poussé le code final sur ici. Je n'ai pas implémenté le code de test, je vais donc essayer de l'implémenter bientôt.

L'exécution est effectuée sur la VM sur laquelle MySQL est installé. Avant l'exécution, définissez les informations de paramétrage DB dans la variable d'environnement.

$ export SPRING_DATASOURCE_URL=jdbc:mysql://<hostname>:<port>/<database>;
$ export SPRING_DATASOURCE_USERNAME=<username>;
$ export SPRING_DATASOURCE_PASSWORD=<password>;

Puis compilez avec Gradle et exécutez le fichier Jar résultant. Le nom de la personne qui l'a mis à jour est affiché dans l'enregistreur inséré.

$ ./gradlew clean build
.
.
.
$ java -jar build/libs/agecorrector.jar

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.7.RELEASE)
.
.
.
2019-08-29 01:50:29.334  INFO 2781 --- [           main] c.g.h.agecorrector.batch.JobListener     : Start job.
2019-08-29 01:50:29.391  INFO 2781 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [step]
2019-08-29 01:50:29.565  INFO 2781 --- [           main] c.g.h.a.batch.CorrectAgeProcessor        : Correct Alice.
2019-08-29 01:50:29.609  INFO 2781 --- [           main] c.g.h.a.batch.CorrectAgeProcessor        : Correct Bob.
2019-08-29 01:50:29.624  INFO 2781 --- [           main] c.g.h.a.batch.CorrectAgeProcessor        : Correct Carol.
2019-08-29 01:50:29.651  INFO 2781 --- [           main] c.g.h.agecorrector.batch.JobListener     : Completed job.
.
.
.

Vérifions également les données dans MySQL. Le jour où je l'ai diffusé, c'était le «8/29», mais vous pouvez mettre à jour l'âge de la personne née ce jour-là.

mysql> select * from person;
+----+-------+-----+------------+
| id | name  | age | birthday   |
+----+-------+-----+------------+
|  1 | Alice |  24 | 1995-08-29 |
|  2 | Bob   |  39 | 1980-08-29 |
|  3 | Carol |  30 | 1989-08-29 |
|  4 | Dave  |  23 | 1995-08-30 |
+----+-------+-----+------------+

Résumé

Après cela, si vous vous inscrivez auprès de Cron, etc., vous pouvez mettre à jour votre âge régulièrement. Je pense que la combinaison de Spring Batch et My Batis est un framework facile à comprendre et facile à utiliser pour les programmeurs Java. De plus, il existe de nombreuses fonctions utiles qui ne sont pas implémentées cette fois dans Spring Batch, veuillez donc les utiliser par tous les moyens.

référence

Recommended Posts

Mettre à jour périodiquement la base de données avec Spring Batch et My Batis
Compatibilité de Spring JDBC et My Batis avec Spring Data JDBC (provisoire)
Spring avec Kotorin --2 RestController et Data Class
Créez un lot à la demande simple avec Spring Batch
Authentification DB avec Spring Security et hachage avec BCrypt
HTTPS avec Spring Boot et Let's Encrypt
Méthode d'implémentation pour source multi-données avec Spring boot (Mybatis et Spring Data JPA)
Exemple de traitement par lots de données sur DB avec des démarreurs Apache Camel Spring Boot
Juste des images d'entrée et de sortie avec Spring MVC
Spring Batch 4.1.x - Documentation de référence Lecture et traduction
Comment utiliser MyBatis2 (iBatis) avec Spring Boot 1.4 (Spring 4)
[Débutant] Téléchargez des images et des fichiers avec Spring [Autosuffisant]
Créez une application CRUD avec Spring Boot 2 + Thymeleaf + MyBatis
[JAVA] [Spring] [MyBatis] Utiliser IN () avec SQL Builder
Vous pouvez éliminer @Param avec Kotlin 1.1 et MyBatis 3.4.1+! !!
Essayez d'utiliser un conteneur DI avec Laravel et Spring Boot
Changer d'environnement avec Spring Boot application.properties et l'annotation @Profile
Mémo d'utilisation de Spring Security: coopération avec Spring MVC et Boot
Spring Boot avec les paramètres du filtre de sécurité Spring et les points addictifs
Tentative de SSR Vue.js avec Spring Boot et GraalJS
[Spring Batch] Vérification de la mise en œuvre de l'étape de bloc et de l'étape de tâche de Spring Batch
Contrôlez le flux de traitement Spring Batch avec JavaConfig.
Connectez Spring Boot et Angular en toute sécurité avec OpenAPI Generator