[JAVA] Résumer les principaux points de démarrage avec JPA appris avec Hibernate

1. Motivation

La société développe des applications Web utilisant le framework struts2. Cette application utilise Hibernate au lieu de JDBC pour l'accès à la base de données, mais j'étais en difficulté car je n'avais aucune connaissance. Pendant ce temps, je suis tombé sur les bons livres suivants, j'ai donc compris le contenu et résumé les principaux points.

--Introduction à JPA pour l'accès aux bases de données appris avec Seasar2 et Hibernate Écrit par Toshihiro Nakamura, publié par Mainichi Communications

2. Mots clés qui apparaissent

3. Glossaire

a. Mappage O / R

Associez un objet Java (Object) aux données d'une base de données relationnelle (Relationnelle). Une caractéristique majeure de JPA est qu'il dispose d'une fonction de mappage O / R. D'autre part, JDBC (*) doit programmer l'association entre les objets et DB. (Le programme devient compliqué.)


b. JPA(Java Persistence API) API incluse dans Java EE (*). JPA n'est qu'une spécification, et il existe plusieurs produits qui implémentent JPA, et les représentants sont Hibernate, TopLink Essentials et Open JPA. Aspect environnemental: peut être utilisé avec Java EE et Java SE. JDK 5.0 ou supérieur est requis.


c. Hibernate

Une implémentation JPA open source fournie par Red Hat. Pour utiliser Hibernate comme une implémentation JPA, vous avez besoin de trois produits: Hibernate Core, Hibernate Annotations et Hibernate Entity Manager. Par rapport à JDBC, les 4 processus suivants sont inutiles. (Les détails seront décrits plus tard)

4. Comment mettre en œuvre l'acquisition / la mise à jour / l'ajout / la suppression de données

JPA associe une table à une classe Java par mappage O / R et traite un enregistrement de la table comme une instance de la classe Java. Cette fois. Les classes Java sont appelées ** classes d'entité **, leurs instances sont appelées ** entités ** et les entités sont gérées via ** EntityManager **.

Lorsqu'une application demande à obtenir une entité, EntityManager vérifie d'abord si elle est mise en cache dans le contexte de persistance et renvoie l'entité mise en cache si elle existe.

L'image ressemble à ceci.

画像1.png

a. Acquisition de données

Il existe deux types de méthodes d'acquisition d'entités: l'acquisition de clé primaire (1) et l'acquisition de JPQL (2).

(1) Acquisition par entité

Pour obtenir une entité avec une clé primaire, utilisez la méthode *** find d'EntityManager ***.

article La description
argument Passez la classe d'entité comme premier argument et la valeur de clé primaire comme deuxième argument
Valeur de retour Si une entité existe, cette entité.
Null s'il n'existe pas
public void findById() throws Exception{
	// EntityManager(em)Est injecté avec DI
	//Obtenez l'enregistrement (entité) dont la clé primaire de la classe Emp (table) est "1"
	Emp emp = em.find(Emp.class, 1L);
}
(2) Acquisition par JPQL

Dans le cas où l'entité n'est pas acquise en spécifiant la clé primaire, la méthode find d'EntityManager ne peut pas être utilisée, et il est nécessaire de l'implémenter dans JPQL. JPQL est le propre langage de requête de JPA et est complètement différent de SQL. Dans JPQL, vous pouvez créer un objet Query en passant un argument à la *** méthode createQuery *** d'EntityManager. Vous pouvez transmettre des paramètres de variable de liaison et des informations de pagination à Query. Les entités peuvent être obtenues en exécutant la méthode getResultList et la méthode getSingleResult de Query.

