[JAVA] Ich habe versucht, mit Spring Data JPA zu beginnen

Am Anfang

Ich hatte noch nie einen anderen OP-Mapper als Doma berührt, also dachte ich plötzlich darüber nach und berührte ihn mit halbem Interesse.

Installation in einer Spring Boot-Anwendung - Ich möchte über den Vergleich mit Doma schreiben, den ich durch das Erstellen einer einfachen API empfand.

Umgebung

Annahme

Ich möchte eine einfache API erstellen und sie auf verschiedene Arten berühren. Die zu erstellende API lautet wie folgt.

Endpunkt Http Method Überblick Bemerkungen
/api/employee/{employeeId} GET Abrufen von Mitarbeiterinformationen, die mit der Mitarbeiter-ID übereinstimmen.
/api/employee GET Mitarbeiterinformationen abrufen. Wir werden auch nach Suchbedingungen eingrenzen.
/api/employee POST Registrieren Sie Mitarbeiterinformationen.
/api/employee/{employeeId} PUT Aktualisieren Sie die Mitarbeiterinformationen.
/api/employee/{employeeId} DELETE Mitarbeiterinformationen löschen.

API-Erstellung

(Vorerst) Erstellen einer Vorlage für die Anwendung

Erstellen Sie eine Vorlage für Ihre Anwendung mit dem VSCode-Plug-In Spring Initializer Java Support.

