[JAVA] Aide-mémoire Spring Boot2

introduction

L'auteur qui utilise Spring pour les affaires a étudié «[Introduction à la programmation SpringBoot2](https://www.amazon.co.jp/Spring-Boot-2-Introduction à la programmation-Yano Palmada / dp / 4798053473)» C'est comme une feuille de triche / un mémo de lecture. Le public cible est ceux qui ont appris les bases de Java et n'ont aucune expérience avec Spring Boot - le niveau qui a commencé à étudier les bases. Le langage est Java, L'outil de construction est Maven, Le moteur de modèle est Thymeleaf.

Qu'est-ce que Spring Boot?

Un framework (groupe) créé en combinant la bibliothèque fournie par Spring Framework et Spring MVC (framework) pour le développement d'applications WEB à grande vitesse.

1. 1. Configuration du développement de printemps

Puisque cet article est utilisé comme aide-mémoire, il est omis ici.

2. Développement d'applications très simple avec Groovy

Groovy est un langage adapté à la réalisation de prototypes en peu de temps avant le développement à grande échelle en Java. Groovy est omis ici. @ RestController Il est utilisé pour construire un système accessible de l'extérieur pour récupérer les informations nécessaires. Utilisations telles que le renvoi des informations nécessaires au format texte ou XML lors de l'accès. @ RequestMapping Cela signifie exécuter cette méthode lors de l'accès à cette adresse. Écrivez comme `@RequestMapping (" / ") ʻet spécifiez le chemin comme argument. Lors de l'accès au chemin spécifié, la méthode avec cette annotation sera exécutée.

SampleController.java


@RestController
public class SampleController {

  @RequestMapping("/")
  public String index() {
    return "Hello SpringBoot World";
  }
}

Utilisez Thymeleaf

Un moteur de modèle qui peut être utilisé en ajoutant des balises HTML. la caractéristique est,

--Préparation d'un attribut unique de "th: ◯◯" dans la balise

home.html


<body>
  <h1>Hello!</h1>
  <p class="msg" th:text="${msg}">this is sample.</p>
</body>

Il est possible d'écrire du HTML avec Groovy comme moteur de modèle, mais il est omis ici pour plus de commodité.

[@Controller est décrit au chapitre 3](# -controller) @ ResponseBody Pour les méthodes avec «@ ResponseBody», la valeur de retour devient le contenu de la réponse tel quel. Pour la méthode du contrôleur avec @ RestController, la valeur de retour sera le contenu sans ajouter @ ResponseBody. Les méthodes des classes de contrôleur avec @ Controller renvoient souvent la classe ModelAndView, sauf lorsque vous devez renvoyer JSON ou XML, vous pouvez ajouter @ ResponseBody au contrôleur pour le contenu. Il peut se retourner.

3. 3. Principes de base du développement Spring Boot avec Java

Comment fonctionne l'application Spring Boot

Spring Boot utilise le serveur Java intégré pour exécuter l'application, aucun déploiement n'est donc requis. Cela fonctionne bien avec les éléments qui exécutent des programmes à l'intérieur du serveur, tels que les services cloud. Bien qu'il présente l'inconvénient d'augmenter la taille du fichier, il devient de facto le standard du développement Web en Java.

Projet Spring Starter pom.xml

La définition de parent est la suivante

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.3.0.RELEASE</version>
  <relativePath/> <!-- lookup parent from repository -->
</parent>

La définition des dépendances est la suivante

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>      
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
</dependencies>

Les définitions de build et plugin sont les suivantes

<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
  </plugins>
</build>

Utiliser RestController

Lorsque vous créez un projet Spring Starter avec Spring Tool Suite (STS), un fichier appelé MyBootAppApplication.java est créé par défaut. Si @SpringBootApplication est attaché, ce sera une classe qui sera appelée au démarrage de SpringBoot. SpringApplication.run, la classe annotée lancera l'application. "Exécuter" est une méthode pour démarrer une application. Pour les arguments, préparez l'instance Class de la classe à exécuter et les données à transmettre en tant que paramètres.

MyBootAppApplication.java


@SpringBootApplication
public class MyBootAppApplication {

  public static void main(String[] args) {
    SpringApplication.run(MyBootAppApplication.class, args);
  }
}

À propos de l'architecture MVC

architecture rôle
Model Gérer les données utilisées par l'application
View Affichage de l'écran de la poignée
Controller Contrôlez l'ensemble du processus

Passer les paramètres

En utilisant une variable de chemin sous la forme de @RequestMapping (" / {param} "), vous pouvez recevoir la valeur passée à la partie de chemin sous l'adresse en tant que variable. [Qu'est-ce que @RequestMapping](# -requestmapping)

Variables de chemin et @ PathVariable

Indique que la valeur est transmise par une variable de chemin.

@RequestMapping("/{num}")
public String index(@PathVariable int num){
  int res = 0;
  for(int i = 1; i<= num; i++){
    res += i;
  }
  return "total:" + res;
}

Objet de sortie dans JSON

Les services REST peuvent également renvoyer des classes en tant que valeurs de retour autres que String. L'instance renvoyée est convertie au format JSON.

//Définissez la classe DataObject séparément
public DataObject index(@PathVariable int id) {
  return new DataObject();
}

Création de page Web par le contrôleur

Lorsque vous utilisez une page Web normale, ajoutez @ Controller avant la classe de contrôleur. Dans cet article, je souhaite utiliser Thymeleaf comme modèle, alors ajoutez la dépendance à pom.xml comme suit.

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

@ Controller Utilisé pour rendre et afficher des pages HTML à l'aide de modèles.

SampleController.java


@Controller
public class SampleController {
  @RequestMapping("/")
  public String home(){
    return "home";
  }
}

Utilisation de la classe Model

Model est une classe de gestion des données utilisées sur les pages Web. Les données peuvent être transmises en définissant la valeur utilisée dans le modèle dans ce Modèle. Définissez la valeur avec ʻaddAttribute. Spécifiez le nom de la valeur dans le premier argument et la valeur complémentaire dans le deuxième argument. En suivant l'exemple ci-dessous, la valeur de la variable msg peut être récupérée sous la forme $ {msg}` côté modèle. La valeur de retour ne peut pas être utilisée comme «Modèle» (car elle ne contient pas d'informations sur le modèle).

@RequestMapping("/{num}")
public String home(@PathVariable int num, Model model) {
  ...
  model.addAttribute("msg", "total:" + res);
  return "home";
}

Utilisation de la classe ModelAndView

Gérez les données utilisées dans les modèles et les informations sur les vues (noms de modèles, etc.). En renvoyant ce ModelAndView comme valeur de retour, le modèle défini sera utilisé. Définissez l'objet comme ʻaddObject (String entitySetName, Object entity) , et définissez le nom de la vue à utiliser avec setViewName (String viewName) `.

@RequestMapping("/{num}")
public ModelAndView index(@PathVariable int num, ModelAndView mav) {
  ...
  mav.addObject("msg",  "total:" + res);
  mav.setViewName("home");
  return mav;
}

Utilisez le formulaire

Préparez un formulaire avec <form method =" POST "action =" / ">, et envoyez POST avec la même destination " / ". Dans la balise ʻinput type = "text" , la valeur de $ value est affichée dans le champ de saisie comme dans th: text = "$ {value}" . S'il y a plusieurs arguments pour @ RequestMapping tels que @RequestMapping (value =" / ", method = RequestMethod.POST), omettez le nom de l'argument comme value = "/" pour la destination du mappage. Besoin d'écrire sans. L'exemple a la même adresse et fait la distinction entre «GET» et «POST» pour les méthodes. La valeur envoyée depuis le formulaire est traitée par la méthode d'envoi. @ RequestParam est une annotation pour spécifier la valeur soumise dans le formulaire, qui transmet la valeur saisie dans le formulaire name =" text1 " à cet argument str`.

[Côté Conrotorer]

SampleController.java


@Controller
public class SampleController {
  @RequestMapping(value="/", method=RequestMethod.GET)
  public ModelAndView index(ModelAndView mav) {
    mav.setViewName("form");
    mav.addObject("msg", "please put and send your name.");
    return mav;
  }

  @RequestMapping(value="/", method=RequestMethod.POST)
  public ModelAndView send(@RequestParam("text1")String str, ModelAndView mav) {
    mav.addObject("msg", "Bonjour");
    mav.addObject("value", "message");
    mav.setViewName("form");
    return mav;
}

[Côté modèle]

form.html



<body>
    <h1>Sample Form</h1>
    <p th:text ="${msg}">Cela remplace msg</p>
    <form method="POST" action="/">
        <input type="text" name="text1" th:value="${value}"/>
        <input type="submit" value="Click" />
    </form>
</body>

Autre exemple de modèle de contrôle de formulaire

La valeur soumise à partir du formulaire est reçue par la méthode send. La méthode a quatre arguments avec @ RequestParam afin de pouvoir recevoir des valeurs du formulaire. Spécifiez le nom du paramètre avec "valeur" et spécifiez la contrainte nulle de la valeur avec "obligatoire". [Côté contrôleur]

SampleController.java


@Controller
public class SampleController {
    @RequestMapping(value="/", method=RequestMethod.GET)
    public ModelAndView index(ModelAndView mav) {
    //Demande GET omise
    }
  
    @RequestMapping(value="/", method=RequestMethod.POST)
    public ModelAndView send(
        //Case à cocher: la valeur peut obtenir l'état sélectionné sous forme de valeur booléenne
        @RequestParam(value="check1", required=false)boolean check1,
        //Bouton radio: transmettez la valeur de l'élément sélectionné en tant que valeur de chaîne, mais null si elle n'est pas sélectionnée
        @RequestParam(value="radio1",required=false)String radio1,
        //Liste de sélection: lorsqu'un seul élément est sélectionné, la valeur est transmise en tant que valeur de chaîne, mais lorsque plusieurs éléments peuvent être sélectionnés, elle est transmise en tant que tableau de chaînes, et lorsqu'elle n'est pas sélectionnée, elle est nulle.
        @RequestParam(value="select1", required=false)String select1,
        @RequestParam(value="select2", required=false)String[] select2, 
        ModelAndView mav) {
      String res = "";
      //Traitement omis
      ...
      //Incorporer la résolution dans le msg
      mav.addObject("msg", res);
      mav.setViewName("form");
      return mav;
    }
}

[Côté modèle]

<body>
    <h1>Form Controll Example</h1>
    <form method="POST" action="/">
        <div>
        <input type="checkbox" id="check1" name="check1" />
        <label for="check1">Case à cocher</label>
        </div>
        <div>
        <input type="radio" id="radioA" name="radio1" value="male" />
        <label for="radioA">Masculin</label>
        </div>
        <div>
        <input type="radio" id="radioB" name="radio1" value="female" />
        <label for="radioB">Femme</label>
        </div>
        <div>
        <select id="select1" name="select1" size="4">
            <option value="Red">rouge</option>
            <option value="Blue">Bleu</option>
            <option value="Yellow">Jaune</option>
        </select>
        <select id="select2" name="select2" size="4" multiple="multiple">
            <option value="SmartPhone">téléphone intelligent</option>
            <option value="Tablet">Tablette</option>
            <option value="Laptop">Portable</option>
        </select>
        </div>
        <input type="submit" value="Click" />
    </form>
</body>

réorienter

Il existe ** forward ** et ** redirect ** pour vous permettre de passer à une autre adresse lorsque vous accédez à une adresse.

[Côté contrôleur]

SampleController.java


@Controller
public class SampleController {
    @RequestMapping("/")
    public ModelAndView index(ModelAndView mav) {
        mav.setViewName("home");
        return mav;
    }
    //"/other"L'adresse elle-même"/"Il est remplacé par, et le contenu affiché est également"/"Devenez une chose.
    @RequestMapping("/other")
    public String other() {
        return "redirect:/";
    }
    //"/home"Lorsque vous y accédez, le contenu affiché reste le même"/"Montrez des choses.
    @RequestMapping("/home")
    public String home() {
        return "forward:/";
    }
}

[Côté modèle]

home.html


<body>
  <h1>Home Page</h1>
</body>

4. Maîtrisez le moteur de template

Thymeleaf divers

Objet utilitaire

Les classes fréquemment utilisées peuvent être utilisées en les décrivant directement dans une expression constante comme une constante "** # nom **". Puisqu'il s'agit d'une constante de classe, elle peut être utilisée en appelant directement des méthodes de classe. Comme "# dates. Méthode de classe". L'exemple suivant

Objet utilitaire constant
#strings Constante de classe de chaîne
#numbers Constante de classe numérique
#Bools Constante de classe booléenne
#dates Constante de classe de date
#objects Constante de classe d'objets
#arrays Constante de classe de tableau
#lists Répertorier les constantes de classe
#sets Définir la constante de classe
#maps Constante de classe de carte

Utilisez la méthode format de la constante de classe Date # dates, créez un objet de classe Date dans le premier argument et spécifiez le format aaaa / MM / jj HH: mm: ss dans le deuxième argument.

