├── 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