Dieses Plugin selbst ist im Spring Boot Extension Pack enthalten, also im [Spring Boot Extension Pack]( Es reicht aus, https://marketplace.visualstudio.com/items?itemName=Pivotal.vscode-boot-dev-pack) installiert zu haben.

Erstellen Sie interaktiv eine Vorlage. Wählen Sie in der Befehlspalette "Spring Initializr: Generate a Gradle Project" aus.

create-application-01.png

Wählen Sie Java.

create-application-02.png

Geben Sie den Paketnamen ein. Lassen Sie es diesmal standardmäßig als "com.example".

create-application-03.png

Geben Sie den Projektnamen ein. Bitte geben Sie uns Ihren Lieblingsnamen. (Ich habe Employee-API verwendet.)

create-application-04.png

Wählen Sie die Version von Spring Boot. (Wählen Sie 2.3.1)

create-application-05.png

Wählen Sie eine abhängige Bibliothek aus. Ich habe die folgende Bibliothek ausgewählt, weil ich nur eine einfache API erstellen wollte.

Spring Boot DevTools / Lombok / Spring Web / Spring Data JPA / PostgreSQL Driver

create-application-06.png

Definieren Sie die Verbindungsinformationen in application.properties

spring.jpa.database=postgresql
spring.datasource.platform=postgres
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/sample
spring.datasource.username=postgres
spring.datasource.password=postgres

Definieren Sie die Entitätsklasse

Insert_date und update_date sind als allgemeine Elemente in der Tabelle definiert.

CommonEntity.java


/**
 *Eine Klasse, die allgemeine Elemente in einer Tabelle definiert.</br>
 *Alle Entitätsklassen werden durch Erben dieser Klasse erstellt.
 */
@MappedSuperclass
@Getter
@Setter
public class CommonEntity {

  /**Datum und Uhrzeit der Datenregistrierung*/
  @Column(name = "insert_date")
  @Temporal(TemporalType.DATE)
  private Date insertdate;

  /**Datum und Uhrzeit der Datenaktualisierung*/
  @Column(name = "update_date")
  @Temporal(TemporalType.DATE)
  private Date updateDate;

  /**
   *Häufig ausgeführte Methode vor der Datenregistrierung
   */
  @PrePersist
  public void preInsert() {
    Date date = new Date();
    setInsertdate(date);
    setUpdateDate(date);
  }

  /**
   *Häufig ausgeführte Methoden vor dem Aktualisieren von Daten
   */
  @PreUpdate
  public void preUpdate() {
    setUpdateDate(new Date());
  }

}

Erben Sie "CommonEntity", das allgemeine Tabellenelemente definiert und eine Entitätsklasse für den geschäftlichen Gebrauch erstellt.

EmployeeEntity.java


@Entity
@Table(name = "employee")
@Getter
@Setter
public class EmployeeEntity extends CommonEntity {

  /**Mitarbeiter-ID*/
  @Id
  @Column(name = "id")
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Integer employeeId;
  
  /**Mitarbeitername*/
  @Column(name = "name")
  private String employeeName;

  /**Alter*/
  @Column(name = "age")
  private Integer age;

  /**Positions-ID*/
  @Column(name = "position_id")
  private String positionId;

  /**Abteilungs-ID*/
  @Column(name = "department_id")
  private String departmentId;

}

Definieren Sie die Repository-Schnittstelle

Definiert eine Schnittstelle, die "org.springframework.data.jpa.repository.JpaRepository" erbt.

EmployeeRepository.java


package com.example.employeeapi.employee;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface EmployeeRepository extends JpaRepository<EmployeeEntity, Integer> {

}

(Referenz) JpaRepository

Es gibt Methoden, die grundlegende CRUD-Operationen verarbeiten können. In der Schnittstelle, die diese Schnittstelle erbt (in diesem Beispiel "EmployeeRepository"), können Sie Ihre eigene Methode definieren, wenn die im Voraus in den Geschäftsspezifikationen usw. vorbereitete Methode nicht ausreicht. (Beitreten, um Aufzeichnungen usw. zu erhalten)

JpaRepository.java


/*
 * Copyright 2008-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.data.jpa.repository;

import java.util.List;

import javax.persistence.EntityManager;

import org.springframework.data.domain.Example;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.QueryByExampleExecutor;

/**
 * JPA specific extension of {@link org.springframework.data.repository.Repository}.
 *
 * @author Oliver Gierke
 * @author Christoph Strobl
 * @author Mark Paluch
 */
@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.CrudRepository#findAll()
	 */
	@Override
	List<T> findAll();

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.PagingAndSortingRepository#findAll(org.springframework.data.domain.Sort)
	 */
	@Override
	List<T> findAll(Sort sort);

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.CrudRepository#findAll(java.lang.Iterable)
	 */
	@Override
	List<T> findAllById(Iterable<ID> ids);

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.CrudRepository#save(java.lang.Iterable)
	 */
	@Override
	<S extends T> List<S> saveAll(Iterable<S> entities);

	/**
	 * Flushes all pending changes to the database.
	 */
	void flush();

	/**
	 * Saves an entity and flushes changes instantly.
	 *
	 * @param entity
	 * @return the saved entity
	 */
	<S extends T> S saveAndFlush(S entity);

	/**
	 * Deletes the given entities in a batch which means it will create a single {@link Query}. Assume that we will clear
	 * the {@link javax.persistence.EntityManager} after the call.
	 *
	 * @param entities
	 */
	void deleteInBatch(Iterable<T> entities);

	/**
	 * Deletes all entities in a batch call.
	 */
	void deleteAllInBatch();

	/**
	 * Returns a reference to the entity with the given identifier. Depending on how the JPA persistence provider is
	 * implemented this is very likely to always return an instance and throw an
	 * {@link javax.persistence.EntityNotFoundException} on first access. Some of them will reject invalid identifiers
	 * immediately.
	 *
	 * @param id must not be {@literal null}.
	 * @return a reference to the entity with the given identifier.
	 * @see EntityManager#getReference(Class, Object) for details on when an exception is thrown.
	 */
	T getOne(ID id);

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.query.QueryByExampleExecutor#findAll(org.springframework.data.domain.Example)
	 */
	@Override
	<S extends T> List<S> findAll(Example<S> example);

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.query.QueryByExampleExecutor#findAll(org.springframework.data.domain.Example, org.springframework.data.domain.Sort)
	 */
	@Override
	<S extends T> List<S> findAll(Example<S> example, Sort sort);
}

Service definieren, Controller-Klasse

Definieren Sie eine Service-Klasse, die das zuvor definierte "EmployeeRepository" verwendet, und eine Controller-Klasse, die es aufruft.

EmployeeService.java


package com.example.employeeapi.employee;

import java.util.ArrayList;
import java.util.List;

import javax.transaction.Transactional;

import com.example.employeeapi.employee.dto.Employee;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
@Transactional
public class EmployeeService {

  @Autowired
  private EmployeeRepository employeeRepository;

  public Employee getEmployeeById(String employeeId) {
    EmployeeEntity entity = employeeRepository.findById(Integer.parseInt(employeeId)).get();
    Employee employee = new Employee();
    copyEntityToBean(entity, employee);
    return employee;
  }

  public List<Employee> getEmployeeList() {
    List<Employee> employees = new ArrayList<>();
    List<EmployeeEntity> employeeEntityList = employeeRepository.findAll();
    employeeEntityList.forEach(entity -> {
      Employee employee = new Employee();
      copyEntityToBean(entity, employee);
      employees.add(employee);
    });
    return employees;
  }