    <p th:text="${#dates.format(new java.util.Date(), 'dd/MMM/yyyy HH:mm')}"></p>

En utilisant la méthode formatInteger de la constante # nombres de la classe Number, l'entier est affiché comme premier argument et les chiffres du deuxième argument sont affichés, séparés par le troisième argument.

    <p th:text="${#numbers.formatInteger(10000000, 3, 'COMMA')}"></p>

Le toUpperCase de la constante de classe String # strings est une méthode qui convertit le texte de l'argument en majuscules.

    <p th:text="${#strings.toUpperCase('show uppercase')}"></p>

Accès aux paramètres

En écrivant comme {param.id}, vous pouvez recevoir la valeur envoyée sous la forme "id = ○○" et utiliser les paramètres directement dans le modèle sans passer par le contrôleur. Cependant, comme les valeurs obtenues sont des tableaux, les valeurs sont extraites et utilisées.

<!--/?id=hoge&name=Passer comme fuga-->
<p th:text="'from parameter.. id=' + ${param.id[0] + ',name=' + param.name[0]}"></p>

Expression de message

Extrayez la valeur du fichier de propriétés et utilisez-la dans le modèle. La méthode de description est # {spécifier la valeur}

message.properties


article.title=this is home page.
article.message=this message from properties.
<h1 th:text="#{article.title}"></h1>
<p th:text="#{article.message}"></p>

Linked et href

Lorsque vous accédez à /? Id = fuga, ** / hoge / fuga ** est défini pour le lien.

<p><a href="home.html" th:href="@{/hoge/{id}(id=${param.id})}">link</a></p>

Expression de variable vers l'objet sélectionné

Les expressions variables peuvent utiliser des objets ainsi que des nombres et du texte. La façon de faire est de spécifier un objet et d'utiliser * {valeur} pour récupérer la valeur dans l'objet sélectionné.

