Java >> Java Tutorial >  >> Tag >> Spring

Spring Batch Tutorial:Schreiben von Informationen in eine Datenbank mit JDBC

Mein Spring Batch-Tutorial hat uns beigebracht, die Eingabedaten unseres Batch-Jobs aus verschiedenen Datenquellen zu lesen. Unsere Batch-Jobs sind jedoch nicht sehr nützlich, da wir nicht wissen, wie wir die Daten speichern können, die aus diesen Datenquellen gelesen werden.

Es ist an der Zeit, den nächsten Schritt zu tun und zu erfahren, wie wir die Daten speichern können, die von unserem Spring Batch-Job verarbeitet wurden. Dieser Blogbeitrag hilft uns, die verarbeiteten Daten mithilfe von JDBC in eine Datenbank zu schreiben.

Beginnen wir mit einem kurzen Blick auf unsere Beispielanwendung.

Einführung in unsere Beispielanwendung

Während dieses Tutorials werden wir mehrere Spring Batch-Jobs implementieren, die die Studenteninformationen eines Online-Kurses verarbeiten. Die Informationen eines einzelnen Schülers bestehen aus den folgenden Informationen:

  • Der Name des Schülers.
  • Die E-Mail-Adresse des Kursteilnehmers.
  • Der Name des gekauften Pakets.

Bevor wir diese Informationen in eine Datenbank schreiben können, müssen wir die Eingabedaten für die Komponente bereitstellen, die sie in eine Datenbank schreibt. In diesem Fall werden diese Informationen mithilfe von StudentDTO bereitgestellt Objekte.

Das StudentDTO Klasse enthält die Informationen eines einzelnen Schülers und ihr Quellcode sieht wie folgt aus:

public class StudentDTO {

    private String emailAddress;
    private String name;
    private String purchasedPackage;

    public StudentDTO() {}

    public String getEmailAddress() {
        return emailAddress;
    }

    public String getName() {
        return name;
    }

    public String getPurchasedPackage() {
        return purchasedPackage;
    }

    public void setEmailAddress(String emailAddress) {
        this.emailAddress = emailAddress;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setPurchasedPackage(String purchasedPackage) {
        this.purchasedPackage = purchasedPackage;
    }
}

Lassen Sie uns weitermachen und herausfinden, wie wir den Anwendungskontext unserer Anwendung konfigurieren können.

Konfigurieren des Anwendungskontextes unserer Anwendung

Bevor wir den ItemWriter konfigurieren können Objekt, das Schülerinformationen in die Datenbank schreibt, müssen wir das NamedParameterJdbcTemplate konfigurieren Bohne. Wir können dies tun, indem wir zwischen diesen beiden Optionen wählen:

Zuerst , wenn wir Spring Framework verwenden, müssen wir diesen Schritten folgen:

  1. Fügen Sie ein jdbcTemplate() hinzu -Methode in die Anwendungskontext-Konfigurationsklasse.
  2. Stellen Sie sicher, dass die jdbcTemplate() -Methode gibt ein NamedParameterJdbcTemplate zurück Objekt und nimmt eine DataSource Objekt als Methodenparameter.
  3. Kommentieren Sie die Methode mit @Bean Anmerkung.
  4. Implementieren Sie die Methode, indem Sie ein neues NamedParameterJdbcTemplate zurückgeben Objekt.

Der relevante Teil unserer Anwendungskontext-Konfigurationsklasse sieht wie folgt aus:

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import javax.sql.DataSource;
import java.util.Properties;

@Configuration
public class PersistenceContext {

    @Bean(destroyMethod = "close")
    DataSource dataSource(Environment env) {
        HikariConfig dataSourceConfig = new HikariConfig();

        dataSourceConfig.setDriverClassName(env.getRequiredProperty("db.driver"));
        dataSourceConfig.setJdbcUrl(env.getRequiredProperty("db.url"));
        dataSourceConfig.setUsername(env.getRequiredProperty("db.username"));
        dataSourceConfig.setPassword(env.getRequiredProperty("db.password"));

        return new HikariDataSource(dataSourceConfig);
    }
	
    @Bean
    NamedParameterJdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new NamedParameterJdbcTemplate(dataSource);
    }
}

Zweiter , wenn wir Spring Boot verwenden und die automatische Konfigurationsfunktion nicht deaktiviert haben, müssen wir keine Änderungen an unserer Konfiguration vornehmen, da Spring Boot sowohl das JdbcTemplate konfiguriert und NamedParameterJdbcTemplate Bohnen.