  public Employee createEmployee(Employee employee) {
    EmployeeEntity entity = new EmployeeEntity();
    copyBeanToEntityForInsert(employee, entity);
    EmployeeEntity createdEntity = employeeRepository.save(entity);
    Employee newEmployee = new Employee();
    copyEntityToBean(createdEntity, newEmployee);
    return newEmployee;
  }

  public Employee updateEmployee(Employee employee) {
    EmployeeEntity entity = new EmployeeEntity();
    copyBeanToEntityForUpdate(employee, entity);
    EmployeeEntity updatedEntity = employeeRepository.save(entity);
    Employee updatedEmployee = new Employee();
    copyEntityToBean(updatedEntity, updatedEmployee);
    return updatedEmployee;
  }

  public boolean deleteEmployeeById(String employeeId) {
    employeeRepository.deleteById(Integer.parseInt(employeeId));
    return true;
  }

  private void copyEntityToBean(EmployeeEntity entity, Employee employee) {
    //Erstellen Sie für das Beispiel eine einfache Kopie.
    //Wenn Sie es sauber machen wollen, BeanUtils#Verwenden Sie copyProperties usw.
    employee.setId(String.valueOf(entity.getEmployeeId()));
    employee.setName(entity.getEmployeeName());
    employee.setAge(String.valueOf(entity.getAge()));
    employee.setPositionId(entity.getPositionId());
    employee.setDepartmentId(entity.getDepartmentId());
    employee.setInsertDate(String.valueOf(entity.getInsertdate()));
    employee.setUpdateDate(String.valueOf(entity.getUpdateDate()));
  }

  private void copyBeanToEntityForInsert(Employee employee, EmployeeEntity entity) {
    //Erstellen Sie für das Beispiel eine einfache Kopie.
    //Wenn Sie es sauber machen wollen, BeanUtils#Verwenden Sie copyProperties usw.
    if (!"".equals(employee.getName())) {
      entity.setEmployeeName(employee.getName());
    }
    if (!"".equals(employee.getAge())) {
      entity.setAge(Integer.parseInt(employee.getAge()));
    }
    if (!"".equals(employee.getPositionId())) {
      entity.setPositionId(employee.getPositionId());
    }
    if (!"".equals(employee.getDepartmentId())) {
      entity.setDepartmentId(employee.getDepartmentId());
    }
  }

  private void copyBeanToEntityForUpdate(Employee employee, EmployeeEntity entity) {
    //Erstellen Sie für das Beispiel eine einfache Kopie.
    //Wenn Sie es sauber machen wollen, BeanUtils#Verwenden Sie copyProperties usw.
    entity.setEmployeeId(Integer.parseInt(employee.getId()));
    copyBeanToEntityForInsert(employee, entity);
  }

}

EmployeeController.java


package com.example.employeeapi.employee;

import java.util.List;

import com.example.employeeapi.common.dto.HttpResponseDto;
import com.example.employeeapi.employee.dto.Employee;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class EmployeeController {

  @Autowired
  private EmployeeService employeeService;

  @GetMapping(path = "/api/employee/{employeeId}")
  public HttpResponseDto getEmployeeById(@PathVariable("employeeId") String employeeId) {
    HttpResponseDto httpResponseDto = new HttpResponseDto();
    Employee employee = employeeService.getEmployeeById(employeeId);
    httpResponseDto.setHttpStatus(HttpStatus.OK);
    httpResponseDto.setResponseData(employee);
    return httpResponseDto;
  }

  @GetMapping(path = "/api/employee")
  public HttpResponseDto getEmployeeList() {
    HttpResponseDto httpResponseDto = new HttpResponseDto();
    List<Employee> employees = employeeService.getEmployeeList();
    httpResponseDto.setHttpStatus(HttpStatus.OK);
    httpResponseDto.setResponseData(employees);
    return httpResponseDto;
  }

  @PostMapping(path = "/api/employee")
  public HttpResponseDto createEmployee(@RequestBody Employee employee) {
    HttpResponseDto httpResponseDto = new HttpResponseDto();
    Employee newEmployee = employeeService.createEmployee(employee);
    httpResponseDto.setHttpStatus(HttpStatus.CREATED);
    httpResponseDto.setResponseData(newEmployee);
    return httpResponseDto;
  }

  @PutMapping(path = "/api/employee/{employeeId}")
  public HttpResponseDto updateEmployee(@PathVariable("employeeId") String emplyeeId, @RequestBody Employee employee) {
    HttpResponseDto httpResponseDto = new HttpResponseDto();
    employee.setId(emplyeeId);
    Employee updatedEmployee = employeeService.updateEmployee(employee);
    httpResponseDto.setHttpStatus(HttpStatus.CREATED);
    httpResponseDto.setResponseData(updatedEmployee);
    return httpResponseDto;
  }

  @DeleteMapping(path = "/api/employee/{employeeId}")
  public HttpResponseDto deleteEmployee(@PathVariable("employeeId") String employeeId) {
    HttpResponseDto httpResponseDto = new HttpResponseDto();
    if (employeeService.deleteEmployeeById(employeeId)) {
      httpResponseDto.setHttpStatus(HttpStatus.OK);
      httpResponseDto.setMessage("delete success.");
    } else {
      // do something
    }
    return httpResponseDto;
  }
}