article La description
argument jpql (texte d'enquête)
Valeur de retour S'il y a un enregistrement qui correspond à la condition, la liste d'entités correspondante
Liste vide si elle n'existe pas (taille = 0)

b. Mise à jour des données

Vous pouvez mettre à jour les données en obtenant l'entité que vous souhaitez mettre à jour avec EntityManager et en modifiant l'état de cette entité. EntityManager gère les données d'origine avant la modification, compare les données d'origine avec les données actuelles à un moment approprié et détecte automatiquement la mise à jour. Une instruction de mise à jour est automatiquement émise lorsqu'elle détecte qu'une entité a été mise à jour.

(La condition de la colonne de version (décrite plus loin) utilisée dans le contrôle exclusif optimiste est automatiquement ajoutée à l'instruction Update émise à ce moment.)

public void updateEntity() throws Exception{
	// EntityManager(em)Est injecté avec DI
	//Obtenez l'enregistrement (entité) dont la clé primaire de la classe Emp (table) est "1"
	Emp emp = em.find(Emp.class, 1L);
    emp.setEmpName("NEWNAME");
    //La déclaration de mise à jour est émise automatiquement
}

c. Ajouter des données

Pour ajouter une entité, transmettez l'entité nouvellement créée à la *** méthode persist *** d'EntityManager. Si l'annotation @GeneratedValue est spécifiée pour l'enregistrement de clé primaire dans la définition de classe d'entité de la cible d'opération, elle est automatiquement définie sans définir la valeur de l'élément de clé primaire.

public void persistEntity() throws Exception{
	// EntityManager(em)Est injecté avec DI
	//Générer l'entité Emp suivante
    Emp emp = new Emp();
    emp.setEmpNo (123);
    emp.setEnpName("123Name");
    em.persist(emp);
    //La déclaration d'insertion est émise automatiquement
}

d. Supprimer les données

Pour supprimer une entité, transmettez l'entité que vous souhaitez supprimer à la *** méthode de suppression *** d'EntityManager. EntityManager émet une instruction SQL Delete au bon moment.

(La condition de la colonne de version (décrite plus loin) utilisée dans le contrôle exclusif optimiste est automatiquement ajoutée à l'instruction Delete émise à ce moment.)

public void removeEntity() throws Exception{
	// EntityManager(em)Est injecté avec DI
	//Supprimer l'entité suivante
    em.remove(emp);
    //La déclaration de suppression est émise automatiquement
}

5. Cartographie O / R

a. Annotation

Les annotations requises pour le mappage O / R sont les suivantes. Toutes ces annotations appartiennent au package "javax.persistence".

*** Pour l'attribut fetch de @ManyToOne, @OneToMany et @OneToOne, spécifiez essentiellement "fetchType.LAZY" (décrit plus loin). *** ***

No Annotation Emplacement spécifié Signification de représenter
1 @Entity classe Être une entité
Le nom d'entité est un nom utilisé dans JPQL pour identifier une entité dans le monde Java.
Exemple:@Entity(name = "Hoge")
2 @Id champ Soyez la clé primaire
3 @Transient champ Être non permanent
Attribué lorsque vous ne souhaitez pas vous associer à des colonnes de base de données
4 @GeneratedValue champ Générer automatiquement la valeur de la clé primaire
5 @ManyToOne champ La relation est plusieurs à un
6 @OneToMany champ La relation est un-à-plusieurs
7 @OneToOne champ La relation est un à un
8 @Table classe Spécifiez la table à mapper
9 @Column champ Spécifiez qu'il s'agit d'une colonne cible de mappage
Les colonnes sans contrainte NOT NULL doivent utiliser le type wrapper pour représenter NULL
10 @JoinColumn champ Spécifiez la colonne source et la colonne de destination
11 @SequenceGenerator champ Définition de la séquence qui génère la clé primaire
12 @TableGenerator champ Définition de la table qui génère la clé primaire
13 @Version champ Doit être un champ de numéro de version pour utiliser un contrôle exclusif optimiste (décrit ci-dessous)
Le type de champ doit être de type entier ou long

b. Chargement paresseux

Lorsqu'une table a une configuration parent-enfant, la table enfant n'est pas acquise lors de l'acquisition de la table parente, mais est acquise en cas de besoin (au verso).

L'attribut fetch de @ManyToOne, @OneToMany et @OneToOne est défini par défaut sur "fetchType.EAGER", utilisez donc le chargement différé "fetchType.LAZY" sauf si vous avez une intention spécifique.

C. Problème N + 1

Émettez une instruction SELECT une fois pour obtenir N enregistrements (entités parentes) à partir de n'importe quelle table, N enregistrements émettent une instruction SELECT une fois pour obtenir les données associées (entité enfant), un total de N fois. Veuillez noter qu'une grande quantité de SQL sera émise involontairement. Il existe les deux solutions suivantes.

--Utilisation de JOIN FETCH avec JPQL -Utiliser l'annotation @Fetch


référence

  1. JPQL JPQL est interprété par l'implémentation JPA, converti en SQL adapté à la base de données à utiliser, puis exécuté. SQL a un dialecte pour chaque base de données, mais en utilisant JPQL, certaines différences entre les dialectes peuvent être absorbées.

a. Grammaire et terminologie

(1) Nom de l'entité et variable d'identification

Spécifiez le nom de l'entité (≠ nom de la table) dans la section FROM de JPQL. La variable d'identification (ci-après dénommée "e" en SQL) est déclarée après le nom de l'entité, et les éléments d'extraction, etc. sont spécifiés en l'utilisant.

select e from Employee e;
(2) Récupérer la jointure

Avec le chargement différé appliqué, les entités enfants ne sont récupérées qu'en cas de besoin. En revanche, si l'on sait que les entités enfants sont également requises depuis le début, il est plus efficace de les acquérir en même temps avec un seul SQL. Dans de tels cas, utilisez *** fetch join ***. Le SQL utilisant la jointure de récupération est le suivant.

select distinct d d from Department d inner join fetch d.employees where d.name = "ABC";

7. Cycle de vie de l'entité

a. Quatre états de l'entité

Une fois récupérée, l'entité est gérée dans un contexte persistant. Dans le contexte persistant, il est géré dans les quatre états suivants. Ces états changent en raison de l'exécution des méthodes EntityManager et de la fin des contextes persistants, et sont appelés *** cycle de vie d'entité ***. La figure est la suivante.

--Nouveau La nouvelle entité reste une nouvelle entité, sauf si vous spécifiez les méthodes persist ou merge d'EntityManager.

--Détaché Même si vous apportez des modifications à l'entité séparée, les modifications ne seront pas reflétées dans le contexte de persistance, sauf si l'entité est re-gérée par la méthode de fusion d'EntityManager.

画像2.png

b. Synchronisation de la base de données

EntityManager reflète les entités gérées et supprimées dans la base de données. Ce processus s'appelle *** synchronisation de base de données ***. La synchronisation écrit les informations de modification d'entité stockées dans le contexte de persistance dans la base de données.

La synchronisation par défaut de la base de données est la suivante:

--Lorsque la méthode flush d'EntityManager est appelée

8. Contrôle exclusif optimiste de JPA

Le contrôle exclusif inclut un contrôle exclusif pessimiste qui verrouille des données spécifiques et interdit CRUD d'autres transactions, et un contrôle exclusif optimiste qui ne verrouille pas les données et échoue l'autre traitement en cas de conflit de mise à jour. ..

JPA peut réaliser un contrôle exclusif optimiste basé sur ce numéro de version en préparant une colonne de type entier qui gère le numéro de version (affectation @Version) dans la base de données.


* Edition supplémentaire * Ce qu'il est utile de savoir

--Je veux vérifier le SQL émis par Hibernate dans le journal → Définissez "true" dans la propriété hibernate.show_sql de persistence.xml (*).

<property name = "hibernate.show_sql" value = "true" />

--Je souhaite formater et afficher le SQL dans le journal émis par Hibernate → Définissez "true" dans la propriété hibernate.format_sql de persistence.xml (*).

<property name = "hibernate.format_sql" value = "true" />


Recommended Posts

Résumer les principaux points de démarrage avec JPA appris avec Hibernate
Démarrez avec le fonctionnement de JVM GC
Premiers pas avec Doma-Using Projection avec l'API Criteira
Premiers pas avec les sous-requêtes utilisant Doma avec l'API Criteria
Premiers pas avec Doma-Using Joins avec l'API Criteira
Premiers pas avec Doma - Introduction à l'API Criteria
Premiers pas avec DBUnit
Premiers pas avec Ruby
Premiers pas avec Swift
Premiers pas avec Doma-Transactions
Premiers pas avec Doma-Dynamic Construction de clauses WHERE avec l'API Criteria
Premiers pas avec Reactive Streams et l'API JDK 9 Flow
Premiers pas avec Git Hub Container Registry au lieu de Docker Hub
Premiers pas avec le traitement Doma-Annotation
Premiers pas avec Java Collection
Premiers pas avec JSP et servlet
Premiers pas avec les bases de Java
Résumez les mots que vous avez appris
Premiers pas avec Spring Boot
Premiers pas avec les modules Ruby
Générez un numéro de série avec TableGenerator of Hibernate (JPA) et stockez-le dans l'ID de String.
Revenir au début, démarrer avec Java ② Instructions de contrôle, instructions de boucle
Voir le comportement des mises à jour d'entités avec Spring Boot + Spring Data JPA
Prise en main des opérateurs logiques utilisant Doma tels que AND et OR dans la clause WHERE de l'API Criteria
Premiers pas avec Java_Chapitre 5_Exercices pratiques 5_4
[Google Cloud] Premiers pas avec Docker
Premiers pas avec Docker avec VS Code
Ajouter @ManyToOne à une partie de la clé primaire composite dans Hibernate JPA
J'ai essayé de résumer les points clés de la conception et du développement de gRPC
Avant d'oublier, les fonctions et les points de l'application Furima