Fahren wir fort und konfigurieren den ItemWriter Bean, die die verarbeiteten Schülerinformationen in die Datenbank schreibt.

Schreiben von Informationen in eine Datenbank mit JDBC

Wir können den ItemWriter konfigurieren Bean, indem Sie diesen Schritten folgen:

Zuerst , müssen wir die Konfigurationsklasse erstellen, die die Beans enthält, die den Workflow unseres Spring Batch-Jobs beschreiben. Wir können dies tun, indem wir eine CsvFileToDatabaseJobConfig erstellen Klasse und kommentieren Sie sie mit @Configuration Anmerkung.

Der Quellcode der CsvFileToDatabaseJobConfig Klasse sieht wie folgt aus:

import org.springframework.context.annotation.Configuration;

@Configuration
public class CsvFileToDatabaseJobConfig {

}

Zweiter , müssen wir die Methode erstellen, die unseren ItemWriter konfiguriert Bohne. Wir können dies tun, indem wir diesen Schritten folgen:

  1. Fügen Sie eine neue Methode zu unserer Anwendungskontext-Konfigurationsklasse hinzu und stellen Sie sicher, dass die erstellte Methode ein ItemWriter zurückgibt Objekt.
  2. Stellen Sie sicher, dass die erstellte Methode die DataSource übernimmt und NamedParameterJdbcTemplate Objekte als Methodenparameter.
  3. Implementieren Sie die Methode, indem Sie null zurückgeben .

Nachdem wir der CsvFileToDatabaseJobConfig eine neue Methode hinzugefügt haben Klasse sieht der Quellcode wie folgt aus:

import org.springframework.batch.item.ItemWriter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import javax.sql.DataSource;

@Configuration
public class CsvFileToDatabaseJobConfig {
    
    @Bean
    ItemWriter<StudentDTO> csvFileDatabaseItemWriter(DataSource dataSource, 
													 NamedParameterJdbcTemplate jdbcTemplate) {
        return null;
    }
}

Dritter , müssen wir einen neuen JdbcBatchItemWriter erstellen Objekt, legen Sie die verwendete Datenquelle und das JDBC-Template fest und stellen Sie sicher, dass unsere Methode das erstellte Objekt zurückgibt.

Nachdem wir dies getan haben, ist der Quellcode der CsvFileToDatabaseJobConfig Klasse sieht wie folgt aus:

import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import javax.sql.DataSource;

@Configuration
public class CsvFileToDatabaseJobConfig {

    @Bean
    ItemWriter<StudentDTO> csvFileDatabaseItemWriter(DataSource dataSource, 
													 NamedParameterJdbcTemplate jdbcTemplate) {
        JdbcBatchItemWriter<StudentDTO> databaseItemWriter = new JdbcBatchItemWriter<>();
        databaseItemWriter.setDataSource(dataSource);
        databaseItemWriter.setJdbcTemplate(jdbcTemplate);
        
        return databaseItemWriter;
    }
}

Unser nächster Schritt ist die Konfiguration von INSERT Anweisung, die Studenteninformationen in unsere Datenbank einfügt. Wir können zwei verschiedene Strategien verwenden, um die Parameter unseres INSERT anzugeben -Anweisung, und beide Strategien erfordern eine etwas andere Konfiguration.

Beginnen wir mit der Erstellung eines INSERT Anweisung, die indizierte Parameter verwendet.

Indizierte Parameter verwenden

Wenn wir indizierte Parameter verwenden möchten, können wir das verwendete INSERT konfigurieren -Anweisung, indem Sie diesen Schritten folgen:

Zuerst , müssen wir ein INSERT erstellen -Anweisung, die Daten in die Studenten einfügt Tabelle und verwendet indizierte Parameter.

Nachdem wir ein konstantes Feld erstellt haben, das unser neues INSERT enthält -Anweisung und stellte sicher, dass der JdbcBatchItemWriter Objekt verwendet unser neues INSERT -Anweisung, der Quellcode der CsvFileToDatabaseJobConfig Klasse sieht wie folgt aus:

import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import javax.sql.DataSource;

@Configuration
public class CsvFileToDatabaseJobConfig {

    private static final String QUERY_INSERT_STUDENT = "INSERT " +
            "INTO students(email_address, name, purchased_package) " +
            "VALUES (?, ?, ?)";