Vergleich mit anderen OR Mapper (subjektiv)

Ich habe es als Vergleich mit anderen OP-Mappern geschrieben, aber es ist ein Vergleich mit Doma.

»Was ich fühlte, war gut

(Ergänzung) Datenbankaufbau

Die Verifizierungsdatenbank basiert auf Docker. Es ist mühsam, eine Datenbank zu erstellen, da sie mit Kopieren und Einfügen funktioniert! Bitte benutzen Sie es.

$ tree
.
├── docker-compose.yml
└── init-script
    ├── 01_create_table.sql
    └── 02_insert_data.sql

docker-compose.yml


version: '3'
volumes:
  db_data:
services:
  database:
    image: postgres:11.6
    container_name: postgres
    ports:
      - 5432:5432
    volumes:
      - db_data:/var/lib/postgresql/data
      - ./init-script:/docker-entrypoint-initdb.d
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: sample

01_create_table.sql


create table department (
  --Abteilungscode
  id varchar(3) primary key,
  --Abteilungsname
  name varchar(50),
  --Dateneingabedatum
  insert_date date,
  --Datum der Datenaktualisierung
  update_date date
);

create table "position" (
  --Positions-ID
  id varchar(2) primary key,
  --Titel
  name varchar(20),
  --Dateneingabedatum
  insert_date date,
  --Datum der Datenaktualisierung
  update_date date
);

--Tabellengenerierung
create table "employee" (
  --Mitarbeiternummer
  id serial primary key,
  --Mitarbeitername
  name varchar(50),
  --Alter
  age integer,
  --Position
  position_id varchar(2) references position(id),
  --ID der Zugehörigkeitsabteilung
  department_id varchar(3) references department(id),
  --Dateneingabedatum
  insert_date date,
  --Datum der Datenaktualisierung
  update_date date
);

02_insert_data.sql


insert into department (id, name, insert_date, update_date)
values ('001', 'Personalabteilung', '2020-06-17', '2020-06-17');
insert into department (id, name, insert_date, update_date)
values ('002', 'Abteilung Allgemeine Angelegenheiten', '2020-06-17', '2020-06-17');
insert into department (id, name, insert_date, update_date)
values ('003', 'Entwicklungsabteilung', '2020-06-17', '2020-06-17');
insert into department (id, name, insert_date, update_date)
values ('004', 'Abteilung für Öffentlichkeitsarbeit', '2020-06-17', '2020-06-17');
insert into position (id, name, insert_date, update_date)
values ('01', 'Direktor', '2020-06-17', '2020-06-17');
insert into position (id, name, insert_date, update_date)
values ('02', 'Manager', '2020-06-17', '2020-06-17');
insert into position (id, name, insert_date, update_date)
values ('03', 'Allgemeines', '2020-06-17', '2020-06-17');
insert into employee (
    name,
    age,
    position_id,
    department_id,
    insert_date,
    update_date
  )
values (
    'Shacho-san',
    50,
    '01',
    '001',
    '2020-06-17',
    '2020-06-17'
  );
insert into employee (
    name,
    age,
    position_id,
    department_id,
    insert_date,
    update_date
  )
values (
    'Butcho-san',
    46,
    '02',
    '001',
    '2020-06-17',
    '2020-06-17'
  );
insert into employee (
    name,
    age,
    position_id,
    department_id,
    insert_date,
    update_date
  )
values (
    'Kaccho',
    30,
    '03',
    '001',
    '2020-06-17',
    '2020-06-17'
  );
insert into employee (
    name,
    age,
    position_id,
    department_id,
    insert_date,
    update_date
  )
values (
    'Pampy',
    30,
    '03',
    '002',
    '2020-06-17',
    '2020-06-17'
  );

Am Ende

Ich möchte mir einen realen Anwendungsfall vorstellen und eine praktischere API erstellen.

Referenz

Recommended Posts

Ich habe versucht, mit Spring Data JPA zu beginnen
Ich habe versucht, mit Web Assembly zu beginnen
Ich habe versucht, mit Swagger mit Spring Boot zu beginnen
Ich habe das Spring Boot-Einführungshandbuch [Zugriff auf Daten mit JPA] ausprobiert.
Rails-Anfänger haben versucht, mit RSpec zu beginnen
Beginnen Sie mit Spring Boot
Ich habe versucht, das Hochladen von Dateien mit Spring MVC zu implementieren
Ich habe MySQL 5.7 mit Docker-Compose gestartet und versucht, eine Verbindung herzustellen
Wie fange ich mit schlank an?
Ich habe versucht, mit Java zu interagieren
Ich habe GraphQL mit Spring Boot ausprobiert
Ich habe Flyway mit Spring Boot ausprobiert
ODER suchen Sie mit der Spring Data Jpa-Spezifikation
Ich habe versucht, mithilfe von JDBC Template mit Spring MVC eine Verbindung zu MySQL herzustellen
[Hinweis] Erste Schritte mit Rspec
Ich habe es mit Spring versucht.
Ich habe Lazy Initialization mit Spring Boot 2.2.0 ausprobiert
Ich habe Spring Data JDBC 1.0.0.BUILD-SNAPSHOT ausprobiert (-> 1.0.0.RELEASE)
Ich habe versucht, AdoptOpenJDK 11 (11.0.2) mit dem Docker-Image zu überprüfen
Ich habe versucht, eine Standardauthentifizierung mit Java durchzuführen
Ich habe versucht, die Federbeinkonfiguration mit Coggle zu verwalten
Erste Schritte mit Eclipse Micro Profile
Ich habe versucht, JavaFX und Spring Framework zu verknüpfen.
Ich wollte Spring Boot in einem Multiprojekt gradle
Sortieren nach Spring Data JPA (mit zusammengesetzter Schlüsselsortierung)
Erstellen eines gemeinsamen Repositorys mit Spring Data JPA
Ich habe versucht, den Block mit Java zu brechen (1)
Ich habe versucht, mit Gradle auf Heroku zu beginnen
[Ich habe es versucht] Spring Tutorial
Ich habe Spring Batch ausprobiert
Beginnen Sie mit Gradle
Jackson kann hibernateLazyInitializer in Spring Data nicht JSON serialisieren JPA führt zu einem Fehler
Ich habe versucht, automatisch eine Klasse zu generieren, um sie mit APT von einer Datenklasse in ein Bundle zu konvertieren
Ich habe versucht, eine Webanwendung voller Fehler mit Spring Boot zu klonen
Ich habe versucht, was ich mit Stream leise versuchen wollte.
Ein Memorandum beim Versuch von Spring Data JPA mit STS
Ich habe versucht, CSV mit Outsystems zu lesen und auszugeben
Ich habe versucht, TCP / IP + BIO mit JAVA zu implementieren
[Java 11] Ich habe versucht, Java auszuführen, ohne mit Javac zu kompilieren
05. Ich habe versucht, die Quelle von Spring Boot zu löschen
Ich habe versucht, die Kapazität von Spring Boot zu reduzieren
Ich habe versucht, Animationen mit der Blazor + Canvas-API zu zeichnen
Einführung in "Einführung in die praktische Rostprogrammierung" (Tag 3)
Ich habe versucht, Sterling Sort mit Java Collector zu implementieren
Ich habe versucht, mit Java und Spring eine Funktion / einen Bildschirm für den Administrator einer Einkaufsseite zu erstellen
[spring] Verwenden wir Spring Data JPA
Ich habe Spring State Machine ausprobiert
Ich habe UPSERT mit PostgreSQL ausprobiert.
Erste Schritte mit Spring Boot
Ich habe BIND mit Docker ausprobiert
Ich habe versucht, yum-cron zu verifizieren
Ich habe versucht, mit Chocolatey eine Java8-Entwicklungsumgebung zu erstellen
Ich habe versucht, eine Java EE-Anwendung mit OpenShift zu modernisieren.