程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 實例講授Java的MyBatis框架對MySQL中數據的聯系關系查詢

實例講授Java的MyBatis框架對MySQL中數據的聯系關系查詢

編輯:關於JAVA

實例講授Java的MyBatis框架對MySQL中數據的聯系關系查詢。本站提示廣大學習愛好者:(實例講授Java的MyBatis框架對MySQL中數據的聯系關系查詢)文章只能為提供參考,不一定能成為您想要的結果。以下是實例講授Java的MyBatis框架對MySQL中數據的聯系關系查詢正文


mybatis 供給了高等的聯系關系查詢功效,可以很便利地將數據庫獲得的成果集映照到界說的Java Bean 中。上面經由過程一個實例,來展現一下Mybatis關於罕見的一對多和多對一關系龐雜映照是如何處置的。
設計一個簡略的博客體系,一個用戶可以開多個博客,在博客中可以揭橥文章,許可揭橥評論,可認為文章加標簽。博客體系重要有以下幾張表組成:
Author表:作者信息表,記載作者的信息,用戶名和暗碼,郵箱等。
Blog表   :  博客表,一個作者可以開多個博客,即Author和Blog的關系是一對多。
Post表  : 文章記載表,記載文章揭橥時光,題目,注釋等信息;一個博客下可以有許多篇文章,Blog 和Post的關系是一對多。
Comments表:文章評論表,記載文章的評論,一篇文章可以有許多個評論:Post和Comments的對應關系是一對多。
Tag表:標簽表,表現文章的標簽分類,一篇文章可以有多個標簽,而一個標簽可以運用到分歧的文章上,所以Tag和Post的關系是多對多的關系;(Tag和Post的多對多關系經由過程Post_Tag表表現)
Post_Tag表: 記載 文章和標簽的對應關系。

普通情形下,我們會依據每張表的構造 創立與此絕對應的JavaBean(或許Pojo),來完成對表的根本CRUD操作。

上述對單個表的JavaBean界說有時刻不克不及知足營業上的需求。在營業上,一個Blog對象應當有其作者的信息和一個文章列表,以下圖所示:

假如想獲得如許的類的實例,則最最少要有一下幾步:
1. 經由過程Blog 的id 到Blog內外查詢Blog信息,將查詢到的blogId 和title 賦到Blog對象內;
2. 依據查詢到到blog信息中的authorId 去 Author表獲得對應的author信息,獲得Author對象,然後賦到Blog對象內;
3. 依據 blogId 去 Post內外查詢 對應的 Post文章列表,將List<Post>對象賦到Blog對象中;
如許的話,在底層最最少挪用三次查詢語句,請看以下的代碼:

/* 
 * 經由過程blogId獲得BlogInfo對象 
 */ 
public static BlogInfo ordinaryQueryOnTest(String blogId) 
{ 
 BigDecimal id = new BigDecimal(blogId); 
 SqlSession session = sqlSessionFactory.openSession(); 
 BlogInfo blogInfo = new BlogInfo(); 
 //1.依據blogid 查詢Blog對象,將值設置到blogInfo中 
 Blog blog = (Blog)session.selectOne("com.foo.bean.BlogMapper.selectByPrimaryKey",id); 
 blogInfo.setBlogId(blog.getBlogId()); 
 blogInfo.setTitle(blog.getTitle()); 
  
 //2.依據Blog中的authorId,進入數據庫查詢Author信息,將成果設置到blogInfo對象中 
 Author author = (Author)session.selectOne("com.foo.bean.AuthorMapper.selectByPrimaryKey",blog.getAuthorId()); 
 blogInfo.setAuthor(author); 
  
 //3.查詢posts對象,設置進blogInfo中 
 List posts = session.selectList("com.foo.bean.PostMapper.selectByBlogId",blog.getBlogId()); 
 blogInfo.setPosts(posts); 
 //以JSON字符串的情勢將對象打印出來 
 JSONObject object = new JSONObject(blogInfo); 
 System.out.println(object.toString()); 
 return 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" column="blog_author_id" 
  javaType="com.foo.bean.Author" 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 
 B.BLOG_ID, 
 B.TITLE, 
 B.AUTHOR_ID AS BLOG_AUTHOR_ID 
 FROM LOULUAN.BLOG B 
 where B.BLOG_ID = #{blogId,jdbcType=DECIMAL} 
</select> 

/* 
 * 經由過程blogId獲得BlogInfo對象 
 */ 
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; 
} 

經由過程上述的代碼完整可以完成後面的誰人查詢。這裡我們在代碼裡只須要 blogInfo = (BlogInfo)session.selectOne("com.foo.bean.BlogMapper.queryBlogInfoById",id);一句便可獲得到龐雜的blogInfo對象。

