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
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)
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.
Il existe deux types de méthodes d'acquisition d'entités: l'acquisition de clé primaire (1) et l'acquisition de JPQL (2).
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);
}
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) |
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
}
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
}
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
}
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 |
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.
É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
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;
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";
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.
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
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.
--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" />