    @Bean
    ItemWriter<StudentDTO> csvFileDatabaseItemWriter(DataSource dataSource,
                                                     NamedParameterJdbcTemplate jdbcTemplate) {
        JdbcBatchItemWriter<StudentDTO> databaseItemWriter = new JdbcBatchItemWriter<>();
        databaseItemWriter.setDataSource(dataSource);
        databaseItemWriter.setJdbcTemplate(jdbcTemplate);

        databaseItemWriter.setSql(QUERY_INSERT_STUDENT);

        return databaseItemWriter;
    }
}

Zweiter , müssen wir eine Klasse erstellen, die den ItemPreparedStatementSetter implementiert Schnittstelle. Diese Klasse ist dafür verantwortlich, die tatsächlichen Parameterwerte auf das PreparedStatement zu setzen Objekt, das als Methodenparameter angegeben wird, wenn setValues() -Methode des ItemPreparedStatementSetter Schnittstelle wird aufgerufen.

Wir können diese Klasse erstellen, indem wir diesen Schritten folgen:

  1. Erstellen Sie eine Klasse, die den ItemPreparedStatementSetter implementiert Schnittstelle. Wenn wir diese Schnittstelle implementieren, müssen wir einen Typparameter angeben, der den Typ des Elements angibt (StudentDTO ), die die eigentlichen Parameterwerte enthält.
  2. Implementieren Sie setValues() -Methode und konfigurieren Sie die Parameterwerte in dieser Reihenfolge:emailAddress , Name und gekauftes Paket .

Der Quellcode der erstellten Klasse sieht wie folgt aus:

import org.springframework.batch.item.database.ItemPreparedStatementSetter;

import java.sql.PreparedStatement;
import java.sql.SQLException;

final class StudentPreparedStatementSetter implements ItemPreparedStatementSetter<StudentDTO> {

    @Override
    public void setValues(StudentDTO student, 
						  PreparedStatement preparedStatement) throws SQLException {
        preparedStatement.setString(1, student.getEmailAddress());
        preparedStatement.setString(2, student.getName());
        preparedStatement.setString(3, student.getPurchasedPackage());
    }
}

Dritter , müssen wir sicherstellen, dass der JdbcBatchItemWriter verwendet den StudentPreparedStatementSetter Klasse, wenn sie die tatsächlichen Parameterwerte des aufgerufenen INSERT ermittelt Aussage.

Nachdem wir den verwendeten ItemPreparedStatementSetter konfiguriert haben Objekt, der Quellcode der CsvFileToDatabaseJobConfig Klasse sieht wie folgt aus:

import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.ItemPreparedStatementSetter;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import javax.sql.DataSource;

@Configuration
public class CsvFileToDatabaseJobConfig {

    private static final String QUERY_INSERT_STUDENT = "INSERT " +
            "INTO students(email_address, name, purchased_package) " +
            "VALUES (?, ?, ?)";

    @Bean
    ItemWriter<StudentDTO> csvFileDatabaseItemWriter(DataSource dataSource,
                                                     NamedParameterJdbcTemplate jdbcTemplate) {
        JdbcBatchItemWriter<StudentDTO> databaseItemWriter = new JdbcBatchItemWriter<>();
        databaseItemWriter.setDataSource(dataSource);
        databaseItemWriter.setJdbcTemplate(jdbcTemplate);

        databaseItemWriter.setSql(QUERY_INSERT_STUDENT);

        ItemPreparedStatementSetter<StudentDTO> valueSetter = 
                new StudentPreparedStatementSetter();
        databaseItemWriter.setItemPreparedStatementSetter(valueSetter);

        return databaseItemWriter;
    }
}

Wir haben jetzt einen ItemWriter konfiguriert Bean, das Informationen in unsere Datenbank einfügt, indem es ein INSERT verwendet -Anweisung, die indizierte Parameter verwendet.

Lassen Sie uns herausfinden, wie wir dasselbe Ergebnis mit INSERT erreichen können Anweisung, die benannte Parameter verwendet.

Verwenden von benannten Parametern

Wenn wir benannte Parameter verwenden möchten, können wir das verwendete INSERT konfigurieren -Anweisung, indem Sie diesen Schritten folgen:

Zuerst , müssen wir ein INSERT erstellen -Anweisung, die Daten in die Studenten einfügt Tabelle und verwendet benannte Parameter. Wenn wir die Namen unserer benannten Parameter angeben, sollten wir Parameternamen verwenden, die den Eigenschaftsnamen des StudentDTO entsprechen Klasse.

