MyBatis bietet erweiterte Association -Abfragefunktionen, mit denen die von der Datenbank erhaltenen Ergebnissätze leicht zu definierten Java -Bohnen abbilden können. Das Folgende ist ein Beispiel, um zu zeigen, wie MyBatis mit gemeinsamen Eins-zu-Viele- und vielen zu einem Beziehungskomplexzuordnungen umgeht.
Entwerfen Sie ein einfaches Blog -System, in dem ein Benutzer mehrere Blogs öffnen, Artikel im Blog veröffentlichen, Kommentare zulassen und Artikel kennzeichnen. Das Blog -System besteht hauptsächlich aus den folgenden Tabellen:
Autorentabelle: Autoreninformationstabelle, zeichnen Sie die Informationen des Autors, den Benutzernamen und das Passwort, die E -Mail -Adresse usw. auf.
Blog-Tabelle: Blog-Tabelle, ein Autor kann mehrere Blogs öffnen, dh die Beziehung zwischen Autor und Blog ist eins zu viele.
Beitragstabelle: Artikel -Datensatztabelle, Aufzeichnung der Post -Veröffentlichungszeit, des Titels, des Textes und anderer Informationen; Es kann viele Artikel unter einem Blog geben, und die Beziehung zwischen Blog und Post ist eins zu vielen.
Kommentare Tabelle: Artikelkommentabelle, Rekordartikel Kommentare, ein Artikel kann viele Kommentare haben: Die Korrespondenz zwischen Beitrag und Kommentaren ist eins zu vielen.
Tag -Tabelle: Tag -Tabelle, die die Tag -Klassifizierung des Artikels darstellt. Ein Artikel kann mehrere Tags haben, und ein Tag kann auf verschiedene Artikel angewendet werden, sodass die Beziehung zwischen Tag und Post eine viel-zu-Viele-Beziehung ist. (Die vielen zu viele Beziehung zwischen Tag und Post wird über die post_tag-Tabelle widerspiegelt)
POST_TAG -TABELLE: Aufzeichnet die Korrespondenz zwischen Artikeln und Tags.
Im Allgemeinen erstellen wir ein entsprechendes Javaboan (oder Pojo), das auf der Struktur jeder Tabelle basiert, um den grundlegenden CRUD -Betrieb der Tabelle abzuschließen.
Die obige Javabäe -Definition einer einzelnen Tabelle kann manchmal nicht den geschäftlichen Anforderungen entsprechen. Im Geschäft sollte ein Blog -Objekt Informationen über seinen Autor und eine Liste von Artikeln haben, wie in der folgenden Abbildung gezeigt:
Wenn Sie eine Instanz einer solchen Klasse erhalten möchten, benötigen Sie mindestens ein paar Schritte:
1. Fragen Sie die Bloginformationen in der Blog -ID in der Blog -Tabelle ab und weisen Sie dem Blog -Objekt die Abfrageblogid und den Titel zu.
2. Nach der Abfrageautorid in den Bloginformationen gehen Sie zur Autor -Tabelle, um die entsprechenden Autoreninformationen zu erhalten, das Autorenobjekt zu erhalten und sie dann dem Blog -Objekt zuweisen.
3. Nach BlogID fragen Sie die entsprechende Artikelliste für Post -Artikel in der Post -Tabelle ab und weisen Sie das Objekt der Liste <Post> dem Blog -Objekt zu.
Auf diese Weise werden mindestens drei Abfrageanweisungen in der unteren Schicht aufgerufen. Bitte beachten Sie den folgenden Code:
/** Das Bloginfo -Objekt über BlogID erhalten*/ public static bloginfo organicQueryontest (String blogId) {BigDecimal id = new BigDecimal (BlogID); SQLSession Session = SQLSessionFactory.OpenSession (); Bloginfo bloginfo = new Bloginfo (); // 1. Fragen Sie das Blog -Objekt gemäß BlogID ab und setzen Sie den Wert auf Bloginfo blog = (Blog) Sitzung.Selectone ("com.foo.bean.blogmapper.SelectByprimaryKey", ID); bloginfo.setblogid (blog.getBlogid ()); bloginfo.settitle (blog.gettitle ()); // 2. Laut der Autorid im Blog geben Sie die Datenbank ein, um Autoreninformationen abzufragen und das Ergebnis dem Bloginfo -Objektautor Autor = (Autor) Sitzung festlegen. Bloginfo.setAuthor (Autor); // 3. Fragen Sie das Post -Objekt ab und setzen Sie es in Bloginfo -Liste eins. Bloginfo.setPosts (Beiträge); // Drucken Sie das Objekt in Form eines JSON -String -JsonObject Object = new JSONObject (blogInfo); System.out.println (Object.ToString ()); return bloginfo; }Aus dem obigen Code können wir erkennen, dass es schwieriger ist, ein Bloginfo -Objekt zu erhalten. Sie müssen die Datenbankabfrage insgesamt dreimal anrufen, die erforderlichen Informationen abrufen und dann das Bloginfo -Objekt zusammenstellen.
Verschachtelte Erklärung Anfrage
MyBatis bietet einen Mechanismus namens Nested Statement Query, der die oben genannten Vorgänge erheblich vereinfachen und Konfiguration und Code wie folgt hinzufügen kann:
<resultmap type = "com.foo.bean.blogInfo" id = "bloginfo"> <id column = "blog_id" Property = "blogId" /> <result column = "title" property = "title" /> <association property = "author" columne select="com.foo.bean.AuthorMapper.selectByPrimaryKey"> </association> <collection property="posts" column="blog_id" ofType="com.foo.bean.Post" select="com.foo.bean.PostMapper.selectByBlogId"> </collection> </resultMap> <select id="queryBlogInfoById" resultmap = "bloginfo" parameterType = "java.math.bigdecimal"> select bblog_id, b.title, b.Author_id als blog_author_id von louluan.blog b won b.blog_id = #{blogid, jdbctype = decimal} </ausgewählt} </ausgewählt. /** Holen Sie Bloginfo -Objekt über BlogID*/ public static blogInfo nestedQueryontest (String BlogID) {BigDecimal id = new BigDecimal (BlogID); SQLSession Session = SQLSessionFactory.OpenSession (); Bloginfo bloginfo = new Bloginfo (); bloginfo = (bloginfo) session.selectone ("com.foo.bean.blogmapper.queryblogInfobyid", id); JsonObject Object = new JsonObject (blogInfo); System.out.println (Object.ToString ()); return bloginfo; }Die vorherige Abfrage kann durch den obigen Code vollständig realisiert werden. Hier brauchen wir nur bloginfo = (bloginfo) session. Im Code können wir ein komplexes Bloginfo -Objekt erhalten.
Das Prinzip der verschachtelten Aussagefrist
Im obigen Code führt MyBatis den folgenden Prozess aus:
1. Führen Sie zunächst die entsprechende Anweisung von queryblogInfobyid aus, um das Ergebnis der Ergebnissergebnis aus der Blog -Tabelle zu erhalten.
2. Nehmen Sie den nächsten gültigen Datensatz des Ergebnissets aus und erstellen Sie dann das entsprechende Bloginfo -Objekt basierend auf den vom Ergebnismap definierten Zuordnungsspezifikationen.
3. Wenn Sie das Autor -Attribut in Bloginfo zuweisen möchten, stellen Sie fest, dass es eine zugeordnete Abfrage gibt. Zu diesem Zeitpunkt wird MyBatis zunächst die Auswahl der Abfrageanweisung ausführen, um das zurückgegebene Ergebnis zu erhalten und das Ergebnis dem Autorattribut von Bloginfo festzulegen.
4. Bei der Zuweisung der Beiträge von Bloginfo sind auch ähnliche Prozesse vorhanden.
5. Wiederholen Sie 2 Schritte bis zum Ergebnis. next () == false;
Das Folgende ist ein schematisches Diagramm des Bloginfo -Objektkonstruktionszuweisungsprozesses:
Eine sehr gute Funktion dieser Art der zugehörigen verschachtelten Abfrage besteht darin, dass sie die Auswahlanweisung wiederverwenden und komplexe Objekte durch die Kombination zwischen einfachen Auswahlanweisungen konstruieren kann. Die beiden oben genannten Aussagen, die oben com.foo.bean.authormapper.SelectByprimaryKey und com.foo.bean.postmapper.Selectbyblogid verschrieben wurden, können unabhängig verwendet werden.
N+1 Problem
Seine Nachteile sind auch ziemlich offensichtlich: das sogenannte N+1-Problem. Die zugehörige verschachtelte Abfrage zeigt einen Ergebnissatz, und dann wird die zugehörige Abfrage basierend auf jedem Datensatz dieses Ergebnissatzes durchgeführt.
Nehmen wir nun an, es gibt nur eine verschachtelte Abfrage (dh ein Assoziations -Tag im ResultMap), und die Anzahl der von der Abfrage zurückgegebenen Einträge ist n, dann wird die zugehörige Abfrage -Anweisung n -mal ausgeführt, plus die Abfrage selbst gibt das Ergebnis einmal auf Abfrage ein und eine Gesamtsumme von N+1, die auf die Datenbank zuzugreifen ist. Wenn n relativ groß ist, ist ein solcher Datenbankzugriffsverbrauch sehr groß! Daher müssen Benutzer, die diese Art von verschachtelter Anweisungsabfrage verwenden, sorgfältig prüfen, um sicherzustellen, dass der N -Wert nicht sehr groß ist.
Beispielsweise gibt die Auswahlanweisung selbst ein Ergebnis mit com.foo.bean.blogmapper.queryblogInfobyid mit 1 zurück. Da es zwei zugeordnete Anweisungsabfragen enthält, muss sie auf die Datenbank 1* (1+1) = insgesamt dreimal zugreifen.
Verschachtelte Ergebnisanfrage
Abfragen verschachtelter Aussagen können unsichere Datenbankzugriffszeiten verursachen, die die Leistung beeinflussen können. MyBatis unterstützt auch eine Art verschachtelte Ergebnisse-Abfrage: Das heißt, für die Abfrage von Eins-zu-Viele, vielen zu vielen und vielen Situationen sucht MyBatis die Ergebnisse aus der Datenbank gleichzeitig durch gemeinsame Abfrage und konvertiert dann die Ergebnisse, die auf der Grundlage der geforderten Objekte, die zu den erforderlichen Objekten, die erforderlichen, die erforderlichen Objekte und die erforderlichen Beziehung und die im Bereich der Konfiguration und die Konfiguration und die Konfiguration und die Konfiguration und die Konfiguration und die Konfiguration, die im Ergebnis basiert, und die in der Folge und der Verhältnis zu den entsprechenden Verhältnissen und die im Rahmen der Runde und des Konfiguration und der Konfiguration umsetzt.
Definieren Sie die Ergebniskarte von Bloginfo neu
<resultMap type = "com.foo.bean.blogInfo" id = "bloginfo"> <id column = "blog_id" Property = "blogId"/> <result column = "title" property = "title"/> <assoziation property = "author" columne column = "user_name" property = "userername"/> <resultal column = "password" property = "password"/> <resultal column = "E -Mail" Eigenschaft = "E -Mail"/> <result columne <result column = "blog_id" Eigenschaft = "blogId"/> <resultal column = "create_time" property = "createTime"/> <resultal column = "subjekt" property = "subjekt"/> <resultal = "body" property = "body"/> <resultal column = "entworfen" property = "entworfen"/> </collection> </resultmap> </resultmap> </resultmap> <
Die entsprechenden SQL -Anweisungen sind wie folgt:
<select id="queryAllBlogInfo" resultMap="BlogInfo"> SELECT B.BLOG_ID, B.TITLE, B.AUTHOR_ID AS BLOG_AUTHOR_ID, A.AUTHOR_ID, A.USER_NAME, A.PASSWORD, A.EMAIL, A.BIOGRAPHY, P.POST_ID, P.BLOG_ID AS BLOG_POST_ID, P.CREATE_TIME, P.SUBJECT, P.BODY, P.DRAFT FROM Blog B links Outer Join Autor A auf B.ATUTHOR_ID = A.AUTHOR_ID LINKEN OUTER JOIN POST P ON P.BLOG_ID = B.BLOG_ID </SELECT>
/** Erhalten Sie alle Informationen zu allen Blogs*/ public static blogInfo nestedResultontest () {SQLSession Session = SQLSessionFactory.OpenSession (); Bloginfo bloginfo = new Bloginfo (); bloginfo = (bloginfo) session.selectone ("com.foo.bean.blogmapper.queryallbloginfo"); JsonObject Object = new JsonObject (blogInfo); System.out.println (Object.ToString ()); return bloginfo; } Ausführungsschritte für verschachtelte Ergebnisanfrage:
1. Führen Sie die Join -Operationen an, basierend auf der entsprechenden Beziehung der Tabelle, um den Ergebnissatz zu erhalten.
2. Nach den Ergebnissen der Ergebnisse und den Ergebnissen der Ergebnismap -Definition von Bloginfo montieren und weisen Sie die zurückgegebene Ergebnis -Set in Speicher zum Konstrukten -Bloginfo zusammen;
3. Rückgeben Sie die konstruierte Ergebnisliste <Bloginfo> Ergebnis.
Wenn es sich um die zugehörige Ergebnisabfrage handelt, wird es von der <Association Property = "Author" column = "blog_author_id" javatype = "com.foo.bean.author"> konfiguriert, wenn es sich um eine viele-zu-Eins-Beziehung handelt. MyBatis holt Daten über den Wert des Author_ID, der der Spalteneigenschaft entspricht, aus dem Speicher aus dem Speicher und verkapuliert sie in ein Autorenobjekt.
Wenn es sich um eine Eins-zu-Viele-Beziehung handelt, genau wie die Beziehung zwischen Blog und Post wird sie von der <collection property = "post" column = "blog_post_id" oftype = "com.foo.bean.post"> konfiguriert, verwendet MyBatis Blog_ID, um Postobjekte im Speicher zu holen und in List zu inkapitulieren.
Für die Abfragestation der zugehörigen Ergebnisse müssen Sie die Datenbank nur einmal abfragen, und dann werden die Integration und Montage der Ergebnisse im Speicher platziert.
Das obige ist es, Eins-zu-viele- und viele-zu-Eins-Zuordnungsobjektverarbeitung zu demonstrieren, indem alle Blog-Informationen abfragen.
PS: Beispiel für die Selbstassoziationskartierung:
Entitätsklasse
öffentliches Klassenmodul {private int id; privater Stringschlüssel; privater Zeichenfolge Name; Private Modul Parentmodule; Private List <Modul> Kindermodules; private String -URL; private INT -Sortierung; private String -Show; private String del; public int getid () {return id; } public void setId (int id) {this.id = id; } public String getKey () {return key; } public void setKey (String -Schlüssel) {this.key = key; } public String getName () {return name; } public void setName (String -Name) {this.name = name; } öffentliches Modul getParentModule () {Return ParentModule; } public void setParentModule (Modul parentModule) {this.parentmodule = parentModule; } public String geturl () {return url; } public void seturl (String url) {this.url = url; } public int tertort () {return sort; } public void setSort (int sort) {this.sort = sort; } public String getshow () {return show; } public void setShow (String show) {this.show = show; } public String getdel () {return del; } public void setdel (string del) {this.del = del; } public list <Modul> getChildrenmodules () {return childhesmodules; } public void setChildrenmodules (list <modul> childrenmodules) {this.childrenmodules = childhumodules; }} XML -Code:<mapper namespace = "com.sagaware.caraccess.mapper.modulemapper"> <resultmap type = "modul" id = "moduleresultmap"> <id property = "id" Spalte = "module_id"/> <resulting achapel column="module_url"/> <result property="sort" column="module_sort"/> <result property="show" column="module_show"/> <result property="del" column="module_del"/> <!-- Query the parent module--> <association property="parentModule" column="module_parent_id" select="getModulesById" /> <!-- Query the submodule-> <collection properation = "chidessmodules" column = "module_id" select = "getChildrenmodules"/> </resultmap> <select id = "getModules" parameterType = "String" resultMap = "moduleresultmap"> select * aus tb_moduls wob parameterType = "int" resultMap = "moduleresultMap"> SELECT * Aus tb_module wob </mapper>