嵌套語句查詢的道理
在下面的代碼中,Mybatis會履行以下賤程:
1.先履行 queryBlogInfoById 對應的語句從Blog內外獲得到ResultSet成果集;
2.掏出ResultSet下一條有用記載,然後依據resultMap界說的映照規格,經由過程這筆記錄的數據來構建對應的一個BlogInfo 對象。
3. 當要對BlogInfo中的author屬性停止賦值的時刻,發明有一個聯系關系的查詢,此時Mybatis會先履行這個select查詢語句,獲得前往的成果,將成果設置到BlogInfo的author屬性上;
4. 對BlogInfo的posts停止賦值時,也有上述相似的進程。
5. 反復2步調,直至ResultSet. next () == false;
以下是blogInfo對象結構賦值進程表示圖:

這類聯系關系的嵌套查詢,有一個異常好的感化就是:可以重用select語句,經由過程簡略的select語句之間的組合來結構龐雜的對象。下面嵌套的兩個select語句com.foo.bean.AuthorMapper.selectByPrimaryKey和com.foo.bean.PostMapper.selectByBlogId完整可以自力應用。

N+1成績
它的弊病也比擬顯著:即所謂的N+1成績。聯系關系的嵌套查詢顯示獲得一個成果集,然後依據這個成果集的每筆記錄停止聯系關系查詢。
如今假定嵌套查詢就一個(即resultMap 外部就一個association標簽),現查詢的成果集前往條數為N,那末聯系關系查詢語句將會被履行N次,加上本身前往成果集查詢1次,共須要拜訪數據庫N+1次。假如N比擬年夜的話,如許的數據庫拜訪消費長短常年夜的!所以應用這類嵌套語句查詢的應用者必定要斟酌鄭重斟酌,確保N值不會很年夜。
以下面的例子為例,select 語句自己會前往com.foo.bean.BlogMapper.queryBlogInfoById 條數為1 的成果集,因為它有兩條聯系關系的語句查詢,它須要共拜訪數據庫 1*(1+1)=3次數據庫。

嵌套成果查詢
嵌套語句的查詢會招致數據庫拜訪次數不定,進而有能夠影響到機能。Mybatis還支撐一種嵌套成果的查詢:即關於一對多,多對多,多對一的情形的查詢,Mybatis經由過程結合查詢,將成果從數據庫內一次性查出來,然後依據其一對多,多對一,多對多的關系和ResultMap中的設置裝備擺設,停止成果的轉換,構建須要的對象。
從新界說BlogInfo的成果映照 resultMap

<resultMap type="com.foo.bean.BlogInfo" id="BlogInfo"> 
 <id column="blog_id" property="blogId"/> 
 <result column="title" property="title"/> 
 <association property="author" column="blog_author_id" javaType="com.foo.bean.Author"> 
  <id column="author_id" property="authorId"/> 
  <result 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 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="draft"/> 
 </collection> 
  
</resultMap> 

對應的sql語句以下:

<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 
LEFT OUTER JOIN AUTHOR A 
 ON B.AUTHOR_ID = A.AUTHOR_ID 
LEFT OUTER JOIN POST P 
 ON P.BLOG_ID = B.BLOG_ID 
</select> 

/* 
 * 獲得一切Blog的一切信息 
 */ 
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; 
} 

嵌套成果查詢的履行步調:
1.依據表的對應關系,停止join操作,獲得到成果集;
2. 依據成果集的信息和BlogInfo 的resultMap界說信息,對前往的成果集在內存中停止組裝、賦值,結構BlogInfo;
3. 前往結構出來的成果List<BlogInfo> 成果。
關於聯系關系的成果查詢,假如是多對一的關系,則經由過程形如 <association property="author" column="blog_author_id" javaType="com.foo.bean.Author"> 停止設置裝備擺設,Mybatis會經由過程column屬性對應的author_id 值去從內存中取數據,而且封裝成Author對象;
假如是一對多的關系,就如Blog和Post之間的關系,經由過程形如 <collection property="posts" column="blog_post_id" ofType="com.foo.bean.Post">停止設置裝備擺設,MyBatis經由過程 blog_Id去內存中取Post對象,封裝成List<Post>;
關於聯系關系成果的查詢,只須要查詢數據庫一次,然後對成果的整合和組裝全體放在了內存中。
以上是經由過程查詢Blog一切信息來演示了一對多和多對一的映照對象處置。

ps:本身聯系關系映照示例:
實體類

public class Module { 
 
 private int id; 
 private String key; 
 private String name; 
 private Module parentModule; 
 private List<Module> childrenModules; 
 private String url; 
 private int sort; 
 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 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<Module> getChildrenModules() { 
  return childrenModules; 
 } 
 
 public void setChildrenModules(List<Module> childrenModules) { 
  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="module_key"/> 
  <result property="name" column="module_name"/> 
  <result property="url" column="module_url"/> 
  <result property="sort" column="module_sort"/> 
  <result property="show" column="module_show"/> 
  <result property="del" column="module_del"/> 
   
  <!-- 查詢父模塊 --> 
  <association property="parentModule" column="module_parent_id" select="getModulesById" /> 
   
  <!-- 查詢子模塊 --> 
  <collection property="childrenModules" column="module_id" select="getChildrenModues" /> 
   
 </resultMap> 
  
 <select id="getModules" parameterType="String" resultMap="moduleResultMap"> 
  select * from tb_module where module_id=2 
 </select> 
  
 <select id="getModulesById" parameterType="int" 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> 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved