├── build.gradle
├── settings.gradle
└── src
    └── main
        ├── java
        │   └── com
        │       └── example
        │           ├── Counter.java
        │           ├── CounterController.java
        │           ├── CounterRepository.java
        │           └── CounterService.java
        └── resources
            ├── application.properties
            └── data.sql
build.gradle
plugins {
  id 'org.springframework.boot' version '2.2.6.RELEASE'
  id 'io.spring.dependency-management' version '1.0.9.RELEASE'
  id 'java'
}
group = 'com.example'
version = '0.0.1'
sourceCompatibility = '11'
repositories {
  mavenCentral()
}
dependencies {
  // Spring
  implementation 'org.springframework.boot:spring-boot-starter-web'
  implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
  // Lombok
  compileOnly 'org.projectlombok:lombok'
  annotationProcessor 'org.projectlombok:lombok'
  // H2 Database
  runtimeOnly 'com.h2database:h2'
}
settings.gradle
rootProject.name = 'my-app'
src/main/resources/application.properties
application.properties
#Paramètres de la base de données H2
#AUTOCOMMIT avec autocommit désactivé=OFF
#TRACE pour sortir les journaux_LEVEL_SYSTEM_OUT=Précisez 2
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false;AUTOCOMMIT=OFF;TRACE_LEVEL_SYSTEM_OUT=2
#Spécifiez pour générer des journaux tels que Spring Framework et Hibernate ORM
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql=TRACE
logging.level.org.springframework.orm.jpa=DEBUG
logging.level.com.example=DEBUG
#N'utilisez pas le modèle Ouvrir EntityManager dans la vue
spring.jpa.open-in-view=false
src/main/resources/data.sql
--Ajouter les données initiales à la base de données
INSERT INTO counter (name, count, updated_at) VALUES ('mycounter', 0, LOCALTIMESTAMP);
src/main/java/com/example/Counter.java
Classe d'entité.
package com.example;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.time.LocalDateTime;
/**
 *Équivaut à un enregistrement dans la table DB.
 */
@Data //Générez automatiquement des méthodes utiles telles que getter setter avec Lombok
@Entity //Traiter comme une entité JPA
public class Counter {
  //Nom du compteur
  @Id //Faire en sorte que JPA reconnaisse cette variable comme l'ID de l'objet
  private String name;
  //Numéro de compte
  private int count;
  //Mettre à jour la date et l'heure
  private LocalDateTime updatedAt;
}
src/main/java/com/example/CounterController.java
package com.example;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@SpringBootApplication
@RestController
@Slf4j // org.slf4j.Le journal des variables finales statiques de type enregistreur est généré automatiquement
public class CounterController {
  public static void main(String[] args) {
    SpringApplication.run(CounterController.class, args);
  }
  @Autowired
  private CounterService service;
  @GetMapping("/counter/{name}")
  public Map counter(@PathVariable("name") String name) {
    //Compter jusqu'à
    log.debug("Before: countup");
    Counter counter = service.countup(name);
    log.debug("After: countup");
    //Générer une réponse JSON
    return Map.of(counter.getName(), counter.getCount());
  }
}
src/main/java/com/example/CounterService.java
package com.example;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.time.LocalDateTime;
@Service
@Slf4j // org.slf4j.Le journal des variables finales statiques de type enregistreur est généré automatiquement
public class CounterService {
  @Autowired
  private CounterRepository repository;
  /**
   *Comptez le compteur.
   *
   * @nom du paramètre Nom du compteur
   * @liste des compteurs de retour
   */
  @Transactional //Démarrer la transaction au début de la méthode, valider à la fin
  public Counter countup(String name) {
    //Obtenez 1 enregistrement de DB
    log.debug("Before: getOne");
    Counter counter = repository.getOne(name);
    log.debug("After: getOne");
    //Nombre de mises à jour
    log.debug("Before: setCount");
    counter.setCount(counter.getCount() + 1);
    log.debug("After: setCount");
    //Mettre à jour la date et l'heure
    log.debug("Before: setUpdatedAt");
    counter.setUpdatedAt(LocalDateTime.now());
    log.debug("After: setUpdatedAt");
    //Obtenez 1 enregistrement de DB
    log.debug("Before: getOne");
    Counter result = repository.getOne(name);
    log.debug("After: getOne");
    return result;
  }
}
src/main/java/com/example/CounterRepository.java
package com.example;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
 *Référentiel pour l'accès à la base de données.
 *La méthode fournie par Spring Data JPA en standard est générée automatiquement.
 */
@Repository
public interface CounterRepository extends JpaRepository<Counter, String> { //Spécifiez l'entité et le type de clé primaire
}
Lancez l'application Spring Boot avec la tâche gradle bootRun.
$ gradle bootRun
> Task :bootRun
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.6.RELEASE)
Si vous regardez le journal Spring Boot, vous pouvez voir que Hibernate ORM 5.4.12.Final est utilisé.
org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.4.12.Final
o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
Une table DB est automatiquement générée à partir de la définition de la classe d'entité.
org.hibernate.SQL                        : drop table counter if exists
org.hibernate.SQL                        : create table counter (name varchar(255) not null, count integer not null, updated_at timestamp, primary key (name))
o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
Journal de la base de données H2. Comme décrit dans data.sql, l'instruction insert a été émise.
2020-05-09 23:21:10 jdbc[3]: 
/*SQL */drop table counter if exists;
2020-05-09 23:21:10 jdbc[3]: 
/*SQL t:6*/create table counter (name varchar(255) not null, count integer not null, updated_at timestamp, primary key (name));
2020-05-09 23:21:10 jdbc[3]: 
/*SQL #:1 t:16*/INSERT INTO counter (name, count, updated_at) VALUES ('mycounter', 0, LOCALTIMESTAMP);
Accès avec la commande curl depuis un autre terminal.
$ curl http://localhost:8080/counter/mycounter
{"mycounter":1}
Consultez le journal Spring Boot. Lors de l'appel de CounterService # countup.
com.example.CounterController            : Before: countup
o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [com.example.CounterService.countup]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
o.s.orm.jpa.JpaTransactionManager        : Opened new EntityManager [SessionImpl(1254645459<open>)] for JPA transaction
o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@4ef360f9]
Lors de l'appel de CounterRepository # getOne.
com.example.CounterService               : Before: getOne
o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(1254645459<open>)] for JPA transaction
o.s.orm.jpa.JpaTransactionManager        : Participating in existing transaction
com.example.CounterService               : After: getOne
Lors de l'appel de Counter # setCount. Il semble que nous publions enfin une instruction select ici.
com.example.CounterService               : Before: setCount
org.hibernate.SQL                        : select counter0_.name as name1_0_0_, counter0_.count as count2_0_0_, counter0_.updated_at as updated_3_0_0_ from counter counter0_ where counter0_.name=?
o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [mycounter]
o.h.type.descriptor.sql.BasicExtractor   : extracted value ([count2_0_0_] : [INTEGER]) - [0]
o.h.type.descriptor.sql.BasicExtractor   : extracted value ([updated_3_0_0_] : [TIMESTAMP]) - [2020-05-09T23:21:10.472636]
com.example.CounterService               : After: setCount
Journal de la base de données H2.
2020-05-09 23:21:19 jdbc[3]: 
/*SQL l:153 #:1*/select counter0_.name as name1_0_0_, counter0_.count as count2_0_0_, counter0_.updated_at as updated_3_0_0_ from counter counter0_ where counter0_.name=? {1: 'mycounter'};
2020-05-09 23:21:19 jdbc[3]: 
/*SQL l:58 #:1*/SELECT VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE NAME=? {1: 'QUERY_TIMEOUT'};
Lors de l'appel de Counter # setUpdatedAt. Il semble qu'il n'a pas été traité.
com.example.CounterService               : Before: setUpdatedAt
com.example.CounterService               : After: setUpdatedAt
Même si vous appelez la méthode setter de l'entité plusieurs fois (setCount et setUpdatedAt), le processus de mise à jour n'est pas exécuté à ce stade.
Lors de l'appel de CounterRepository # getOne.
com.example.CounterService               : Before: getOne
o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(1254645459<open>)] for JPA transaction
o.s.orm.jpa.JpaTransactionManager        : Participating in existing transaction
com.example.CounterService               : After: getOne
Une fois que tout le code de CounterService # countup est terminé, une instruction de mise à jour est émise et validée.
o.s.orm.jpa.JpaTransactionManager        : Initiating transaction commit
o.s.orm.jpa.JpaTransactionManager        : Committing JPA transaction on EntityManager [SessionImpl(1254645459<open>)]
org.hibernate.SQL                        : update counter set count=?, updated_at=? where name=?
o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [INTEGER] - [1]
o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [TIMESTAMP] - [2020-05-09T23:21:19.247019]
o.h.type.descriptor.sql.BasicBinder      : binding parameter [3] as [VARCHAR] - [mycounter]
Journal de la base de données H2.
2020-05-09 23:21:19 jdbc[3]: 
/*SQL l:53 #:1 t:3*/update counter set count=?, updated_at=? where name=? {1: 1, 2: TIMESTAMP '2020-05-09 23:21:19.247019', 3: 'mycounter'};
2020-05-09 23:21:19 jdbc[3]: 
/*SQL */COMMIT;
2020-05-09 23:21:19 jdbc[3]: 
/*SQL */COMMIT;
Après la transaction.
o.s.orm.jpa.JpaTransactionManager        : Closing JPA EntityManager [SessionImpl(1254645459<open>)] after transaction
Appel de comptage CounterService # terminé.
com.example.CounterController            : After: countup
Recommended Posts