  <table th:object="${object}">
    <tr><th>ID</th><td th:text="*{id}"></td></tr>
    <tr><th>NAME</th><td th:text="*{name}"></td></tr>
    <tr><th>MAIL</th><td th:text="*{value}"></td></tr>
  </table>

Remplacement littéral

Si vous entourez le texte avant et après avec "|", vous pouvez directement écrire l'expression variable et combiner les chaînes.

<p th:text="|My name is *{name}. Mailaddress is *{value}.|"></p>

Sortie de code HTML

Dans Thymeleaf, lors de la sortie de texte en tant qu'expression variable, toutes les balises HTML sont échappées pour des raisons de sécurité, donc Vous pouvez libérer l'échappement en utilisant th: utext. Cependant, si la valeur contient une balise HTML, elle fonctionnera telle quelle, donc si vous créez du texte basé sur les informations envoyées par l'utilisateur, vous serez vulnérable aux attaques telles que XSS.

[Côté contrôleur]

@RequestMapping("/")
public ModelAndView index(ModelAndView mav) {
    mav.setViewName("home");
    mav.addObject("msg", "message 1<hr/>message 2<br/>message3");
    return mav;
} 

[Côté modèle]

<p th:utext="${msg}">message.</p>

Syntaxe / disposition en ligne

Expression conditionnelle

Modifiez le contenu de la sortie en fonction du résultat de la valeur booléenne préparée à l'avance.

[Côté contrôleur]

@RequestMapping("/{id}")
public ModelAndView index(@PathVariable int id,
		ModelAndView mav) {
	mav.setViewName("check");
	mav.addObject("id",id);
	mav.addObject("num",id % 2 == 0);
	mav.addObject("even","Even number!");
	mav.addObject("odd","Odd number...");
	return mav;
}

[Côté modèle]

check.html


<p th:class="${num} ? 'even' : 'odd'"></p>

La valeur définie est «true» (nombre différent de zéro, «0», Dans le cas de (y compris du texte autre que des valeurs telles que "off" et "no"), cette balise et les balises qu'elle contient sont affichées.

Si la valeur définie est «false» (y compris du texte tel que le nombre zéro, «0», «off», «no»), cette balise et les balises internes sont affichées.

[Côté contrôleur]

@RequestMapping("/{id}")
public ModelAndView index(@PathVariable int id,
		ModelAndView mav) {
	mav.setViewName("check");
	mav.addObject("id",id);
	mav.addObject("num",id >= 0);
	mav.addObject("trueVal","POSITIVE!");
	mav.addObject("falseVal","negative...");
	return mav;
}

[Côté modèle]

check.html


	<p th:if="${num}" th:text="${id} + ' is ' + ${trueVal}"></p>
	<p th:unless="${num}" th:text="${id} + ' is ' + ${falseVal}"></p>

Vérifie la valeur de l'expression conditionnelle spécifiée, recherche la même valeur à partir du «th: case» à l'intérieur et renvoie uniquement cette balise. th: case =" * " est un joker qui attrape tout ce qui ne remplit aucune des conditions.

[Côté contrôleur]

@RequestMapping("/{month}")
public ModelAndView index(@PathVariable int month,
		ModelAndView mav) {
	mav.setViewName("index");
	int m = Math.abs(month) % 12;
	m = m == 0 ? 12 : m;
	mav.addObject("month",m);
	mav.addObject("check",Math.floor(m / 3));
	return mav;
}

[Côté modèle]

<div th:switch="${check}">
    <p th:case="0" th:text="|${month} - Winter|"></p>
    <p th:case="1" th:text="|${month} - Spring|"></p>
    <p th:case="2" th:text="|${month} - Summer|"></p>
    <p th:case="3" th:text="|${month} - Autumn|"></p>
    <p th:case="4" th:text="|${month} - Winter|"></p>
    <p th:case="*">...?</p>
</div>

Dans th: each, préparez un tableau ou une collection en tant que valeur et décrivez-le à la manière d'une instruction for étendue comme value: $ {list}. Cela récupérera les valeurs dans l'ordre de la liste après les deux points et les assignera aux variables avant les deux points.

[Côté modèle]

<table>
    <tr>
        <th>NAME</th>
        <th>MAIL</th>
        <th>TEL</th>
    </tr>
    <tr th:each="obj:${data}">
        <td th:text="${obj[0]}"></td>
        <td th:text="${obj[1]}"></td>
        <td th:text="${obj[2]}"></td>
    </tr>
</table>

Prétraitement

Si vous le déclarez sous la forme __ $ {variable} __, il sera évalué à l'avance et l'expression de variable sera exécutée.

[Côté contrôleur]

ArrayList<Pockemon> monsters = new ArrayList<>();
monsters.add(new Pockemon(0,"Hitokage","Fire"));
monsters.add(new Pockemon(1,"Fushigidane","Grass"));
monsters.add(new Pockemon(2,"Zenigame","Water"));
mav.addObject("num", 1);
mav.addObject("monsters",monsters);
return mav

[Côté modèle]

<div th:object="${monsters.get(${num})}">
    <p th:text="*{id}"></p>
</div>

Traitement en ligne

Même si vous ne le préparez pas sous la forme d'attributs comme th: text (il y a un côté qui n'affecte pas l'affichage de la page même si Thymeleaf ne fonctionne pas), Thymeleaf directement entre les balises HTML Vous pouvez écrire l'expression variable de. Si vous écrivez th: inline =" text " dans la balise, vous pouvez écrire une expression variable comme [[$ {variable}]] à l'intérieur pour activer le traitement en ligne.

[Côté contrôleur]

ArrayList<Pockemon> monsters = new ArrayList<>();
monsters.add(new Pockemon(0,"Hitokage","Fire"));
monsters.add(new Pockemon(1,"Fushigidane","Grass"));
monsters.add(new Pockemon(2,"Zenigame","Water"));
mav.addObject("monsters",monsters);
return mav

[Côté modèle]

<tr th:inline="text" th:each="monster : ${monsters}">
    <td>[[${monster.id}]]</td>
    <td>[[${monster.name}]]</td>
    <td>[[${monster.type}]]</td>
</tr>

Traitement en ligne avec JavaScript

Spécifiez la valeur <script th: inline =" javascript "> et ʻinline comme "javascript" ʻau lieu de"texte", et l'expression de variable est` / * [[$ {expression variable}]] ] * / ʻEt en écrivant sous forme de commentaire, il peut être utilisé en l'incorporant dans le script.

python


<script th:inline="javascript">
   console.log(/*[[$(variable)]]*/);   
</script>

Fragment de modèle

Une méthode appelée ** fragment de modèle ** qui compose une page en combinant plusieurs fichiers. Insérez la partie décrite comme une partie dans le fichier qui peut être coupée et manipulée comme un ** fragment ** à l'emplacement spécifié d'un autre modèle.

[Modèles qui deviennent des pièces]

part.html


<p th:fragment="frag_body">

[Côté incorporation]

<p th:include="part::frag_body">

Autre moteur de modèle

Dans Spring, JSP et Groovy peuvent également être utilisés comme moteurs de modèles, mais ils sont omis pour plus de commodité.

5. Modèle et base de données

En Java, DB est utilisé à l'aide de JPA (API de persistance Java Persistence API). Même au printemps, l'accès à la base de données est effectué à l'aide de SpringBootStarterDataJPA.

Si vous gérez votre projet avec Maven, ajoutez la dépendance suivante à pom.xml et utilisez-la.

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

Lors de l'utilisation de JPA, la partie de données est définie comme une classe appelée ** entité **. Une table est définie dans la base de données et les données y sont stockées sous forme d'enregistrements, mais l'entité peut être considérée comme stockant chacun de ces enregistrements en tant qu'objet Java.

Vous trouverez ci-dessous un exemple de la classe ** Entity ** qui sert de modèle.

@Entity
@Table(name="mydata")
public class MyData {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column
	private long usrId;
	@Column(length = 50, nullable = false)
	private String usrName;
	@Column(length = 200, nullable = true)
	private String usrAddress;
	@Column(nullable = true)
	private Integer age;
	@Column(nullable = true)
	private String comment;

	public long getUsrId() { return usrId; }
    public void setUsrId(long usrId) { this.usrId = usrId; }
    
	public String getUsrName() { return usrName; }
    public void setUsrName(String usrName) { this.usrName = usrName; }
    
    public String getUsrAddress() { return usrAddress; }
    public void setUsrAddress(String usrAddress) { this.usrAddress = usrAddress; }
    
	public Integer getAge() { return age; }
    public void setAge(Integer age) { this.age = age; }
    
	public String getComment() { return comment; }
	public void setComment(String comment) { this.comment = comment; }
}

@ Entity Annotation indiquant qu'il s'agit d'une classe d'entité @ Table(name="mydata") Spécifie la table affectée à cette classe d'entité. Si nom est omis, le nom de la classe sera utilisé comme nom de la table. @ Id Spécifier la clé primaire @ GeneratedValue(strategy = GenerationType.AUTO) Générez automatiquement une valeur pour le champ de la clé primaire. La méthode de génération est spécifiée dans strategy, et dans l'exemple, GenerationType.AUTO et la valeur du type d'énumération sont spécifiées pour être attribuées automatiquement. @ Column Spécifiez le nom de colonne attribué au champ. Si «nom» est omis, le nom du champ est utilisé tel quel comme nom de colonne.

@Argument de colonne La description
name Spécifier le nom de la colonne
length Longueur maximale(Nombre de caractères dans la chaîne)Spécifier
nullable Spécifiez s'il faut autoriser null

À propos du référentiel

Entity-> Une classe qui permet aux données stockées dans des tables d'être traitées comme des objets dans Java Préparé comme une interface de référentiel->, il génère et implémente automatiquement un traitement d'accès à la base de données à usage général, il n'est donc presque pas nécessaire d'écrire du code.

Créé en héritant de JpaRepository @ Repository Indique que cette classe est une classe d'accès aux données.

@Repository
public interface MyDataRepository extends JpaRepository<MyData, Long> {

}

@ Autowired Dans l'exemple, «@ Autowired» est utilisé pour injecter une instance MyDataRepository dans un champ. Si vous mettez @ Autowired devant la variable d'instance, il recherchera la classe correspondante dans les classes avec @ Component, la renouvellera et la plongera dans le champ. Bien qu'il dise «@ Component», «@ Controller», «@ Repository», «@ Service» sont utilisés correctement en fonction de la couche.

méthode findAll

Toutes les entités peuvent être automatiquement récupérées par la méthode fournie dans JpaRepository, qui est la source d'héritage.

@Controller
public class SampleController {

  @Autowired
  MyDataRepository repository;

  @RequestMapping("/")
  public ModelAndView home(ModelAndView mav) {
    mav.setViewName("home");
    Iterable<MyData> list = repository.findAll();
    mav.addObject("data", list);
    return mav;
  }
}

CRUD de l'entité

「Create」「Read」「Update」「Delete」 @ ModelAttribute Il est utilisé pour préparer automatiquement une instance de la classe d'entité. Spécifiez le nom de l'instance dans l'argument. Dans la méthode d'index pour l'accès GET, une nouvelle instance est créée et affectée à l'argument de MyData (toutes les valeurs sont des valeurs initiales). Dans la méthode de formulaire appelée par l'accès POST, les valeurs du formulaire soumis sont automatiquement collectées et transmises à l'instance MyData.

Économisez avec SaveAndFlush

repository.saveAndFlush(mydata);

L'entité préparée est spécifiée dans l'argument de la méthode saveAndFlush fournie dans JpaRepository et est rendue persistante. @ Transactional L'annotation «@ Transactional» est pour la fonction de transaction, et en l'attachant à la méthode, l'accès à la base de données exécuté dans la méthode sera exécuté dans un lot. Dans le cas d'un traitement qui réécrit des données, les transactions sont des traitements importants, par exemple empêcher l'accès à la base de données de l'extérieur et causer des problèmes d'intégrité des données.

L'argument readOnly = false indique littéralement qu'il est" en lecture seule (non réinscriptible) ". Lorsque readOnly = false est défini, la transaction passe d'une transaction en lecture seule à une transaction qui permet la mise à jour des données telle que l'enregistrement.

SampleController.java


@Controller
public class SampleController {
  @Autowired
  MyDataRepository repository;

  @RequestMapping(value = "/", method = RequestMethod.GET)
  public ModelAndView index(@ModelAttribute("formModel") MyData mydata,
      ModelAndView mav) {
    mav.setViewName("index");
    mav.addObject("msg", "this is sample content.");
    Iterable<MyData> list = repository.findAll();
    mav.addObject("datalist", list);
  }

  @RequestMapping(value = "/", method = RequestMethod.POST)
  @Transactional(readonly = false)
  public ModelAndView form(@ModelAttribute("formModel") MyData mydata,
      ModelAndView mav){
    repository.saveAndFlush(mydata);
    return new ModelAndView("redirect:/");        
  }
}
<body>
  <table>
  <form method="post" action="/" th:object="${formModel}">
    <tr>
      <td><label for="name>Nom</label></td>
      <td><input type="text" name="name" th:value="*{name}" /></td>
    </tr>
    <tr>
      <td><label for="name>âge</label></td>
      <td><input type="text" name="age" th:value="*{age}" /></td>
    </tr>
    <tr>
      <td><label for="name>Email</label></td>
      <td><input type="text" name="mail" th:value="*{mail}" /></td>
    </tr>
    <tr>
      <td><label for="name>Note</label></td>
      <td><textarea name="memo" th:value="*{memo}" cols="20" rows="5"></textarea></td>
    </tr>
  </form>
  </table>
  <hr/>
  <table>
    <tr>
      <th>ID</th>
      <th>Nom</th>
    </tr>
    <tr th:each="obj : ${datalist}">
      <td>${obj.id}</td>
      <td>${obj.name}</td>
    </tr>
  <table>
</body>

@ PostConstruct Indique que la méthode est appelée après que le constructeur a créé une instance. Le contrôleur est créé une seule fois au début et l'instance est conservée par la suite.

SampleComtroller.java


@PostConstruct
public void init(){
	MyData d1 = new MyData();
	d1.setName("tuyano");
	d1.setAge(123);
	d1.setMail("[email protected]");
	d1.setMemo("this is my data!");
	repository.saveAndFlush(d1);
	MyData d2 = new MyData();
	d2.setName("hanako");
	d2.setAge(15);
	d2.setMail("hanako@flower");
	d2.setMemo("my girl friend.");
	repository.saveAndFlush(d2);
	MyData d3 = new MyData();
	d3.setName("sachiko");
	d3.setAge(37);
	d3.setMail("sachico@happy");
	d3.setMemo("my work friend...");
	repository.saveAndFlush(d3);
}

Mise à jour des données

【modèle】 Th: object =" $ {formModel} " est spécifié dans <form>, mais si l'entité à éditer est définie dans ce formModel,type = "hidden"le fera. L'ID est stocké dans le champ masqué.

<body>
	<h1 th:text="${title}">Edit page</h1>
	<table>
	<form method="post" action="/edit" th:object="${formModel}">
		<input type="hidden" name="id" th:value="*{id}" />
		<tr><td><label for="name">Nom</label></td>
			<td><input type="text" name="name" th:value="*{name}" /></td></tr>
		<tr><td><label for="age">âge</label></td>
			<td><input type="text" name="age"  th:value="*{age}" /></td></tr>
		<tr><td><label for="mail">Email</label></td>
			<td><input type="text" name="mail"  th:value="*{mail}" /></td></tr>
		<tr><td><label for="memo">Note</label></td>
			<td><textarea name="memo"  th:text="*{memo}" 
			cols="20" rows="5"></textarea></td></tr>
		<tr><td></td><td><input type="submit" /></td></tr>
	</form>
	</table>
</body>

Implémentez le processus de recherche et de récupération des entités par ID dans le référentiel. findById est une méthode pour récupérer une instance MyData avec un numéro d'identification comme argument.

MyDataRepository.java


@Repository
public interface MyDataRepository extends JpaRepository<MyData, Long> {
    public MyData findById(Long name):
}

Dans la méthode d'édition appelée au moment de l'accès GET, l'entité est acquise par «findById» qui prend l'ID envoyé dans la requête comme argument, et «get» est utilisé pour spécifier le nom «formModel» et «addObject». .. La méthode de mise à jour est appelée lorsque le formulaire est soumis à / edit. Lors de l'enregistrement d'une entité basée sur les données du formulaire envoyées, mettez-la à jour avec le même saveAndFlush que lors de l'enregistrement de nouvelles données. La différence entre une nouvelle sauvegarde et une mise à jour est de savoir si un ID est spécifié pour l'entité argument.

SampleController.java


@RequestMapping(value = "/edit/{id}", method = RequestMethod.GET)
public ModelAndView edit(@ModelAttribute MyData mydata, @PathVariable int id, ModelAndView mav) {
	mav.setViewName("edit");
	mav.addObject("title","edit mydata.");
	MyData data = repository.findById((long)id);
	mav.addObject("formModel",data.get());
	return mav;
}
@RequestMapping(value = "/edit", method = RequestMethod.POST)
@Transactional(readOnly=false)
public ModelAndView update(@ModelAttribute MyData mydata, ModelAndView mav) {
	repository.saveAndFlush(mydata);
	return new ModelAndView("redirect:/");
}

Supprimer l'entité

Il existe une méthode delete pour GET access to / delete et une méthode remove pour gérer l'accès POST. La méthode delete recherche l'entité avec l'ID spécifié par findById et l'affiche. Après cela, l'entité envoyée par la méthode de suppression envoyée par POST est supprimée. N'oubliez pas d'ajouter l'annotation «@ Transactional» à la méthode car «delete» implique également de changer la base de données.

@RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
public ModelAndView delete(@PathVariable int id, ModelAndView mav) {
  mav.setViewName("delete");
  mav.addObject("title", "delete mydata.");
  MyData data = repository.findById((long)id);
  mav.addObject("formModel", data);
  return mav;
}
@RequestMapping(value = "/delete", method = RequestMethod.POST)
@Transactional(readOnly = false)
public ModelAndView remove(@RequestParam long id, ModelAndView mav){
  repository.delete(id);
  return new ModelAndView("redirect:/");
}

Génération automatique de méthode de référentiel

JpaRepository a une fonction intégrée de génération de code automatique à l'aide d'un dictionnaire. JpaRepository génère et exécute le texte de requête par JPQL.

findById(argument)
   ↓
"find" "by" "id"argument
   ↓
"select *de la table où id=argument"Exécution de la requête

Comment utiliser JPQL

And Il est utilisé lors de la recherche d'un élément qui correspond aux deux valeurs de deux éléments. Préparez deux arguments comme valeur de chaque élément.

findByIdAndName
   ↓
from MyDataEntity where id = ?1 and name = ?2

Or Il est utilisé lors de la recherche d'un élément qui correspond à l'une des valeurs de deux éléments. Préparez deux arguments comme valeur de chaque élément.

findByIdOrName
    ↓
from MyDataEntity where id = ?1 or name = ?2

Between Il est utilisé lors du passage de deux arguments en tant que valeurs et lors de la recherche d'une valeur entre eux. Recherchez des éléments dans une certaine plage d'éléments spécifiés.

findByAgeBetween
   ↓
from MyDataEntity where age between ?1 and ?2

LessThan Recherchez les éléments numériques inférieurs à la valeur spécifiée dans l'argument.

findByAgeLessThan
   ↓
from MyDataEntity where age < ?1

GreaterThan Recherchez les éléments numériques supérieurs à la valeur spécifiée dans l'argument.

findByAgeGreaterThan
   ↓
from MyDataEntity where age > ?1

IsNull Recherche un élément spécifié avec une valeur nulle.

findCommentIsNull
   ↓
from MyDataEntity where comment is null

IsNotNull, NotNull Recherche la valeur de l'élément spécifié qui n'est pas nulle. Comprendre même avec Not Null

findByCommentNotNull,
findByCommentIsNotNull
   ↓
from MyDataEntity where comment not null

Like Effectuez une recherche LIKE du texte. Recherche ambiguë d'une valeur à partir d'un élément spécifié. Vous pouvez l'utiliser avec un caractère générique attaché à la valeur transmise à l'argument.

findByNameLike
   ↓
from MyDataEntity where name like ?1

NotLike Recherche ambiguë de choses qui n'incluent pas la chaîne de recherche. Vous pouvez l'utiliser avec un caractère générique attaché à la valeur transmise à l'argument.

findByNameNotLike
   ↓
from MyDataEntity where name not like ?1

OrderBy Précisez la commande. Il est ajouté après le nom de la méthode de recherche normale. Vous pouvez spécifier un ordre croissant ou décroissant en ajoutant ʻAsc ou Desc` après le nom de l'élément.

findByNameOrderByAgeAsc
   ↓
from MyDataEntity where name = ?1 order by age Asc

Not Recherchez les éléments dont l'élément spécifié n'est pas égal à la valeur de l'argument.

findByNameNot
   ↓
from MyDataEntity where name <> ?1

In Rechercher si la valeur de l'élément spécifié correspond à l'une des valeurs fournies dans la collection d'arguments

findByNameIn(Collection<String> name)
   ↓
from MyDataEntity where name in ?1

NotIn Recherche la valeur de l'élément spécifié qui ne correspond à aucune des valeurs fournies dans la collection d'arguments

findByNameNotIn(Collection<String> name)
   ↓
from MyDataEntity where name not in ?1

Exemple d'implémentation de la méthode JpaRepository

@Repository
public interface MyDataRepository  extends JpaRepository<MyData, Long> {

	// "%" + str + "%"Vous devez spécifier un caractère générique comme
	public List<MyData> findById(Long name);
	public List<MyData> findByNameLike(String name);
	public List<MyData> findByIdIsNotNullOrderByIdDesc();
	public List<MyData> findByAgeGreaterThan(Integer age);
	public List<MyData> findByAgeBetween(Integer age1, Integer age2);

}

** Toutes les recherches simples sont des méthodes générées automatiquement. Seul le traitement de recherche complexe est défini et utilisé dans DAO **

Validation d'entité

En préparant à l'avance la validation dans le modèle, des règles sont définies pour chaque élément d'entrée et il est possible de vérifier si la valeur d'entrée est violée. @ Validated Cela vérifiera la valeur de l'entité pour la variation. En ajoutant cela, chaque valeur de l'entité sera vérifiée automatiquement.

@ BindingResult Le résultat du contrôle de validation est reçu par l'argument suivant, BindingResult. Vous pouvez vérifier si une erreur s'est produite avec la méthode hasErrors. S'il est "vrai", il y a une erreur, et s'il est "faux", il n'y a pas d'erreur, donc dans le cas ci-dessous, le traitement (stockage de données, etc.) quand il n'y a pas d'erreur dans ʻif (! Result.hasErrors ()) `est effectué. ..

if(!result.hasErrors()) {...}

Message d'erreur de sortie

L'expression de variable est définie dans $ {# fields.detailedErrors ()} dans th: each est un objet qui résume les résultats des contrôles de validation de chaque champ de l'entité dans # fields, etdetailedErrors. La méthoderenvoie des informations sur l'erreur qui s'est produite sous forme de liste collective. Dans th: each, les objets d'erreur sont retirés de la liste et définis dans la variable ʻerror`.

<li th:each="error : ${#fields.detailedErrors}" class="err" th:text="${error.message}">

ʻError a une propriété appelée message, qui vous donne le message de l'erreur qui s'est produite. Il est affiché sous la forme th: text =" $ {error.message} "`.

【modèle】

<form method="post" action="/" th:object="${formModel}">
	<ul>
		<li th:each="error : ${#fields.detailedErrors()}"
			class="err" th:text="${error.message}" />
	</ul>
	<tr><td><label for="name">Nom</label></td>
		<td><input type="text" name="name" 
			th:field="*{name}" /></td></tr>
	<tr><td><label for="age">âge</label></td>
		<td><input type="text" name="age"
			th:field="*{age}" /></td></tr>
	<tr><td><label for="mail">Email</label></td>
		<td><input type="text" name="mail" 
				th:field="*{mail}" /></td></tr>
	<tr><td><label for="memo">Note</label></td>
		<td><textarea name="memo" th:field="*{memo}" 
			cols="20" rows="5" ></textarea></td></tr>
	<tr><td></td><td><input type="submit" /></td></tr>
</form>

【entité】

@Entity
@Table(name = "mydata")
public class MyData {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column
	@NotNull
	private long id;

	@Column(length = 50, nullable = false)
	@NotEmpty
	private String name;

	@Column(length = 200, nullable = true)
	@Email
	private String mail;

	@Column(nullable = true)
	@Min(0)
	@Max(200)
	private Integer age;

	@Column(nullable = true)
	private String memo;

	//…… Accessor omis ……
}

【manette】 Un exemple qui vérifie si la valeur d'entrée enfreint le jeu de validation dans l'entité et permet à la valeur d'être stockée uniquement lorsque la règle est satisfaite.

@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView index(
	@ModelAttribute("formModel") MyData mydata, 
		ModelAndView mav) {
	mav.setViewName("index");
	mav.addObject("msg","this is sample content.");
	mav.addObject("formModel",mydata);
	Iterable<MyData> list = repository.findAll();
	mav.addObject("datalist",list);
	return mav;
}

@RequestMapping(value = "/", method = RequestMethod.POST)
@Transactional(readOnly=false)
public ModelAndView form(
    @ModelAttribute("formModel") @Validated MyData mydata, 
    BindingResult result,
    ModelAndView mov) {

	ModelAndView res = null;
	if (!result.hasErrors()){
		repository.saveAndFlush(mydata);
		res = new ModelAndView("redirect:/");
	} else {
		mov.setViewName("index");
		mov.addObject("msg","sorry, error is occured...");
		Iterable<MyData> list = repository.findAll();
		mov.addObject("datalist",list);
		res = mov;
	}
	return res;
}

Afficher l'erreur dans chaque champ de saisie

<input type="text" name="name" th:value="*{name}" th:errorclass="err" />

La propriété name de l'objet prend la valeurth: value = "* {name}". Un attribut appelé «th: errorclass» est fourni pour spécifier le nom de classe à appliquer lorsqu'une erreur se produit. Le traitement est appliqué uniquement lorsqu'une erreur se produit à cause de cela.

<div th:if="${#fields.hasErrors('name')}" th:errors="*{name}" th:errorclass="err">

hasErrors utilise th: if pour afficher un doug uniquement lorsque true, qu'une erreur se soit produite ou non dans le champ spécifié dans l'argument.

Le message d'erreur est affiché en utilisant l'attribut th: errors, et dans l'exemple,` * {name} ʻest spécifié.

【modèle】

<form method="post" action="/" th:object="${formModel}">
		<tr><td><label for="name">Nom</label></td>
			<td><input type="text" name="name"
				th:value="*{name}" th:errorclass="err" />
			<div th:if="${#fields.hasErrors('name')}" 
				th:errors="*{name}" th:errorclass="err">
				</div></td></tr>
		<tr><td><label for="age">âge</label></td>
			<td><input type="text" name="age"
				th:value="*{age}" th:errorclass="err" />
			<div th:if="${#fields.hasErrors('age')}" 
				th:errors="*{age}" th:errorclass="err">
				</div></td></tr>
		<tr><td><label for="mail">Email</label></td>
			<td><input type="text" name="mail" 
				th:value="*{mail}" th:errorclass="err" />
			<div th:if="${#fields.hasErrors('mail')}" 
				th:errors="*{mail}" th:errorclass="err">
				</div></td></tr>
		<tr><td><label for="memo">Note</label></td>
			<td><textarea name="memo" th:text="*{memo}" 
				cols="20" rows="5" ></textarea></td></tr>
		<tr><td></td><td><input type="submit" /></td></tr>
	</form>

Annotation par javax.validation

Annotation de validation Contenu
@ Null Vérifiez que la valeur est nulle
@ NotNull Ne pas autoriser la valeur à être nulle
@ Min(int num) Spécifiez la valeur minimale qui peut être saisie dans l'élément pour saisir une valeur numérique (entier)
@ Max(int num) Spécifiez la valeur maximale qui peut être saisie dans l'élément pour saisir une valeur numérique (entier)
@ DecimalMin(String num) BigDecimal,BigInteger,Spécifier la valeur minimale lors de la définition de la valeur avec la valeur de chaîne int est également OK
@ DecimalMax(String num) BigDecimal,BigInteger,Spécifier la valeur maximale lors de la définition de la valeur avec la valeur de chaîne int est également OK
@ Degits(integer=5, fraction=10) Limitation du nombre de chiffres dans la partie entière et la partie fractionnaire
@ Future N'acceptez que les dates et heures futures du présent
@ Past N'acceptez que les routes passées du présent
@ Size(min=1, max=10) Spécifiez le nombre d'éléments stockés d'objets tels que des chaînes et des classes de collection en plus de String
@ Pattern(regexp="[a-zA-Z]+") Vérifiez l'entrée en spécifiant le modèle d'expression régulière

Annotation par HiberinateValidator

Annotation de validation Contenu
@ NotEmpty Les caractères nuls ou vides ne sont pas autorisés
@ Length(min=5, max=10) Une annotation qui spécifie la plage de longueurs de chaîne utilisée pour Stringt
@ Range Il est utilisé dans l'élément numérique pour spécifier la plage de la valeur minimale et de la valeur maximale.@Avec Min@Max peut être mis en place
@ Email Vérifiez si la valeur saisie est une adresse e-mail
@ CreditCardNumber Il est utilisé pour les éléments saisis numériquement sous forme de valeurs numériques ou de valeurs de chaîne pour vérifier si elles sont au format numérique Creca.
@ EAN Norme de numéro d'identification de code à barres

À propos du message d'erreur

Comment personnaliser le message d'erreur affiché en anglais Spécifiez le message d'affichage à l'aide de la valeur message lors de la préparation d'une annotation pour validation dans la classe d'entité

@NotEmpty(message="Pas de blancs")

@Email(message="Adresse e-mail uniquement")

@Min(value=0, message="Zéro ou supérieur")
@Max(value=200, message="200 ou moins")

Utilisation des fichiers de propriété

La maintenabilité étant médiocre dans le développement réel, les messages doivent être gérés en préparant un fichier de propriétés. Il peut être géré en créant un fichier texte avec le nom "ValidationMessages.properties" dans le dossier de ressources.

Créez votre propre validateur

Pour votre propre travail de Varidata

La classe d'annotation est Créez une classe de type d'annotation qui décrit le nom après @ interface La classe de validation est définie en implémentant l'interface javax.validation.ConstraintValidator. ConstraintValidator a deux méthodes, ʻinitialize et ʻisValid, et les implémente pour décrire le traitement nécessaire.

Méthode d'initialisation La classe d'annotation spécifiée par le type générique est passée en argument Obtenez des informations sur les annotations au besoin

La pièce à valider La valeur saisie (String) et l'instance ConstraintValidator sont passées en arguments. Vérifiez la valeur ici et renvoyez la valeur booléenne selon que la validation est correcte ou non.

[Classe d'annotation]

@Documented
@Constraint(validatedBy = PhoneValidator.class)
@Target({ ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@ReportAsSingleViolation
public @interface Phone {
  String message() default "Please input a phone number.";
  Class<?>[] groups() default {};
  Class<? extends Payload>[] payload() dedault {};
}

[Classe de validation]

public class PhoneValidator implements ConstraintValidator<Phone, String> {

  @Override
  public void initialize(Phone phone){
  }

  @Override
  public boolean isValid(String input, ConstraintValidatorContext cxt){
    if(input == null){
      return false;
    }
    return input.matches("[0-9()-]*");
  }

}

6. Plongez dans l'accès à la base de données

En préparant un référentiel, l'accès à la base de données est possible avec presque aucune écriture de code, mais il y a une limite, alors considérez comment utiliser la fonction d'accès à la base de données fournie par SpringDataJPA à partir de l'application Spring Boot.

DataAccessObject Lorsque vous utilisez DB, lorsque vous accédez à la page pour afficher les données, préparez le processus pour récupérer les données dans le gestionnaire de requêtes du contrôleur et les afficher dans la vue. En d'autres termes, préparez le traitement d'accès à la base de données nécessaire pour chaque gestionnaire de requêtes du contrôleur.

Si vous écrivez un processus pour chaque demande, le contrôleur deviendra gonflé, donc séparez l'accès aux données et la logique. Par conséquent, préparez un objet appelé DAO (Data Access Object) qui permet d'accéder à la base de données. Appelez-les depuis le contrôleur et effectuez le traitement nécessaire.

ʻEn préparant un champ pour stocker la classe EntityManager`, il fournit les fonctions requises pour utiliser l'entité.

Créer une requête avec createQuery

Query est un objet qui a une fonction équivalente à une seule phrase de requête pour interroger des données avec SQL. La requête JPQL est une instance Query Lorsque createQuery de EntityManager est appelé en spécifiant une phrase de requête par JPQL comme argument, une instance de requête pour exécuter la requête est générée. Qu'est-ce que l'exemple from MyData? Une phrase de requête JPQL équivalente à select * from mydata

Query query = entityManager.createQuery("from MyData");

Obtenir les résultats de la requête

La méthode getResultList de la requête créée vous permet d'obtenir le résultat de l'exécution en tant qu'instance dans la requête.

List<MyData> list = query.getResultList();

@ SuppressWarnings Dans l'exemple, l'annotation attachée à la variable list supprime l'avertissement au moment de la compilation. En utilisant «décroché» comme argument, il est vérifié si la valeur de retour de la méthode est obtenue comme valeur du type de la variable de destination de stockage. Cela n'a rien à voir avec le comportement lui-même, ** pour éviter les avertissements au moment de la construction **

@SuppressWarnings("unchecked")

[Interface DAO]

public interface MyDataDao <T> extends Serializable {	
	public List<T> getAll();	
}

[Classe d'implémentation DAO]

@Repository
public class MyDataDaoImpl implements MyDataDao<MyData> {
	private static final long serialVersionUID = 1L;
	
	private EntityManager entityManager;
	
	public MyDataDaoImpl(){
		super();
	}
	public MyDataDaoImpl(EntityManager manager){
		this();
		entityManager = manager;
	}
	
	@Override
	public List<MyData> getAll() {
		Query query = entityManager.createQuery("from MyData");
		@SuppressWarnings("unchecked")
		List<MyData> list = query.getResultList();
		entityManager.close();
		return list;
	}
	
}

Implémentation du contrôleur

Créez un contrôleur qui utilise une entité dans DAO.

@ PersistenceContext @ PersistenceContext récupère le Bean de ʻEntityManager et le définit dans le champ. Dans Spring Boot, ʻEntityManager est automatiquement enregistré en tant que bean, alors attribuez-le au champ du contrôleur avec @ PersistenceContext. La liaison de bean utilisant @ PersistenceContext ne peut être placée que jusqu'à" ** 1 instance par classe ** "

@PersistenceContext
EntityManager entityManager;

La liste est acquise à partir de l'entité via DAO et l'objet de liste est passé au côté modèle en même temps que la définition du nom de modèle de la vue. Si vous assemblez le processus d'accès pour l'entité dans DAO, vous pouvez facilement appeler le processus d'accès côté contrôleur.

Iterable<MyData> list = dao.getAll();
mav.addObject("datalist", list);
public class SampleController {
  //Dépôt
  @Autowired
  MyDataRepository repository;

  //entité
  @PersistenceContext
  EntityManager entityManager;

  // DAO
  MyDataDaoImpl dao;

  @PostConstruct
  public void init() {
    dao = new MyDataDaoImpl(entityManager);
    MyData md = new MyData():
    md.setHoge("fuga");
    md.setNumber(123);
    repository.saveAndFlush(md);
  }

  @RequestMapping(value = "/", method = RequestMethod.GET)
  public ModelAndView index() {
    mav.setViewName("index");
    mav.addObject("msg", "Ceci est un exemple de MyData.");
    Iterable<MyData> list = dao.getAll();
    mav.addObject("datalist", list);
    return mav;
  }
}

Ajouter une méthode de recherche à DAO

[Interface DAO]

public interface MyDataDao<T> extends Serializable {
	
    public List<T> getAll();
    //Recherche et renvoie une entité avec un ID comme argument
    public T findById(long id);
    //Rechercher et renvoyer une entité par son nom
    public List<T> findByName(String name);
}

[Classe d'implémentation DAO]

" from MyData where id = " -> Requête JPQL (récupère l'entité avec l'ID comme argument) getSingleResult récupère et retourne une seule entité obtenue à partir de Query Pour des choses comme ** une seule entité est recherchée ** (comme ID), il est préférable de renvoyer l'entité obtenue telle quelle plutôt que de la renvoyer sous forme de liste.

@Override
public MyData findById(long id) {
	return (MyData)entityManager.createQuery("from MyData where id = " 
		+ id).getSingleResult();
}

" from MyData where name = " -> Requête JPQL (récupère l'entité avec le nom comme argument) getResultList renvoie une liste, donc findByName aList <MyData>comme type de retour.

@SuppressWarnings("unchecked")
@Override
public List<MyData> findByName(String name) {
	return (List<MyData>)entityManager.createQuery("from MyData where name = " 
		+ name).getResultList();
}

Utilisez JPQL

JPQL est un langage simple qui permet à JPA de générer des requêtes SQL et d'exploiter des bases de données en exécutant des instructions de requête similaires aux requêtes SQL.

HttpServletRequest

Nous avons utilisé @ RequestParam comme argument lors de la réception et du traitement d'une valeur soumise, comme une méthode qui reçoit un formulaire avec POST, mais vous pouvez également utiliser HttpServletRequest comme argument. En fait, le paramètre de @ RequestParam est celui qui appelle getParameter de HttpServletRequest et effectue automatiquement l'opération pour recevoir le paramètre et définit le résultat comme un argument. HttpServletResponse peut également être spécifié comme argument

@RequestMapping(value = "/find", method = RequestMethod.POST)
public ModelAndView search(HttpServletRequest request,
		ModelAndView mav) {
	mav.setViewName("find");
	String param = request.getParameter("fstr");
	if (param == ""){
		mav = new ModelAndView("redirect:/find");
	} else {
		mav.addObject("title","Find result");
		mav.addObject("msg","「" + param + "Résultats de recherche");
		mav.addObject("value",param);
		List<MyData> list = dao.find(param);
		mav.addObject("datalist", list);
	}
	return mav;
}

Ajouter la méthode de recherche à DAO (utiliser le paramètre nommé)

Tout ce qui est écrit dans l'instruction de requête JPQL dans un format tel que : fstr dans la requête" " de MyData où id =: fstr " "est traité comme une ** variable de paramètre **. Le paramètre setParameter suivant de l'instance Query définit la valeur du deuxième argument sur la variable du premier argument et attribue la valeur au précédent: fstr pour créer une requête.   [Interface DAO]

public List<T> find(String fstr);

[Classe d'implémentation DAO]

@Override
public List<MyData> find(String fstr){
	List<MyData> list = null;
	String qstr = "from MyData where id = :fstr";
	Query query = entityManager.createQuery(qstr)
		.setParameter("fstr", Long.parseLong(fstr));
	list = query.getResultList();
	return list;
}

Vous pouvez intégrer n'importe quel nombre de paramètres multiples dans une requête

Vous pouvez définir plusieurs paramètres dans une requête en connectant setParameter (renvoyant une instance de requête avec des paramètres déjà définis) dans une chaîne de méthodes.

String qstr = "from MyData where id = :fid or name like :fname or mail like :fmail";
Long fid = 0L;
Query query =
    entityManager.createQuery(qstr).setParameter("fid", fid)
			.setParameter("fname", "%" + fstr + "%")
			.setParameter("fmail", fstr + "@%");

Paramètre de numérotation par "?"

Certaines variables de paramètres à incorporer dans la requête définissent leurs valeurs en spécifiant un nombre. Définissez l'intégration des paramètres en spécifiant un nombre après "**? **" comme "? 1`

String qstr = "from MyData where id = ?1 or name like ?2 or mail like ?3";
Long fid = 0L;
    Query query = entityManager.createQuery(qstr).setParameter(1, fid)
		.setParameter(2, "%" + fstr + "%")
		.setParameter(3, fstr + "@%");

Annotation de requête

Les requêtes nommées peuvent être créées en utilisant @ NamedQuery. Ajouter à la déclaration de classe d'entité Nommez et définissez la chaîne de requête

@Entity
@NamedQuery(
  name = "findWithName",
  query = "from MyData where name like :fname"
)
@Table(name = "mydata")
public class MyData {
  ...
}

Utilisez @ NamedQueries pour combiner plusieurs requêtes Vous pouvez ajouter @ NamedQuery autant de fois que vous le souhaitez, séparés par des virgules.

@NamedQueries (
    @NamedQuery(
        name="findWithName",
        query="from MyData where name like :fname"
    )
)

createNamedQuery obtient une requête avec ce nom en spécifiant le nom de l'annotation de requête dans le texte comme argument, et crée une instance Query. Placez la requête dans la classe d'entité, détachée du code DAO à l'aide d'une requête nommée -> Lorsqu'il s'agit de plusieurs entités, il est facile à comprendre en mettant des requêtes avec la même fonction dans chacune avec le même nom

Query query = entityManager
    .createQuery("findWithName")
    .setParameter("fname", "%" + fstr + "%");

Référentiel et @ Query

Puisqu'il est absurde de réécrire l'entité à chaque fois que la fonction de recherche est étendue, je souhaite préparer une requête du côté qui exécute réellement l'accès à la base de données. Les requêtes peuvent être déclarées avec @ Query dans l'interface qui sera le référentiel @ Query utilisera la requête spécifiée lors de l'appel de la méthode qui décrit l'annotation

@Repository
public interface MyDataRepository  extends JpaRepository<MyData, Long> {
	
	@Query("SELECT d FROM MyData d ORDER BY d.name")
	List<MyData> findAllOrderByName();
}

Essayez d'appeler le référentiel pour exécuter la requête à partir du contrôleur Il n'y a pas de différence interne car le lieu de préparation de la requête est DAO ou le référentiel.

@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView index(ModelAndView mav) {
	mav.setViewName("index");
	mav.addObject("title","Find Page");
	mav.addObject("msg","Ceci est un exemple de MyData.");
	Iterable<MyData> list = repository.findAllOrderByName(); //dao.getAll();
	mav.addObject("datalist", list);
	return mav;
}

@ Paramètres NamedQuery

Si vous souhaitez effectuer une recherche détaillée, vous devrez inclure la valeur de la condition de recherche dans la requête. Dans ce cas, les paramètres peuvent être préparés dans le texte de requête défini dans l'annotation de requête.

@NamedQuery (
    name = "findByAge",
    query = "from MyData where age > :min and age < :max"
)

Préparez @ NamedQuery de cette manière avant la classe d'entité et appelez-la depuis DAO en transmettant la valeur au paramètre intégré dans la requête. Essayez d'appeler findByAge depuis DAO Pour créer une instance Query, utilisez createNamedQuery comme argument et spécifiez le nom de la requête. Utilisez ensuite setParameter pour passer la valeur au paramètre du texte de requête préparé dans @ NamedQuery. Recherchez ensuite l'entité avec getResultList

public List<MyData> findByAge(int min, int max);
@suppresswarning
@Override
public List<MyData> findByAge(int min, int max) {
    return (List<MyData>) entityManager
        .createNamedQuery("findByAge")
        .setParameter("min", min)
        .setParameter("max", max)
        .getResultList();
}

Utilisez @Query

Lorsque vous utilisez @ Query, la méthode pour incorporer une variable dans le texte de la requête et la spécifier avec l'argument de la méthode est la même. Cependant, utilisez @ Param pour spécifier quelle variable est associée à quel paramètre Vous trouverez ci-dessous un exemple lorsque le findByAge ajouté à @ NamedQuery est imprimé dans le référentiel.   [Interface du référentiel]

@Query("from MyData where age > :min and age < :max")
public List<MyData> findByAge(@Param("min") int min, @Param("max") int max);

Le fait d'avoir la requête dans l'entité elle-même ou de la préparer dans le référentiel dépend de la conception de l'application.

Recherche par API de critères

Il existe également une fonction pour accéder à la base de données par chaîne de méthodes sans utiliser un langage comme JPQL-> Criteria API L'API Criteria utilise une combinaison de trois classes

classe Ce que tu peux faire
CriteriaBuilder Gérer la génération de requêtes
CriteriaQuery Exécution de la requête
Root Vous pouvez restreindre les entités d'ici par la racine de l'entité recherchée

① Acquisition de Criteria Builder Préparez une instance de CriteriaBuilder et appelez ʻEntityManager # getCriteriaBuilder`

CriteriaBuilder builder = entityManager.getCriteriaBuilder();

② Création de requêtes de critères Ne prenez pas une instruction de requête comme argument Spécifiez la propriété de classe d'une entité spécifique comme argument pour accéder à cette entité

CriteriaQuery <Entity> query = builder.createQuery(Entity.class);

③ Acquisition de Root Obtenir la racine avec la méthode from de CriteriaQuery Spécifiez la propriété Class de l'entité à rechercher dans l'argument

Root <Entity> root = query.from(Entity.class);

④ Exécution de la méthode CriteriaQuery Appel d'une méthode pour restreindre les entités avec CriteriaQuery Appelez une chaîne de méthodes au besoin

query.select(root);

⑤ Créez une requête pour obtenir le résultat Enfin, générez une requête avec createQuery et obtenez le résultat List avec getResultList. Spécifier QriteriaQuery comme argument de createQuery est différent du traitement de la recherche par une requête normale.

List<Entity> list = (List<MyData>)entityManager
    .createQuery(query)
    .getResultList();
return list;

Voici un exemple pour obtenir toutes les entités par la méthode getAll.

Spécifiez MyData.class comme argument de la méthode from pour obtenir la racine Vous pouvez obtenir une instance racine qui contient toutes les données MyData comme informations Après avoir obtenu la racine, pour obtenir toutes mes données, appelez avec CriteriaQuery # select comme argument et spécifiez MyData.class. Après cela, si vous createQuery this CriteriaQuery et getResult, vous pouvez obtenir tous les Mydata.

@Override
public List<MyData> getAll() {
	List<MyData> list = null;		
	CriteriaBuilder builder = 
			entityManager.getCriteriaBuilder();
	CriteriaQuery<MyData> query = 
			builder.createQuery(MyData.class);
	Root<MyData> root = query.from(MyData.class);
	query.select(root);
	list = (List<MyData>)entityManager
			.createQuery(query)
			.getResultList();
	return list;
}

Recherche de nom à l'aide de l'API Criteria

Seules les entités dont le texte d'argument et la valeur de nom correspondent sont recherchées. Après avoir acquis l'instance racine, effectuez un traitement pour restreindre les entités à récupérer.   Après select (root), utilisez la chaîne de méthodes pour affiner les entités en utilisant la méthode where avec Expression (qui gère l'évaluation de diverses expressions) comme argument. Méthode ʻEqual Vérifie s'ils sont égaux par l'expression et l'objet spécifiés dans l'argument, et retourne le résultat comme une instance de la classe Predicate. Puisque Predicate a le rôle d'exprimer les conditions et les expressions spécifiées dans la méthode en tant qu'objets, par exemple, dans le cas de ʻequal, Predicate indiquant les conditions qui sont les mêmes que celles spécifiées dans l'argument est préparé, et les entités qui correspondent aux conditions sont réduites.

// where(Expression<boolen>)
// equal(Expression, Object)
query.select(root)
		.where(builder.equal(root.get("name"), fstr));

Méthodes CriteriaBuilder

Méthode Format La description
equal equal(Expression x, Expression y) Créez un prédicat pour vérifier que les arguments sont égaux.
gt gt(Expression<? extends java.lang.Number> x, Expression<? extends java.lang.Number> y) Créez un prédicat pour vérifier si le premier argument est supérieur au deuxième argument.
greaterThan greaterThan(Expression<? extends Y> x, Expression<? extends Y> y) Créez un prédicat pour vérifier si le premier argument est supérieur au deuxième argument.
ge ge(Expression<? extends java.lang.Number> x, Expression<? extends java.lang.Number> y) Créez un prédicat pour vérifier si le premier argument est supérieur ou égal au second.
greaterThanOrEqualTo greaterThanOrEqualTo(Expression<? extends Y> x, Expression<? extends Y> y) Créez un prédicat pour vérifier si le premier argument est supérieur ou égal au second.
lt lt(Expression<? extends java.lang.Number> x, Expression<? extends java.lang.Number> y) Créez un prédicat pour vérifier si le premier argument est inférieur au second.
lessThan Predicate lessThan(Expression<? extends Y> x, Y y)
le le(Expression<? extends java.lang.Number> x, java.lang.Number y) Créez un prédicat pour vérifier si le premier argument est inférieur ou égal au deuxième argument.
lessThanOrEqualTo lessThanOrEqualTo(Expression<? extends Y> x, Y y) Créez un prédicat pour vérifier si le premier argument est inférieur ou égal au deuxième argument.
between between(Expression<? extends Y> v, Expression<? extends Y> x, Expression<? extends Y> y) Créez un prédicat pour vérifier que le premier argument est une valeur entre les deuxième et troisième arguments.
isNull isNull(Expression<?> x) Créez un prédicat qui vérifie si l'expression est nulle.
isNotNull isNotNull(Expression<?> x) Créez un prédicat qui vérifie si l'expression n'est pas nulle.
isEmpty isEmpty(Expression collection) Créez un prédicat pour vérifier si la collection est vide.
isNotEmpty isNotEmpty(Expression collection) Créez un prédicat pour vérifier que la collection n'est pas vide.
like like(Expression<java.lang.String> x, Expression<java.lang.String> pattern) Créez un prédicat qui vérifie si l'expression satisfait le modèle donné.
and and(Expression<java.lang.Boolean> x, Expression<java.lang.Boolean> y) Crée le produit logique d'une expression booléenne donnée.
or or(Expression<java.lang.Boolean> x, Expression<java.lang.Boolean> y) Crée la somme logique des expressions booléennes données.
not not(Expression<java.lang.Boolean> restriction) Refusez la limitation donnée.

Tri des entités par orderBy

Le résultat récupéré utilise la méthode ʻorderBy pour obtenir l'entité en tant que List L'argument ʻExpression utilise CriteriaBuilder # get pour spécifier le chemin qui indique la propriété de l'entité. L'argument de ʻorderBy` dans les ensembles d'exemples Predicate pour trier les éléments de nom par ordre croissant.

query.select(root).orderBy(builder.asc(root.get("name")));

Définition de la position d'acquisition et du nombre d'acquisitions

La méthode get de l'entité de la requête est [getSingleResult](ajoute une méthode de recherche à ### DAO) qui ne renvoie qu'une seule entité et [getResultList](### obtient le résultat de Query) qui renvoie toutes les entités sous forme de liste. y a-t-il Lorsque vous utilisez réellement le DB, vous pouvez également spécifier la position et le numéro pour l'obtenir.

Spécifiez une valeur entière pour l'argument La position d'acquisition commence par 0 dans la liste.

 query.setFirstResult(int pos);

Spécifiez le numéro à acquérir Seul le nombre maximum pouvant être obtenu est défini, donc s'il n'y a pas assez d'entités, seules certaines seront récupérées.

@Override
public List<MyData> getAll() {
	int offset = 1; //Spécifier la position d'extraction
	int limit = 2;  //Précisez le numéro à retirer
	List<MyData> list = null;
	CriteriaBuilder builder = 
			entityManager.getCriteriaBuilder();
	CriteriaQuery<MyData> query = 
			builder.createQuery(MyData.class);
	Root<MyData> root = 
			query.from(MyData.class);
	query.select(root);
	list = (List<MyData>)entityManager
			.createQuery(query)
			.setFirstResult(offset)
			.setMaxResults(limit)
			.getResultList();
	return list;
}

Intégration d'entité

Dans une base de données où plusieurs tables fonctionnent les unes par rapport aux autres, les entités sont liées et traitées par une fonction appelée «association». -> Avoir une autre entité comme propriété de la classe

@ OneToOne Indique une correspondance biunivoque entre deux entités @ OneToMany Le multiple de l'autre entité correspond à une entité @ ManyToOne Pour plusieurs entités, une seule des autres entités correspond @ ManyToMany Relations dans lesquelles plusieurs autres entités correspondent à plusieurs entités

L'exemple MsgData permet à un membre de publier n'importe quel nombre de messages, donc Associé à MyData dans @ ManyToOne

[Entité associée]

@Entity
@Table(name = "msgdata")
@Getter
@Setter
public class MsgData {
  @Id
  @Column
  @NotNull
  private long id;

  @Column
  private String title;

  @Column(nullable = false)
  @NotEmpty
  private String message;

  @ManyToOne
  private MyData mydata;

  //Ci-dessous, le constructeur et l'accesseur sont omis.
}

[Entité associée] Ajouter la propriété msgdatas à associer à MsgData

@Entity
@Table(name = "mydata")
@Getter
@Setter
public class MyData {
  @OneToMany(cascade = CascadeType.ALL)
  @Column(nullable = true)
  private List<MsgData> msgdatas;
}

Dans le référentiel «save», lors de l'enregistrement, s'il y a un champ associé à une autre entité, l'instance est acquise en fonction des informations envoyées et définie automatiquement. Par conséquent, il n'est pas nécessaire que le programmeur mette en œuvre le processus d'enregistrement des enregistrements associés en tenant compte de la coopération des entités.

repository.saveAndFlush(msgdata);

<Points de coopération des entités>

7. Utilisez davantage Spring Boot

Qu'est-ce qu'un service?

En logique métier, la partie qui est mise en composants pour pouvoir y accéder depuis l'application est généralement appelée «** couche de service **», et contrairement à DAO qui utilise des contrôleurs et des modèles, c'est une classe qui peut être appelée et utilisée de n'importe où.

Ce qui peut être librement appelé à la fois à partir du contrôleur et de la logique métier (modèle) est ** service **

Spring Framework peut être utilisé à tout moment en enregistrant simplement ce service en tant que bean et en écrivant des annotations.

○ Couche d'application
·manette
Gestionnaire de demande
·modèle
Logique métier
entité
○ Couche de domaine
·un service
・ Dépôt

@ Service Une annotation pour enregistrer cette classe en tant que service, et la classe de service place cette annotation avant le nom de la classe.

@ PersisitenceContext C'est pour assigner automatiquement le Bean de ʻEntityManager, et il est également possible de préparer et d'utiliser ʻEntityManager dans le service plutôt que du côté de la classe du contrôleur.

@Service
public class MyDataService {

	@PersistenceContext
	private EntityManager entityManager;

	@SuppressWarnings("unchecked")
	public List<MyData> getAll() {
		return (List<MyData>) entityManager
			.createQuery("from MyData").getResultList();
	}

	public MyData get(int num) {
		return (MyData)entityManager
				.createQuery("from MyData where id = " + num)
				.getSingleResult();
	}

	public List<MyData> find(String fstr) {
		CriteriaBuilder builder = entityManager.getCriteriaBuilder();
		CriteriaQuery<MyData> query = builder.createQuery(MyData.class);
		Root<MyData> root = query.from(MyData.class);
		query.select(root).where(builder.equal(root.get("name"), fstr));
		List<MyData> list = null;
		list = (List<MyData>) entityManager.createQuery(query).getResultList();
		return list;
	}

}

Utiliser le bean service dans le contrôleur

Accès à la base de données depuis DAO à l'aide du bean de service Utiliser le service créé comme un bean avec @ Autowired en association avec le contrôleur

La classe de service dans laquelle «@ Service» est décrit est beanisée dans l'application et affectée au champ par «@ Autowired».

@Controller
public class SampleController  {

	@Autowired
	MyDataRepository repository;

        //Associer un bean de service à un champ
	@Autowired
	private MyDataService service;
	
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public ModelAndView index(ModelAndView mav) {
		mav.setViewName("index");
		mav.addObject("title","Find Page");
		mav.addObject("msg","Ceci est un exemple de MyData.");
                //Obtenez toutes les entités
		List<MyData> list = service.getAll(); 
		mav.addObject("datalist", list);
		return mav;
	}

        // "/find"GET gestionnaire de requêtes omis

        @RequestMapping(value = "/find", method = RequestMethod.POST)
        public ModelAndView search(HttpServletRequest request,
            ModelAndView mav) {
        mav.setViewName("find");
        String param = request.getParameter("fstr");
        if(param == "") {
            mav = new ModelAndView("redirect:/find");
        } else {
            mav.addObject("title", "Find result");
            mav.addObject("msg", "「" + param + "Résultats de recherche");
            mav.addObject("value", param);
            //Rechercher des entités
            List<MyData> list = service.find(param);
            mav.addObject("datalist", list);
        }
        return mav;
    }
    
    //Le constructeur, l'accesseur, etc. sont omis ci-dessous.

}

Créer un RestController

"** Service " dans le développement d'applications Web signifie généralement " Programme Web accessible de l'extérieur et recevant les informations nécessaires **" Il existe des services REST au format JSON et au format XML qui peuvent être utilisés de l'extérieur.

@RestController
public class MyDataRestController {

	@Autowired
	private MyDataService service;

	@RequestMapping("/rest")
	public List<MyData> restAll() {
		return service.getAll();
	}

	@RequestMapping("/rest/{num}")
	public MyData restBy(@PathVariable int num) {
		return service.get(num);
	}
}

Obtenir des données en XML

Lors de la manipulation avec XML dans RestController, préparez une bibliothèque "Jackson DataFormat XML" qui analyse et traite le format des données.

@ XmlRootElement Indique qu'il s'agit de l'élément racine des données XML. Request handler restAll La seule différence est qu'il renvoie l'objet avec ʻou restByet est normalement converti au format JSON, et si@ XmlRootElement` est attaché, il est converti au format XML. Si vous utilisez Maven

pom.xml


<dependency>
	<groupId>com.fasterxml.jackson.dataformat</groupId>
	<artifactId>jackson-dataformat-xml</artifactId>
</dependency>

Composants et haricots

** Les composants ** sont des beans générés automatiquement dans votre application, et les instances de bean peuvent être utilisées en liant avec @ Autowired. Un service est un type de composant-> un composant de la couche service est appelé un ** service **

@ Component Les annotations font connaître la classe à laquelle elle est attachée à l'application en tant que composant. Les instances de classe seront désormais enregistrées en tant que beans

@ Constructeur Autowired

Si le constructeur a @ Autowired attaché, le constructeur avec this @ Autowired créera l'instance lorsque l'instance de cette classe est enregistrée en tant que bean. Si le constructeur avec @ Autowired n'est pas préparé dans la classe de composant, une erreur se produira lors de l'exécution de l'application et le démarrage échouera, alors assurez-vous de le préparer.

L'argument d'instance de MySampleBean (ApplicationArguments args) est un objet qui gère l'argument passé lorsque l'application est exécutée, c'est-à-dire lorsque SpringApplication.run est exécuté dans la classe avec @ SpringBootApplication spécifié. Préparez cette instance en tant qu'argument lors de l'utilisation de l'argument passé à l'exécution Dans l'exemple de méthode, utilisez ʻApplicationArgments # getNonOptionArgs pour extraire l'argument d'exécution de l'application en tant que List`.

@Component
public class MySampleBean {

	private int max = 10;

	@Autowired
	public MySampleBean(ApplicationArguments args) {
		List<String> files = args.getNonOptionArgs();
		try {
			max = Integer.parseInt(files.get(0));
		} catch (NumberFormatException e) {
			e.printStackTrace();
		}
	}
        
        public int count() {
		counter++;
		counter = counter > max ? 0 : counter;
		return counter;
	}
}

Utilisation de composants

Ajouter un gestionnaire de requêtes à la classe de contrôleur pour tirer parti du composant Si vous l'associez à un champ avec @ Autowired, il sera automatiquement lié, vous pouvez donc exécuter bean.count dans le gestionnaire de requêtes. Les composants peuvent être librement utilisés de n'importe où en les associant à des champs avec @ Autowired. S'il y a une fonction à usage général à appeler à partir de plusieurs gestionnaires de requêtes, il est bon de la résumer pour le moment

@Autowired
MySampleBean bean;

@RequestMapping("/count")
public int count() {
	return bean.count();
}

De plus, «@ Controller» est un composant qui joue le rôle d'un contrôleur, «@ Repository» est un type de composant auquel un rôle spécial est attribué pour l'accès aux données, et «@ Component» a un tel rôle spécial. Peut être attaché à quelque chose qui ne l'est pas

Autres fonctionnalités à retenir

Dans Spring, vous pouvez lier un bean préparé en standard à l'aide d'une annotation telle que @ Autowired, ou créer votre propre ** composant ** ou ** service ** et l'utiliser comme un bean. Les beans peuvent être utilisés à divers endroits tels que les contrôleurs en utilisant la ** classe de configuration ** En fait, en raison de l'idée de Spring Boot de ** du fichier de configuration à l'annotation **, la méthode de ** création d'un fichier de configuration ** n'est pas recommandée.

Créer une classe de configuration

Si vous ajoutez @ Configuration même à une classe générale qui n'hérite pas d'une classe spéciale, cette classe sera instanciée en tant que classe de configuration au démarrage de l'application, et les beans etc. qui y sont décrits seront enregistrés dans l'application.

[Classe de configuration avec des beans enregistrés dans le champ]

@Configuration
public class MyBootAppConfig {

	@Bean
	MyDataBean myDataBean(){
		return new MyDataBean();
	}
}

Si vous préparez une méthode qui retourne une instance de la classe avec @ Bean dans la classe de configuration, elle sera enregistrée en tant que bean.

[Classe Bean d'origine]

public class MyDataBean {
	
	@Autowired
	MyDataRepository repository;
	
	public String getTableTagById(Long id){
		Optional<MyData> opt = repository.findById(id);
		MyData data = opt.get();
		String result = "<tr><td>" + data.getName()
				+ "</td><td>" + data.getMail() + 
				"</td><td>" + data.getAge() + 
				"</td><td>" + data.getMemo() + 
				"</td></tr>";
		return result;
	}

}

Si vous faites @ Autowired pendant que le bean est préparé dans l'application, l'instance sera automatiquement liée.

[Contrôleur associé au champ pour utiliser le bean]

@Autowired
MyDataBean myDataBean;

@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public ModelAndView indexById(@PathVariable long id,
		ModelAndView mav) {
	mav.setViewName("pickup");
	mav.addObject("title","Pickup Page");
	String table = "<table>"
			+ myDataBean.getTableTagById(id)
			+ "</table>";
	mav.addObject("msg","pickup data id = " + id);
	mav.addObject("data",table);
	return mav;
}

Pagination

Spring Framework fournit une classe ** Page ** pour la division de page, qui peut être utilisée pour réaliser la nation de page, qui est une fonction qui gère les données pour chaque page.

En spécifiant des paramètres, vous pouvez spécifier le nombre d'enregistrements sur la page et le numéro de page à afficher (exemple de 2 données / page, qui est la 0ème page).

【Comment accéder】

/page?size=2&page=0

La méthode findAll, qui est un gestionnaire de requêtes, prend unPagable comme argument, récupère une instance de Page et la transmet au modèle avec le nom datalist.

[Contrôleur avec gestionnaire de requêtes qui implémente la pagination]

@RequestMapping(value = "/page", method = RequestMethod.GET)
public ModelAndView index(ModelAndView mav, Pageable pageable) {
	mav.setViewName("index");
	mav.addObject("title","Find Page");
	mav.addObject("msg","Ceci est un exemple de MyData.");
	Page<MyData> list = repository.findAll(pageable); //●
	mav.addObject("datalist", list);
	return mav;
}

Puisque «Page» est une sous-classe de «List», l'entité passée au modèle peut être affichée dans le tableau de la même manière que «List».

【modèle】

<table>
<tr><th>ID</th><th>Nom</th><th>Email</th><th>âge</th><th>Note(tel)</th></tr>
<tr th:each="obj : ${datalist}">
	<td th:text="${obj.id}"></td>
	<td th:text="${obj.name}"></td>
	<td th:text="${obj.mail}"></td>
	<td th:text="${obj.age}"></td>
	<td th:text="${obj.memo}"></td>
</tr>
</table>

Méthodes de classe paginables

Méthode revenir
Pageable#getPageNumber() Numéro de la page actuelle
Pageable#getPageSize() Nombre d'enregistrements à afficher sur la page
Pageable#first() Première pageable
Pageable#previousOrFirst() Précédent ou premier pageable
Pageable#next() Suivant Pageable

Création de balises originales Thymeleaf

Si vous prenez une entité distincte par pagination, vous devez vous déplacer vers l'avant et l'arrière de la page et préparer les fonctions liées à l'affichage de la page, définissez-la comme une classe Java à l'aide de ** l'objet utilitaire ** Vous pouvez appeler la méthode interne depuis Thymeleaf pour afficher le résultat. Pour utiliser des objets utilitaires, préparez une classe ʻAttributeTagProcessor qui traite les attributs Thymeleaf et une classeDialectpour combiner cette classe.   Lorsqueth: text =" name "" et l'attribut unique de Thymeleaf sont décrits, la valeur "name" est reçue et traitée comme le traitement de l'attribut appelé text, préparez donc le traitement spécifique.

«Un constructeur et« doProcess »sont fournis dans la classe créée en héritant de AbstractAttributeTagProcessor». Les arguments passés à cette méthode sont les suivants

Type d'argument La description
ITemplatecontext Gérez le contexte du modèle. Extrayez les informations de modèle telles que le moteur de modèle et les informations de configuration à partir d'ici.
IProcessableElementTag Les informations telles que les attributs incorporés dans les balises peuvent être récupérées dans les classes qui gèrent les balises d'élément.
AttributeName Gère les noms d'attributs et les préfixes (texte qui précède les valeurs)
String Valeur d'attribut
IElementTagStructureHandler Une classe qui gère des structures telles que l'incorporation d'attributs dans des éléments

Lorsqu'une expression de variable Thymeleaf etc. est décrite dans la valeur Traitez l'expression de variable à l'aide de la fonction d'évaluation de valeur ** résolveur ** intégrée au moteur de modèle pour obtenir la valeur résultante. Puisqu'il est nécessaire d'effectuer un traitement d'attribut réel, l'exemple ci-dessous est exécuté avec doProcess

[Classe d'héritage AbstractAttributeTagProcessor]

public class MyPageAttributeTagProcessor extends AbstractAttributeTagProcessor {
	
	private static final String ATTR_NAME = "mypage";
	private static final int PRECEDENCE = 10000;
	public static int size = 2;

	public MyPageAttributeTagProcessor(final String dialectPrefix) {
		super(TemplateMode.HTML, dialectPrefix, null,
				false, ATTR_NAME, true, PRECEDENCE, true);
    }
	 
	protected MyPageAttributeTagProcessor(TemplateMode templateMode, 
			String dialectPrefix, String elementName,
			boolean prefixElementName, 
			String attributeName, 
			boolean prefixAttributeName, 
			int precedence,
			boolean removeAttribute) {
		super(templateMode, dialectPrefix, elementName, 
				prefixElementName, attributeName, prefixAttributeName, 
				precedence,removeAttribute);
	}

	@Override
	protected void doProcess(ITemplateContext context, 
			IProcessableElementTag tag, 
			AttributeName attrName, 
			String attrValue,
			IElementTagStructureHandler handler) {
		
		final IEngineConfiguration configuration = context.getConfiguration();
		final IStandardExpressionParser parser =
				StandardExpressions.getExpressionParser(configuration);
		final IStandardExpression expression = 
				parser.parseExpression(context, attrValue);
		int value = (int)expression.execute(context);
		value = value < 0 ? 0 : value;
		handler.setAttribute("href", "/page?size=" + size + "&page=" + value);
	}

}

ʻAbstractProcessorDialect a une méthode appelée getProcessors qui obtient un ensemble qui résume ʻIProcessor. ʻIProcessorest une classe qui traite des choses telles que les attributs Thymeleaf. L'exemple crée une instanceSet, incorpore le ʻI Processor et effectue un processus de retour.

[Collecter comme attributs en tant que classe Dialect]

public class MyDialect extends AbstractProcessorDialect {
	
	private static final String DIALECT_NAME = "My Dialect";
	
	public MyDialect() {
		super(DIALECT_NAME, "my", StandardDialect.PROCESSOR_PRECEDENCE);
	}
	protected MyDialect(String name, String prefix, 
			int processorPrecedence) {
		super(name, prefix, processorPrecedence);
	}

	@Override
	public Set<IProcessor> getProcessors(String dialectPrefix) {
		final Set<IProcessor> processors = new HashSet<IProcessor>();
		processors.add(new MyPageAttributeTagProcessor(dialectPrefix));
		return processors;
	}

}

Enregistrez et utilisez Bean pour utiliser ʻAttributeTagProcessor etDialect`

① Créer un moteur de modèle

Après avoir créé l'instance SpringTemplateEngine, définissez le résolveur de modèle avec setTemplateResolver. Ceci définit le résolveur de modèle créé par templateResolver Incorporez l'instance MyDialect créée dans le moteur de modèle préparé avec ʻaddDialect, et lorsque le moteur de modèle revient`, il sera utilisé pour le rendu.

② Créer un templateResolver

Créez une instance de ClassLoaderTemplateResolver et définissez le préfixe, définissez s'il faut activer la mise en cache, définir le suffixe, définir le mode modèle, etc.

[Classe de structure]

@Configuration
public class MyBootAppConfig {

	...

    @Bean
	public ClassLoaderTemplateResolver templateResolver() {
		ClassLoaderTemplateResolver templateResolver = 
			new ClassLoaderTemplateResolver();
		templateResolver.setPrefix("templates/");
		templateResolver.setCacheable(false);
		templateResolver.setSuffix(".html");        
		templateResolver.setTemplateMode("HTML5");
		templateResolver.setCharacterEncoding("UTF-8");
		return templateResolver;
	}
 
	@Bean
	public SpringTemplateEngine templateEngine(){
		SpringTemplateEngine templateEngine = new SpringTemplateEngine();
		templateEngine.setTemplateResolver(templateResolver());
		templateEngine.addDialect(new MyDialect());
		return templateEngine;
	}
}

【modèle】

<div>
<a my:mypage="${datalist.getNumber() - 1}">&lt;&lt;prev</a>
|
<a my:mypage="${datalist.getNumber() + 1}">next&gt;&gt;</a>
</div>

Utilisation de MongoDB

L'utilisation de base de NoSQL MongoDB est presque la même que celle de la base de données SQL car MongoRepository est conçu de la même manière que JpaRepository-> ** Write and call repository **

8. Référence SpringToolSuite

Omis

référence

Recommended Posts

Aide-mémoire Spring Boot2
Aide-mémoire JMeter
Défi Spring Boot
Forme de botte de printemps
Aide-mémoire de Kotlin
Spring Boot Rappelez-vous
gae + botte à ressort
[Aide-mémoire Docker]
Aide-mémoire Mockito + PowerMock
Fiche d'apprentissage SPRING BOOT 01
Botte de printemps + Heroku Postgres
Rédaction de mémo de démarrage de printemps (1)
Fiche technique des collections Eclipse
Fiche technique du didacticiel Rails
Première botte à ressort (DI)
Fiche d'apprentissage SPRING BOOT 02
Gestion des exceptions Spring Boot
Mappage du servlet Spring Boot
Environnement de développement-développement Spring Boot-
Procédure d'apprentissage Spring Boot
Aide-mémoire pour la notation SCSS
Apprentissage de Spring Boot [Début]
Rédaction de mémos de démarrage de printemps (2)
Résumé du document Spring Boot 2.2
[Spring Boot] DataSourceProperties $ DataSourceBeanCreationException
Disponibilité de l'application Spring Boot 2.3
Tutoriels Spring Boot Sujets
Aide-mémoire de la commande Docker
Télécharger avec Spring Boot
[Spring Boot] Construction de l'environnement (macOS)
Essayez Spring Boot de 0 à 100.
Générer un code à barres avec Spring Boot
Hello World avec Spring Boot
Spring Boot sur Microsoft Azure
Implémenter GraphQL avec Spring Boot
Calendrier des tâches du didacticiel Spring Boot
Spring 5 et Spring Boot 2 Procédure de préparation pratique
Démarrez avec Spring Boot
Multi-projets Spring Boot 2 avec Gradle
[Spring Boot] Création d'applications Web
Exécutez LIFF avec Spring Boot
Connexion SNS avec Spring Boot
Paramètres d'échange à chaud Spring Boot
[Java] Thymeleaf Basic (Spring Boot)
Introduction à Spring Boot ① ~ DI ~
Téléchargement de fichiers avec Spring Boot
Spring Boot commençant par copie
[Eclipse] Aide-mémoire sur les touches de raccourci
Introduction à Spring Boot ② ~ AOP ~
Application Java CICS-Run - (4) Application Spring Boot
Spring Boot à partir de Docker
Spring Boot + Springfox springfox-boot-starter 3.0.0 Utilisation
Conseils relatifs à Spring Boot DB
Hello World avec Spring Boot
Définir des cookies avec Spring Boot
[Spring Boot] Recette de processus de pagination facile
Utiliser Spring JDBC avec Spring Boot
Construction de l'environnement Docker × Spring Boot
Changements majeurs dans Spring Boot 1.5