Intercepteur
En parlant d'Interceptor, je crois que les chaussures pour enfants familières avec Struts2 connaissent définitivement Struts2. Struts2 peut personnaliser l'intercepteur pour effectuer une série de travaux connexes que vous souhaitez. Et l'intercepteur dont nous parlons ici a également des fonctions similaires.
Sans dire des bêtises, juste du code:
Ce qui suit est la classe MyInterceptor, qui implémente l'interface intercepteur:
public String onPrepareStatement (String arg0) {return arg0; } public boolean onSave (objet arg0, serializable arg1, objet [] arg2, string [] arg3, type [] arg4) lance callbacKexception {if (arg0 instanceof user) {System.out.println ("user est sauvegoté =>" + ((user) arg0) .getName ()); } return false; } Je ne lirai pas d'autres méthodes, je suivrai simplement l'implémentation par défaut. Nous avons seulement besoin de modifier ces deux méthodes. Nous devons modifier la valeur de retour dans ONPREPARESTATION pour renvoyer l'instruction SQL actuelle. Les paramètres sont l'instruction SQL exécutée transmise. Nous pouvons imprimer l'instruction en le renvoyant directement.
Dans Onsave, vous pouvez dire que cela s'appelle lors de la sauvegarde. Nous pouvons faire une série de travaux de pré-préservation.
Je crois que tout le monde peut le comprendre en regardant les noms des paramètres.
Sérialisable fait référence au paramètre du numéro de séquence, qui fait référence aux attributs qui mappent à l'ID de base de données.
Object [] Il s'agit d'une série d'États, qui n'a pas été beaucoup utilisé pour le moment. Je l'étudierai plus tard. Cependant, l'API explique que peu importe comment la valeur de ce tableau est modifiée, la méthode Onsave doit retourner vrai.
String [] fait référence au nom de l'attribut et le type [] est le type de l'attribut correspondant.
1) Cet intercepteur peut effectuer des opérations correspondantes avant et après l'enregistrement de la base de données. Par exemple, si vous souhaitez modifier les données et ajouter le préfixe ou le suffixe, vous pouvez l'utiliser pour l'implémenter. Jetons un coup d'œil ci-dessous.
public boolean onsave (objet arg0, serializable arg1, objet [] arg2, string [] arg3, type [] arg4) lance callbacKException {if (arg0 instanceof user) {System.out.println ("user à être enregistré =>" + ((user) arg0) .getName ()); } // Nous ajoutons 123 comme préfixe du nom ici utilisateur utilisateur = (utilisateur) arg0; user.setName ("123" + user.getName ()); retourne false; }Jetons un coup d'œil à la méthode de test:
public static void main (String [] args) {configuration cfg = new configuration (). configure (); SessionFactory SessionFactory = cfg.BuildSessionFactory (); Interceptor interceptor = new myinteCeceptor (); Session Session = SessionFactory.OpenSession (intercepteur); Utilisateur utilisateur = nouveau utilisateur (); user.setName ("shun"); Transaction tx = session.begintransaction (); session.save (utilisateur); tx.Commit (); session.close (); } C'est très simple, nous l'avons juste sauvé simplement. Il n'y a pas de fichiers de mappage et de cours d'entité ici, essayez-le simplement.
Exécutez-le et nous pouvons voir:
Utilisateur à enregistrer => Shun Hibernate: Insérez dans l'utilisateur (user_name, âge) VALEURS (? ,?) Hibernate: Mettez à jour l'utilisateur user_name =?, Age =? où user_id =?Il mettra à jour le nom et l'âge à la fin, principalement parce que nous avons apporté des modifications à la méthode Onsave.
public boolean onload (objet arg0, serializable arg1, objet [] arg2, string [] arg3, type [] arg4) lève callbacKexception {if (arg0 instance user) {System.out.println ("user est chargé =>" + (arg2 [0] + ":" + arg2 [1])); } Utilisateur utilisateur = (utilisateur) arg0; // juge quel attribut est nom pour (int i = 0; i <arg3.length; i ++) {if (arg3 [i] .equals ("name")) {user.setName ((string) arg2 [i]). Remplace ("123", "")); Arg2 [i] = ((String) Arg2 [i]). Remplace ("123", ""); }} return false; } La valeur de l'attribut modifié lors du chargement est écrite dans la méthode Onload.
L'ARG0 est ici notre objet utilisateur. Il n'a pas encore de valeur. Cette méthode est appelée après la méthode de chargement, il est donc inutile pour nous de faire fonctionner l'utilisateur pour le moment, et l'utilisateur.setname ici est une opération inutile. Principalement dans:
Arg2 [i] = ((String) Arg2 [i]). Remplace ("123", "");
Ce code modifie la valeur de l'attribut renvoyé, de sorte que la valeur de l'objet utilisateur que nous obtenons dans le programme changera également. Exécutons la méthode de test pour voir:
public static void main (String [] args) {configuration cfg = new configuration (). configure (); SessionFactory SessionFactory = cfg.BuildSessionFactory (); Interceptor interceptor = new myinteCeceptor (); Session Session = SessionFactory.OpenSession (intercepteur); User user = (utilisateur) session.load (user.class, new long (39)); System.out.println ("Nom d'utilisateur:" + user.getName ()); session.close (); }En regardant les résultats, nous avons obtenu:
Hibernate: sélectionnez user0_.user_id en tant qu'utilisateur1_0_0_, user0_.user_name en tant qu'utilisateur2_0_0_, user0_.age en tant qu'âge 00_0_ de l'utilisateur user0_ où user0_.user_id =? Utilisateur à charger => 123Shun: 0 Nom d'utilisateur: Shun
Nous avons supprimé le 123 d'origine et effectué un traitement pertinent après le chargement réel, mais ce n'est pas un traitement réel avant le chargement réel, et il se méfie un peu de la spéculation. Mais c'est aussi une considération. L'intercepteur peut être le plus utilisé dans le traitement pertinent des journaux. Par exemple, nous devons nous connecter en conséquence pour chaque opération, donc l'intercepteur est un bon choix.
Collection
N'oubliez pas l'ensemble que nous avons utilisé dans un à plusieurs exemples précédents, avez-vous toujours l'impression? Si vous ne le faites pas, allez vérifier les informations et les réviser. Aujourd'hui, nous apprendrons autour de ces collections.
Allons juste au point.
1) Apprenons d'abord le jeu. Tout le monde sait qu'il existe également un ensemble dans le package Java Util. Alors, quelle est la différence et la connexion entre l'ensemble et le jeu dans Hibernate? Nous ouvrons l'API Hibernate, Find set, et vous pouvez le voir.
Ce que nous voyons, c'est la classe parent d'une telle collection Hibernate. Il s'agit d'une classe abstraite avec une série de classes d'implémentation concrètes. Lorsque nous continuons à voir la méthode suivante, nous constatons que cette classe met en œuvre l'encapsulation de la collection Java, nous comprenons donc que le soi-disant ensemble d'hibernate n'insule que l'ensemble Java.
Alors, cette caractéristique qui ne permet pas d'éléments en double dans l'ensemble également en hibernate? La réponse est bien sûr oui.
Nous ne les regardons pas ici. Dans le passé, lorsque nous avons appris la cartographie, nous avons directement associé des propriétés aux classes associées, mais aujourd'hui nous ne sommes pas comme ça. Nous utilisons une autre méthode, associez simplement une chaîne pour voir s'il y a un problème.
Mais avant de regarder cette question, jetons un coup d'œil à la comparaison des cordes en Java.
Ce que nous voyons, c'est la classe parent d'une telle collection Hibernate. Il s'agit d'une classe abstraite avec une série de classes d'implémentation concrètes. Lorsque nous continuons à voir la méthode suivante, nous constatons que cette classe met en œuvre l'encapsulation de la collection Java, nous comprenons donc que le soi-disant ensemble d'hibernate n'insule que l'ensemble Java.
Alors, cette caractéristique qui ne permet pas d'éléments en double dans l'ensemble également en hibernate? La réponse est bien sûr oui.
Nous ne les regardons pas ici. Dans le passé, lorsque nous avons appris la cartographie, nous avons directement associé des propriétés aux classes associées, mais aujourd'hui nous ne sommes pas comme ça. Nous utilisons une autre méthode, associez simplement une chaîne pour voir s'il y a un problème.
Mais avant de regarder cette question, jetons un coup d'œil à la comparaison des cordes en Java.
public static void main (String [] args) {String s1 = "shun1"; String s2 = "shun1"; System.out.println ("S1 == S2:" + (S1 == S2)); } Je crois que de nombreuses chaussures pour enfants savent que la réponse est vraie.
Avant de faire un exemple, jetons un coup d'œil à notre fichier de mappage. Nous n'écrirons pas les cours de mappage:
Ceci est le fichier de mappage pour tuser:
<class name = "tuser" table = "t_user" dynamic-insert = "true" dynamic-update = "true" dynamic-update = "true"> <id name = "id" column = "id"> <générateur /> </ id> <propriété name = "name" type = "java.lang.string" colonnet = "name" /> <propriété name = "Âge" type = "java.lang. colonnes = "Age" /> <set name = "adresses" cascade = "all" table = "t_address"> <key column = "user_id" /> <! - <one-to-many /> -> <élément chronny = "adresse" type = "string" /> </ set> </ class>
Ensuite, le fichier de mappage d'adresses:
<class name = "adresse" table = "t_address" dynamic-insert = "false" dynamic-update = "false"> <id name = "id" column = "id" type = "java.lang.integer"> <générateur /> </ id> <propriété name = "adresse" colonnes = "adresse" type = "java.Lang.string" /> not-null = "true"> </ plusieurs-à-un> </ class>
Les chaussures des enfants l'ont vu clairement. J'ai commenté un à plusieurs dans l'ensemble de TUSER et utilisé Element. Quel que soit le problème, regardons d'abord la base de données:
Ceci est le tableau T_Address:
Voici la table T_User:
Nous pouvons voir que l'utilisateur avec ID 4 correspond à trois adresses. Ensuite, jetons un coup d'œil à la méthode de test:
public static void main (String [] args) {configuration cfg = new configuration (). configure (); SessionFactory SessionFactory = cfg.BuildSessionFactory (); Session Session = SessionFactory.OpenSession (); TUSER USER = (TUSER) Session.Load (TUSER.CLASS, NOUVEAU INTEGER (4)); Set set = user.getAddress (); session.close (); System.out.println ("Taille d'adresse:" + set.size ()); } Un cours de requête très simple, vient de retirer ce résultat, nous avons vu un phénomène étrange:
Taille de l'adresse: 1
C'est le résultat!
Vous diras certainement que ça doit être faux, c'est un bug en hibernate. Je dois être heureux ici. Je peux enfin soumettre un bogue. Lorsque j'ai changé de travail, je pouvais dire fort que j'ai soumis un bogue pour Hibernate. Haha, mais malheureusement, ce n'est pas un bug.
Je viens de dire que la comparaison de la chaîne que nous avions devant était en outre la voie ici, alors comment la paver?
Nous utilisons SET dans le fichier de configuration et l'associons via des caractères de chaîne. Ensuite, lorsqu'elle est retirée dans la base de données et la met dans l'ensemble, il déterminera d'abord si les valeurs du caractère associées sont égales. Ici, comme nos valeurs sont égales (nous ne creuserons pas comment il se compare pour le moment), nous avons seulement besoin de savoir que lorsque nous utilisons des chaînes pour comparer, nous tombons dans le piège à cordes en Java. Si vous découvrez qu'il n'y en a qu'un, alors la suppression est plus gênante lors de la suppression, elle supprimera tous les mêmes enregistrements.
Alors jetons un coup d'œil à celui supprimé:
TUSER USER = (TUSER) Session.Load (TUSER.CLASS, NOUVEAU INTEGER (4)); Transaction tx = session.begintransaction (); Objet obj = user.getAddress (). Iterator (). Next (); user.getAddress (). retire (obj); tx.Commit (); session.close ();
La sortie de l'instruction par hibernate ici est:
Hibernate: supprimer de t_address où user_id =?
Je crois que tout le monde sait quand il s'agit de supprimer toutes les adresses sous l'utilisateur. Il n'y a pas d'autre choix que de supprimer tout cela.
Vous devez donc y prêter attention dans un développement réel.
2) Nous avons parlé de Set ci-dessus, il semble qu'il n'est pas très agréable à utiliser. Il y a un tel piège, mais il n'y a aucun moyen. L'ensemble est celui que nous utilisons le plus, et généralement personne n'associe directement les cordes. Mais beaucoup de gens sont toujours mécontents, donc Hibernate aura un sac supplémentaire au besoin (peut-être pas comme requis, peut-être que certaines personnes sont insatisfaites, haha).
Regardons d'abord son utilisation de base:
Tout d'abord, nous devons modifier la balise SET dans le fichier de mappage de tuser
<sac name = "adresses" lazy = "true" table = "t_address"> <key column = "user_id" /> <élément type = "string" colonnes = "adresse" /> </bag>
Et la classe d'entité correspondante doit modifier le type d'adresses pour lister le type.
Ici, nous ajoutons trois adresses:
Nous exécutons le code de test:
public static void main (String [] args) {configuration cfg = new configuration (). configure (); SessionFactory SessionFactory = cfg.BuildSessionFactory (); Session Session = SessionFactory.OpenSession (); TUSER USER = (TUSER) Session.Load (TUSER.CLASS, NOUVEAU INTEGER (4)); System.out.println ("Taille d'adresse:" + user.getAddress (). Size ()); session.close (); }
Nous voyons ici:
Taille de l'adresse: 3
Cette fois, nous pouvons tout voir, qu'il y ait ou non des répétitions.
Mais nous avons juste regardé un problème de suppression. Le sac n'a pas été résolu ici, et nous devons utiliser idbag. Nous voyons le fichier de configuration et avons besoin des modifications suivantes:
idbag name = "adresses" table = "t_address" lazy = "true"> <collection-id type = "int" chronn = "id"> <générateur /> </ collection-id> <key chronnk = "user_id" /> <élément type = "string" chronn = "adresse" /> </ idbag>
Nous voyons qu'il n'a qu'une seule collection de plus que le sac pour indiquer le numéro d'enregistrement à supprimer.
Lorsque nous reloyons le code supprimé:
TUSER USER = (TUSER) Session.Load (TUSER.CLASS, NOUVEAU INTEGER (4)); Transaction tx = session.begintransaction (); Objet obj = user.getAddress (). Iterator (). Next (); user.getAddress (). retire (obj); tx.Commit ();
Nous voyons que l'instruction de sortie est:
Hibernate: supprimer de t_address où id =?
Cette fois, il n'est pas supprimé via user_id, mais sur la base de l'ID de T_Address, ce qui signifie qu'il supprime vraiment l'enregistrement que nous devons supprimer.
Nous voyons la base de données et l'enregistrement est maintenant:
Nous avons supprimé le premier enregistrement, c'est correct.
3) Après avoir examiné les deux méthodes ci-dessus, jetons un coup d'œil à la carte. La plus grande différence entre celle-ci et celle ci-dessus est qu'elle peut correspondre à des valeurs clés. Regardez directement le code, point de vue intuitif:
Tout d'abord, nous devons modifier le fichier de configuration:
<map name = "adresses" table = "t_address" lazy = "true"> <key column = "user_id" /> <index type = "string" colonnes = "type" /> <élément type = "string" colonnes = "adresse" /> </ map>
La plus grande différence entre celle-ci et les deux précédentes est qu'il existe un index, ce qui équivaut à la clé de carte de Java, et nous l'utilisons pour récupérer les enregistrements correspondants. N'oubliez pas qu'après avoir changé ici, vous devez modifier la classe d'entité correspondante et que vous devez modifier le type d'attribut d'adresses à MAP.
Regardez les données de la base de données:
Ici, nous voyons qu'il y a deux bureaux et une maison, alors quel bureau doit être utilisé?
Ne vous inquiétez pas, nous le saurons après avoir exécuté le code de test:
TUSER USER = (TUSER) Session.Load (TUSER.CLASS, NOUVEAU INTEGER (4)); System.out.println (user.getAddress (). Get ("home")); System.out.println (user.getAddress (). Get ("Office"));Shanwei Shanghai
Oui, comme le montre le résultat, nous obtenons celui derrière, ce qui est le même que le principe de la carte. Les valeurs stockées écraseront les valeurs précédentes (si elles sont la même clé).
La carte est relativement simple, ce qui est comparable aux deux premiers.
4) Jetons un coup d'œil au dernier. La liste est différente des précédentes, et elle peut être triée.
Jetons un coup d'œil à la façon dont il est mis en œuvre:
Tout d'abord, modifions le fichier de mappage:
<list name = "adresses" table = "t_address" lazy = "true"> <key column = "user_id" /> <index type = "string" colonnen = "idx" /> <élément type = "string" chronn = "adresse" /> </ list>
Il est similaire à la configuration de la carte, mais les attributs de l'index sont différents. L'index dans la carte est utilisé comme clé pour obtenir la valeur, tandis que l'index de la liste est utilisé comme tri.
Regardons la base de données:
Nous définissons trois valeurs dans l'ordre de 0, 1 et 2.
Exécutons le code pour modifier les valeurs de 0 et 2:
TUSER USER = (TUSER) Session.Load (TUSER.CLASS, NOUVEAU INTEGER (4)); Transaction tx = session.begintransaction (); Objet obj1 = user.getAddress (). Get (0); Objet obj2 = user.getAddress (). Get (2); user.getAddress (). set (0, obj2); user.getAddress (). set (2, obj1); tx.Commit ();
Nous voyons les résultats:
Nous voyons que 0 et 2 ont été remplacés, et bien sûr, cela ne fait que modifier la valeur d'IDX. Mais cela a essentiellement mis en œuvre la fonction de tri.