Mybatis предоставляет функции запросов расширенной ассоциации, которые могут легко отобразить наборы результатов, полученные базой данных с определенными Java Feans. Ниже приведен пример, чтобы показать, как Mybatis имеет дело с общими сложными сопоставлением со стороны отношений.
Разработайте простую систему блога, где пользователь может открыть несколько блогов, публиковать статьи в блоге, разрешать комментарии и отметить статьи. Система блогов в основном состоит из следующих таблиц:
Таблица авторов: Информация о авторе, записи информации автора, имя пользователя и пароль, адрес электронной почты и т. Д.
Таблица блога: таблица блога, автор может открыть несколько блогов, то есть отношения между автором и блогом-один-один.
Таблица публикации: таблица записей статьи, запись времени публикации, название, текст и другая информация; В блоге может быть много статей, и отношения между блогом и постом-один-один.
Таблица комментариев: Таблица комментариев статьи, записи статьи Комментарии, в статье может быть много комментариев: Переписка между публикацией и комментариями-один-один.
Таблица тегов: таблица тегов, которая представляет классификацию тегов статьи. Статья может иметь несколько тегов, а тег может быть применен к разным статьям, поэтому взаимосвязь между тегом и постом-это многие ко многим отношениям; (Многие отношения между тегом и постом отражаются через таблицу post_tag)
Таблица post_tag: записывает переписку между статьями и тегами.
Вообще говоря, мы создадим соответствующее Javabean (или POJO) на основе структуры каждой таблицы, чтобы завершить основную работу таблицы.
Вышеупомянутое джабеанское определение одной таблицы иногда не может удовлетворить потребности бизнеса. В бизнесе объект блога должен иметь информацию о его авторе и списке статей, как показано на рисунке ниже:
Если вы хотите получить экземпляр такого класса, вам нужно хотя бы несколько шагов:
1. Запросите информацию о блоге через идентификатор блога в таблице блога и назначить запрос BlogId и заголовок объекту блога;
2. Согласно запросу авторидации в информации блога, перейдите в таблицу авторов, чтобы получить соответствующую информацию о авторе, получить объект автора, а затем назначить его объекту блога;
3. Согласно BlogyID, запросите соответствующий список статьи о публикации в таблице сообщений и назначить объект «post>» объекту блога;
Таким образом, по крайней мере три оператора запроса вызываются на нижнем слое. Пожалуйста, смотрите следующий код:
/** Получить объект BlogInfo через BlogId*/ public Static BlogInfo OrganicQueryOntest (String blogId) {BigDecimal ID = New BigDecimal (blogiD); SQLSession Session = SQLSessionFactory.Opensession (); Bloginfo bloginfo = new bloginfo (); // 1. Запросить объект блога в соответствии с BlogID и установить ценность для блога блога BlogInfo = (блог) Session.selectone ("com.foo.bean.blogmapper.selectbyprimarykey", id); bloginfo.setblogid (blog.getblogid ()); bloginfo.settitle (blog.getTitle ()); // 2. Согласно Authorid в блоге, введите базу данных, чтобы запросить информацию автора, и установите результат для автора объекта BlogInfo Автор = (Автор) Session.selectone ("com.foo.bean.authormapper.selectbyprimarykey", blog.getAuthorid ()); bloginfo.setauthor (автор); // 3. Запросите объект сообщений и установите его в списки BlogInfo posts = session.selectlist ("com.foo.bean.postmapper.selectbyblogid", blog.getblogid ()); bloginfo.setposts (сообщения); // распечатать объект в форме json string jsonObject object = new jsonObject (blogInfo); System.out.println (object.toString ()); вернуть BlogInfo; }Из приведенного выше кода мы видим, что получить объект BlogInfo. Вы должны позвонить в общий запрос в базе данных три раза, получить необходимую информацию, а затем собрать объект BlogInfo.
Вложенное заявление запрос
Mybatis предоставляет механизм, называемый вложенным запросом заявления, который может значительно упростить вышеуказанные операции и добавить конфигурацию и код следующим образом:
<resultMap type = "com.foo.bean.bloginfo" id = "bloginfo"> <id column = "blog_id" property = "blogid" /> <result column = "title" Property = "title" /> <Association Property = "Author" COLBER = "blog_author_id" javatype = "com.foo.bean.author" select = "com.foo.bean.authormapper.selectbyprimarykey"> </association> <collection property = "posts" column = "blog_id" optype = "com.foo.bean.post" select = "com.foo.bean.postmapper.selectbyblogid"> </collection> </refulmap> <select Id = "QueryBoById"> </collection> </refulmap> <select Id = "QueryboById" ResultMap = "blogInfo" parameterType = "java.math.bigdecimal"> select b.blog_id, b.title, b.author_id as blog_author_id из louluan.blog b, где b.blog_id = #{blogid, jdbctepe = decimal} </select> /** Получить объект BlogInfo через 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 ()); вернуть BlogInfo; }Предыдущий запрос может быть полностью реализован с помощью приведенного выше кода. Здесь нам нужна только сеанс blogInfo = (bloginfo). Selectone ("com.foo.bean.blogmapper.querybloginfobyid", id); В коде мы можем получить сложный объект BlogInfo.
Принцип вложенного заявления запроса
В приведенном выше коде Mybatis выполнит следующий процесс:
1. Сначала выполните соответствующий оператор Querybloginfobyid, чтобы получить набор результатов результата из таблицы блога;
2. Выберите следующую допустимую запись о результатах, а затем создайте соответствующий объект BlogInfo на основе спецификаций отображения, определенных ResultMap.
3. Когда вы хотите назначить атрибут автора в BlogInfo, вы обнаружите, что есть связанный запрос. В настоящее время Mybatis сначала выполнит оператор SELECT Query, чтобы получить возвращенный результат и установить результат атрибуту автора BlogInfo;
4. При назначении сообщений BlogInfo также присутствуют аналогичные процессы.
5. Повторите 2 шага до результата. next () == false;
Ниже приведена схематическая схема процесса назначения объектов BlogInfo:
Очень хорошая функция этого вида связанного вложенного запроса заключается в том, что он может повторно использовать оператор SELECT и построить сложные объекты с помощью комбинации простых операторов SELECT. Два выбранных утверждения, вложенных выше com.foo.bean.authormapper.selectbyprimarykey и com.foo.bean.postmapper.selectbyblogid, можно использовать независимо.
N+1 проблема
Его недостатки также довольно очевидны: так называемая проблема N+1. Связанный вложенный запрос показывает набор результатов, а затем соответствующий запрос выполняется на основе каждой записи этого набора результатов.
Теперь предположим, что существует только один вложенный запрос (то есть внутри Mag -MAP есть ассоциация), а количество записей, возвращаемых запросом, равна n, тогда соответствующий оператор запроса будет выполнены n раз, плюс сам запрос возвращает результат, установленную для запроса один раз, и общая сумма N+1 раз требуется для доступа к базе базы базы. Если N относительно большой, такое потребление доступа к базе данных очень большое! Следовательно, пользователи, которые используют этот вид вложенного запроса на выписку, должны тщательно рассмотреть, чтобы значение n не очень большое.
В качестве примера, сам оператор SELECT вернет набор результатов с com.foo.bean.blogmapper.querybloginfobyid с 1. Поскольку у него есть два связанных запроса оператора, он должен получить доступ к базе данных 1* (1+1) = 3 раза.
Вложенный запрос результата
Запрос вложенных заявлений может вызвать неопределенное время доступа к базе данных, что может повлиять на производительность. Mybatis также поддерживает своего рода вложенные запросы результатов: то есть, для запроса ситуаций от одного ко многим, многим-многим и многим к одному, в один раз ищут результаты базы данных с помощью совместного запроса, а затем преобразует результаты, основанные на его объектах, которые могут быть связаны с одним, во многих отношениях и конфигурации в результате, и создания.
Переопределить карту результатов BlogInfo
<resultMap type = "com.foo.bean.bloginfo" id = "bloginfo"> <id column = "blog_id" property = "blogid"/> <result column = "title" Property = "tit column = "user_name" Property = "username"/> <result column = "password" property = "password"/> <result column = "email" property = "email"/> <result column = "biograph" property = "biography"/> </association> <collection property = "posts" column = "blog_post_id" optype = "com.foo.bean.pean.pean.post"> "id_id_id"/"oftype =" com.foo.bean.pean.pean.pean.pean.pean.pean.pean.pean.pean.pean.post " <Результат Column = "blog_id" Property = "blogId"/> <result column = "create_time" property = "createTime"/> <result column = "subject" property = "subject"/> <result column = "body" property = "body"/> <result column = "draft" property = "/> </collection> </resultmap>
Соответствующие операторы SQL следующие:
<select id = "Queryallbloginfo" resultMap = "blogInfo"> select b.blog_id, b.title, b.author_id as blog_author_id, atuthor_id, a.user_name, a.password, a.email, a.biography, p.post_id, p.blog_id as blog Блог B остается внешнее соединение Автор A на B.Author_ID = A.Author_ID LEAT OUTER ICTE POST POST P ON P.BLOG_ID = B.BLOG_ID </select>
/** Получите всю информацию обо всех блогах*/ public static bloginfo indestResultontest () {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 ()); вернуть BlogInfo; } Шаги выполнения для вложенного запроса на результат:
1. Выполнить операции соединения на основе соответствующей связи таблицы, чтобы получить набор результатов;
2. В соответствии с информацией о наборе результатов и информации о определении ResultMap в блоге, собирайте и назначьте возвращенный результат, набор в памяти для построения BlogInfo;
3. Верните построенный список результатов <goolinfo> результат.
Для соответствующего запроса на результат, если это соотношение для многих к одному, он настроен <association property = "Автор" Column = "blog_author_id" javatype = "com.foo.bean.author">. Mybatis будет получать данные из памяти через значение Author_id, соответствующее свойству столбца, и инкапсулировать их в объект автора;
Если это отношения с одним ко многим, точно так же, как отношения между блогом и постом, он настроен <collection property = "posts" column = "blog_post_id" optype = "com.foo.bean.post">, mybatis использует blog_id для извлечения объектов Post в памяти и инкапсулирует их в список <post>;
Для запроса связанных результатов вам нужно только один раз запросить базу данных, а затем интеграция и сборка результатов все помещены в память.
Выше приведено продемонстрировать обработку объектов от одного ко многим и много-одному, путем запроса всей информации в блоге.
PS: пример картирования самосознания:
Класс сущности
модуль открытого класса {private Int Id; частный ключ строки; Приватное название строки; частный модуль ParentModule; частный список <Модуль> Детские модулы; частная строковая URL; частный int sort; частное строковое шоу; частная строка del; public int getId () {return id; } public void setId (int id) {this.id = id; } public String getKey () {return Key; } public void setKey (String Key) {this.key = key; } public String getName () {return name; } public void setName (string name) {this.name = name; } public module 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; } public List <dodule> getChildrenModules () {return gidsmodules; } public void setChildrenModules (список <doldule> kidsmodules) {this.childrenModules = childrenmodules; }} XML -код: <mapper namespace = "com.sagaware.caraccess.mapper.modulemapper"> <resultmap type = "module" id = "moduleresultmap"> <id property = "id" column = "module_id"/> <result property = "key" column_key "/> <result_fortive =" column "=" module_name "/"/> ressult "/> ressult"/> ressure "/"/> ressuraph "/> ressult" column = "module_url"/> <result property = "sort" column = "module_sort"/> <result property = "show" column = "module_show"/> <result property = "del" column = "module_del"/> <!-Запрос родительского модуля-> <ассоциация = "parentmodule" column_parent_perent_id "select =" getModule "/>>-Querery Querery Quererulue"/> 'Querery Quererulue "! Submodule-> <Collection Property = "kidsModules" colun = "module_id" select = "getChildrenModules"/> </resultMap> <select id = "getModules" parameterType = "string" resultMap = "moduleresultmap"> select * from tb_module, где module_id = 2 </select> <see addrulue = "getModule" intemodule "intemodule" intemodule ". resultMap="moduleResultMap"> select * from tb_module where module_id = #{module_id} </select> <select id="getChildrenModues" parameterType="int" resultMap="moduleResultMap"> select * from tb_module where module_parent_id = #{module_id} </select> </mapper>