MyBatis menyediakan fungsi kueri asosiasi canggih, yang dapat dengan mudah memetakan set hasil yang diperoleh oleh database ke biji java yang ditentukan. Berikut ini adalah contoh untuk menunjukkan bagaimana Mybatis berurusan dengan pemetaan satu-ke-banyak dan banyak hubungan yang kompleks.
Desain sistem blog sederhana di mana pengguna dapat membuka banyak blog, memposting artikel di blog, mengizinkan komentar, dan tag artikel. Sistem blog terutama terdiri dari tabel berikut:
Tabel Penulis: Tabel Informasi Penulis, Catat Informasi Penulis, Nama Pengguna dan Kata Sandi, Alamat Email, dll.
Tabel Blog: Tabel Blog, seorang penulis dapat membuka banyak blog, yaitu hubungan antara penulis dan blog adalah satu-ke-banyak.
Tabel Posting: Tabel Catatan Artikel, Merekam Waktu Publikasi, Judul, Teks dan Informasi Lainnya; Mungkin ada banyak artikel di bawah blog, dan hubungan antara blog dan posting adalah satu-ke-banyak.
Tabel Komentar: Tabel Komentar Artikel, Catat Komentar Artikel, sebuah artikel dapat memiliki banyak komentar: korespondensi antara posting dan komentar adalah satu-ke-banyak.
Tabel tag: Tag tag, yang mewakili klasifikasi tag artikel. Sebuah artikel dapat memiliki banyak tag, dan tag dapat diterapkan pada artikel yang berbeda, sehingga hubungan antara tag dan postingan adalah hubungan banyak-ke-banyak; (Hubungan banyak-ke-banyak antara TAG dan POST tercermin melalui tabel Post_tag)
Tabel POST_TAG: Catat korespondensi antara artikel dan tag.
Secara umum, kami akan membuat Javabean (atau POJO) yang sesuai berdasarkan struktur setiap tabel untuk menyelesaikan operasi dasar tabel.
Definisi Javabean di atas satu tabel kadang -kadang tidak dapat memenuhi kebutuhan bisnis. Dalam bisnis, objek blog harus memiliki informasi tentang penulisnya dan daftar artikel, seperti yang ditunjukkan pada gambar di bawah ini:
Jika Anda ingin mendapatkan contoh dari kelas semacam itu, Anda perlu setidaknya beberapa langkah:
1. Permintaan informasi blog melalui ID blog di tabel blog, dan tetapkan kueri blogid dan judul untuk objek blog;
2. Menurut kueri AuthorID dalam informasi blog, buka tabel penulis untuk mendapatkan informasi penulis yang sesuai, dapatkan objek penulis, dan kemudian tetapkan ke objek blog;
3. Menurut BlogID, query daftar artikel Posting yang sesuai di tabel Posting dan tetapkan Daftar <Post> objek ke objek blog;
Dengan cara ini, setidaknya tiga pernyataan kueri dipanggil di lapisan bawah. Silakan lihat kode berikut:
/** Dapatkan objek BlogInfo melalui BlogID*/ Public Static BlogInfo OrganicQueryontest (String BlogID) {BigDecimal id = new BigDecimal (blogID); Sesi sqlsession = sqlSessionfactory.opensession (); BlogInfo BlogInfo = new blogInfo (); // 1. Permintaan objek blog menurut blogID dan atur nilainya ke bloginfo blog blog = (blog) session.selectone ("com.foo.bean.blogmapper.selectbyprimarykey", id); blogInfo.setBlogid (blog.getBlogid ()); blogInfo.settitle (blog.gettitle ()); // 2. Menurut AuthorID di blog, masukkan database untuk meminta informasi penulis dan menetapkan hasilnya ke penulis objek BlogInfo penulis = (penulis) session.selectone ("com.foo.bean.authormapper.selectbyprimarykey", blog.getauthorid ()); BlogInfo.setAuthor (penulis); // 3. Query The Posts Object dan atur ke postingan daftar blogInfo = session.selectList ("com.foo.bean.postmapper.selectbyblogid", blog.getBlogid ()); BlogInfo.setPosts (Posting); // Cetak objek dalam bentuk JSON String JSONObject Object = new jsonObject (blogInfo); System.out.println (Object.ToString ()); mengembalikan BlogInfo; }Dari kode di atas, kita dapat melihat bahwa lebih merepotkan untuk mendapatkan objek BlogInfo. Anda harus menghubungi kueri basis data secara total tiga kali, mendapatkan informasi yang diperlukan, dan kemudian merakit objek BlogInfo.
Pernyataan Pernyataan Nested
Mybatis menyediakan mekanisme yang disebut permintaan pernyataan bersarang, yang dapat sangat menyederhanakan operasi di atas, dan menambahkan konfigurasi dan kode sebagai berikut:
<resultMap type = "com.foo.bean.bloginfo" id = "blogInfo"> <id kolom = "blog_id" properti = "blogId" /> <hasil kolom = "judul" properti = "title" /> <asosiasi properti = "penulis" kolom = "blog_author_id" javatype = "com.fooo.bean" blog_author_id "javatype =" com.foo.bean " 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"> pilih b.blog_id, b.title, b.author_id sebagai blog_author_id dari louluan.blog b di mana b.blog_id = #{blogid, jdbctype = desimal} </select> /** Dapatkan objek BlogInfo melalui BlogID*/ Public Static BlogInfo NestedQueryontest (String BlogID) {BigDecimal ID = new BigDecimal (blogID); Sesi sqlsession = sqlSessionfactory.opensession (); BlogInfo BlogInfo = new blogInfo (); blogInfo = (blogInfo) session.selectone ("com.foo.bean.blogmapper.querybloginfobyid", id); Objek jsonObject = new jsonObject (blogInfo); System.out.println (Object.ToString ()); mengembalikan BlogInfo; }Kueri sebelumnya dapat sepenuhnya direalisasikan melalui kode di atas. Di sini kita hanya membutuhkan blogInfo = (blogInfo) session.selectone ("com.foo.bean.blogmapper.querybloginfobyid", id); Dalam kode, kita bisa mendapatkan objek BlogInfo yang kompleks.
Prinsip kueri pernyataan bersarang
Dalam kode di atas, mybatis akan melakukan proses berikut:
1. Pertama -tama jalankan pernyataan querybloginfobyid yang sesuai untuk mendapatkan hasil hasil yang diatur dari tabel blog;
2. Ambil catatan valid berikutnya dari hasil Hasil, dan kemudian buat objek BlogInfo yang sesuai berdasarkan spesifikasi pemetaan yang ditentukan oleh HasilMap.
3. Ketika Anda ingin menetapkan atribut penulis di BlogInfo, Anda menemukan bahwa ada pertanyaan terkait. Pada saat ini, MyBatis pertama -tama akan menjalankan pernyataan kueri pilih untuk mendapatkan hasil yang dikembalikan dan mengatur hasilnya ke atribut penulis bloginfo;
4. Saat menetapkan posting BlogInfo, proses serupa juga ada.
5. Ulangi 2 langkah sampai hasil. next () == false;
Berikut ini adalah diagram skematik dari proses penugasan konstruksi objek bloginfo:
Fungsi yang sangat baik dari jenis pertanyaan bersarang yang terkait ini adalah bahwa ia dapat menggunakan kembali pernyataan SELECT dan membangun objek yang kompleks melalui kombinasi antara pernyataan terpilih sederhana. Dua pernyataan terpilih yang bersarang di atas com.foo.bean.authormper.selectbyprimarykey dan com.foo.bean.postmapper.selectbyblogid dapat digunakan secara mandiri.
N+1 masalah
Kerugiannya juga cukup jelas: masalah yang disebut N+1. Kueri bersarang yang terkait menunjukkan hasil yang ditetapkan, dan kemudian kueri terkait dilakukan berdasarkan setiap catatan dari set hasil ini.
Sekarang anggaplah hanya ada satu pertanyaan bersarang (yaitu, ada tag asosiasi di dalam HasilMap), dan jumlah entri yang dikembalikan oleh kueri adalah n, maka pernyataan kueri yang terkait akan dieksekusi N kali, ditambah permintaan itu sendiri mengembalikan hasil yang ditetapkan untuk kueri sekali, dan total n+1 kali diperlukan untuk mengakses basis data. Jika N relatif besar, konsumsi akses basis data seperti itu sangat besar! Oleh karena itu, pengguna yang menggunakan kueri pernyataan bersarang semacam ini harus mempertimbangkan dengan cermat untuk memastikan bahwa nilai N tidak terlalu besar.
Sebagai contoh, pernyataan SELECT itu sendiri akan mengembalikan set hasil dengan com.foo.bean.blogmapper.querybloginfobyId dengan 1. Karena memiliki dua kueri pernyataan terkait, ia perlu mengakses database 1* (1+1) = 3 kali total.
Kueri hasil bersarang
Pernyataan bersarang yang menanyakan dapat menyebabkan waktu akses basis data yang tidak pasti, yang dapat mempengaruhi kinerja. Mybatis juga mendukung semacam pertanyaan hasil bersarang: yaitu, untuk permintaan satu-ke-banyak, banyak-ke-banyak, dan banyak situasi satu-ke-satu, Mybatis mencari hasil dari database yang diperlukan, dan kemudian mengonversi hasilnya berdasarkan hubungan satu-ke-banyak, banyak-ke-satu, banyak-ke-many dan banyak konfigurasi dan banyak konfigurasi dan banyak konfigurasi dan banyak-ke-manym.
Mendefinisikan kembali peta hasil bloginfo
<resultMap type = "com.foo.bean.bloginfo" id = "blogInfo"> <id kolom = "blog_id" properti = "blogid"/> <column = "title" properti = "title"/> <asosiasi property = "author" column = "blog_author_id" javatype = "com.fooo.bean =" blog_Author_id "javatype =" com.fooo.bean "colume =" "colol" <"ID" colol "<" colol "<" IDean = "como.aTor" colol "columh" columhor = "col" columor = "col" colol " column="user_name" property="userName"/> <result column="password" property="password"/> <result column="email" property="email"/> <result column="biography" property="biography"/> </association> <collection property="posts" column="blog_post_id" ofType="com.foo.bean.Post"> <id column="post_id" property="postId"/> <result kolom = "blog_id" properti = "blogId"/> <hasil kolom = "create_time" properti = "createTime"/> <column column = "subjek" properti = "subjek"/> <column hasil = "body" properti = "body"/> <hasil kolom = "draft" properti = "draft"/> </collection> </resultMap>
Pernyataan SQL yang sesuai adalah sebagai berikut:
<pilih id = "queryAllBlogInfo" resultMap = "blogInfo"> pilih b.blog_id, b.title, b.author_id sebagai blog_author_id, a.author_id, a.user_name, p.password, a.mail, a.biography, p.post_id, p.blog_id, p.paspody, a.preate, a.peate, p.post_id, p.blog_id, B Left Outer gabungan penulis A di b.author_id = a.author_id kiri gabungan luar pos p pada p.blog_id = b.blog_id </pilih>
/** Dapatkan semua informasi tentang semua blog*/ Bloginfo public static NestedResultontest () {SQLSession Session = sqlSessionFactory.opensession (); BlogInfo BlogInfo = new blogInfo (); blogInfo = (blogInfo) session.selectone ("com.foo.bean.blogmapper.queryallbloginfo"); Objek jsonObject = new jsonObject (blogInfo); System.out.println (Object.ToString ()); mengembalikan BlogInfo; } Langkah Eksekusi untuk Kueri Hasil Berasal:
1. Lakukan operasi gabungan berdasarkan hubungan tabel yang sesuai untuk mendapatkan set hasil;
2. Menurut Hasil yang ditetapkan informasi dan informasi definisi Hasil dari BlogInfo, Assemble dan tetapkan hasil yang dikembalikan yang ditetapkan dalam memori untuk membangun BlogInfo;
3. Mengembalikan daftar hasil yang dibangun <BOGNINFO> Hasil.
Untuk kueri hasil yang terkait, jika itu adalah hubungan banyak-ke-satu, itu dikonfigurasi oleh <asosiasi properti = "penulis" kolom = "blog_author_id" javatype = "com.foo.bean.author">. Mybatis akan mengambil data dari memori melalui nilai otor_id yang sesuai dengan properti kolom dan merangkumnya menjadi objek penulis;
Jika itu adalah hubungan satu-ke-banyak, sama seperti hubungan antara blog dan posting, itu dikonfigurasi oleh <collection properti = "post" kolom = "blog_post_id" oftype = "com.foo.bean.post">, mybatis menggunakan blog_id untuk mengambil objek posting dalam memori dan membenarkan mereka ke dalam daftar <post>;
Untuk menanyakan hasil yang terkait, Anda hanya perlu meminta database sekali, dan kemudian integrasi dan perakitan hasil semuanya ditempatkan dalam memori.
Di atas adalah untuk menunjukkan pemrosesan objek satu-ke-banyak dan banyak-ke-satu dengan menanyakan semua informasi blog.
PS: Contoh pemetaan asosiasi diri:
Kelas Entitas
modul kelas publik {private int id; kunci string pribadi; nama string pribadi; Modul Pribadi ParentModule; Daftar Pribadi <Todule> Anak -anak; URL string pribadi; sortir int pribadi; Tampilkan String Pribadi; Private String del; publik int getId () {return id; } public void setid (int id) {this.id = id; } public String getKey () {return key; } public void setKey (tombol string) {this.key = key; } public string getName () {return name; } public void setName (name string) {this.name = name; } modul publik getParentModule () {return parentModule; } public void setParentModule (module parentModule) {this.parentModule = parentModule; } public String getUrl () {return url; } public void setUrl (string url) {this.url = url; } public int getSort () {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; } Daftar Publik <Todule> getChildrenModules () {return childrenModules; } public void setChildrenModules (Daftar <Todule> ChildrenModules) {this.childrenModules = ChildrenSmodules; }} Kode XML: <mapper namespace = "com.sagaware.caraccess.mapper.modulemapper"> <resultMap type = "module" id = "moduleresultMap"> <id properti = "id" kolom = "module_id"/> <hasil hasil = "key" kolom = "module_key"//<name = "name =" name = "NAMA =" KUNCI "KOLOM =" MODULE_KEY "/> <NAMA =" NAMA = "COLUMNE =" MODLE "/MODLET" MODLE_KEY "/<NAMA" kolom = "module_url"/> <properti result = "sort" kolom = "module_sort"/> <properti hasil = "tunjukkan" kolom = "module_show"/> <properti hasil = "del" kolom = "module_del"/> <!-query Modul Parent-> <asosiasi properti = "ParentModule" COLMOM = "MODULE_PARENT" PARURY " submodule-> <collection properti = "ChildrenModules" kolom = "module_id" select = "getchildrenmodules"/> </richmap> <pilih id = "getModules" parameTerType = "string" resultMap = "moduleresultMap"> Pilih * dari tb_module di mana module_id = 2 </"moduleSultMap"> dari tb_module di mana module_id = "2 </" moderTypby = "gets =" gets = "gets =" gets = "gets =" gets = "gets =" gets = "gets =" gets = "get =" gets = "get =" gets = "get =" good "get = get =" get "get =" get "get =" get "get =" get "gets =" get "gets =" get ' resultMap = "moduleresultMap"> pilih * dari tb_module di mana module_id = #{module_id} </pilih> <pilih id = "getchildrenmodues" parameTerType = "int" hancur = "moduleresultMap"> dari tb_module di mana module_parent_id = {} {module_id = {module_id = {moduleR = {moduleR = {moduleR = {moduleR =