Nachdem wir ein konstantes Feld erstellt haben, das unser neues INSERT enthält -Anweisung und stellte sicher, dass der JdbcBatchItemWriter Objekt verwendet unser neues INSERT -Anweisung, der Quellcode der CsvFileToDatabaseJobConfig Klasse sieht wie folgt aus:

import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import javax.sql.DataSource;

@Configuration
public class CsvFileToDatabaseJobConfig {
    
    private static final String QUERY_INSERT_STUDENT = "INSERT " +
            "INTO students(email_address, name, purchased_package) " +
            "VALUES (:emailAddress, :name, :purchasedPackage)";
    
    @Bean
    ItemWriter<StudentDTO> csvFileDatabaseItemWriter(DataSource dataSource, 
                                                     NamedParameterJdbcTemplate jdbcTemplate) {
        JdbcBatchItemWriter<StudentDTO> databaseItemWriter = new JdbcBatchItemWriter<>();
        databaseItemWriter.setDataSource(dataSource);
        databaseItemWriter.setJdbcTemplate(jdbcTemplate);

        databaseItemWriter.setSql(QUERY_INSERT_STUDENT);

        return databaseItemWriter;
    }
}

Zweiter , müssen wir den verwendeten ItemSqlParameterSourceProvider konfigurieren Objekt. Der JdbcBatchItemWriter -Objekt verwendet dieses Objekt, um eine Referenz auf SqlParameterSource zu erhalten Objekt, das verwendet wird, um die Parameterwerte unserer benannten Parameter abzurufen.

Weil die Namen unserer benannten Parameter gleich den Eigenschaftsnamen des StudentDTO sind Klasse können wir den BeanPropertyItemSqlParameterSourceProvider verwenden Klasse dazu.

Nachdem wir den verwendeten ItemSqlParameterSourceProvider konfiguriert haben Objekt, der Quellcode der CsvFileToDatabaseJobConfig Klasse sieht wie folgt aus:

import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.ItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import javax.sql.DataSource;

@Configuration
public class CsvFileToDatabaseJobConfig {
    
    private static final String QUERY_INSERT_STUDENT = "INSERT " +
            "INTO students(email_address, name, purchased_package) " +
            "VALUES (:emailAddress, :name, :purchasedPackage)";
    
    @Bean
    ItemWriter<StudentDTO> csvFileDatabaseItemWriter(DataSource dataSource, 
                                                     NamedParameterJdbcTemplate jdbcTemplate) {
        JdbcBatchItemWriter<StudentDTO> databaseItemWriter = new JdbcBatchItemWriter<>();
        databaseItemWriter.setDataSource(dataSource);
        databaseItemWriter.setJdbcTemplate(jdbcTemplate);

        databaseItemWriter.setSql(QUERY_INSERT_STUDENT);

        ItemSqlParameterSourceProvider<StudentDTO> paramProvider = 
                new BeanPropertyItemSqlParameterSourceProvider<>();
        databaseItemWriter.setItemSqlParameterSourceProvider(paramProvider);

        return databaseItemWriter;
    }
}

Wir haben jetzt einen ItemWriter konfiguriert Bean, das Informationen in unsere Datenbank einfügt, indem es ein INSERT verwendet Anweisung, die benannte Parameter verwendet.

Fassen wir zusammen, was wir aus dieser Lektion gelernt haben.

Zusammenfassung

Dieser Blogbeitrag hat uns vier Dinge gelehrt:

  • Wir können Informationen in eine Datenbank schreiben, indem wir den JdbcBatchItemWriter verwenden Klasse.
  • Wenn wir indizierte Parameter verwenden möchten, können wir die tatsächlichen Parameterwerte für JdbcBatchItemWriter bereitstellen durch Implementieren eines ItemPreparedStatementSetter Schnittstelle.
  • Wenn wir benannte Parameter verwenden möchten, können wir die tatsächlichen Parameterwerte für JdbcBatchItemWriter bereitstellen durch Implementieren eines ItemSqlParameterSourceProvider Schnittstelle.
  • Wenn wir benannte Parameter verwenden und unsere Parameternamen den Eigenschaftsnamen der Klasse entsprechen, die die tatsächlichen Parameterwerte enthält, können wir die tatsächlichen Parameterwerte für JdbcBatchItemWriter bereitstellen mithilfe von BeanPropertyItemSqlParameterSourceProvider Klasse.

P.S. Sie können die Beispielanwendungen dieses Blogposts von Github abrufen:Spring example und Spring Boot example.


Java-Tag