mybatis關聯(lián)關系映射的實現(xiàn)
1. 介紹
在當今的軟件開發(fā)中,與數(shù)據(jù)庫進行交互是一項至關重要的任務。開發(fā)人員需要能夠輕松、高效地執(zhí)行數(shù)據(jù)庫操作,同時又要保持代碼的可維護性和靈活性。這正是MyBatis這個數(shù)據(jù)庫訪問框架應運而生的背景所在。
背景
數(shù)據(jù)庫是許多應用程序的核心組成部分,用于存儲和管理數(shù)據(jù)。然而,與數(shù)據(jù)庫進行交互通常涉及到編寫大量的SQL查詢語句,以及處理結果集和數(shù)據(jù)庫連接等繁瑣的任務。這不僅使開發(fā)工作復雜化,還容易引入安全漏洞和性能問題。
在過去,JDBC(Java Database Connectivity)是與數(shù)據(jù)庫交互的主要方式,它要求開發(fā)人員手動管理數(shù)據(jù)庫連接、編寫SQL語句和處理結果集。這種方式存在以下挑戰(zhàn):
冗余的代碼: 大量的重復性代碼需要編寫,包括數(shù)據(jù)庫連接的打開和關閉、SQL語句的編寫等。
硬編碼的SQL: SQL語句通常是硬編碼在Java代碼中的,這使得維護和修改變得困難。
安全性問題: 由于直接拼接SQL語句,容易受到SQL注入攻擊的威脅。
缺乏靈活性: 難以處理復雜的數(shù)據(jù)庫操作,如對象關系映射(ORM)和復雜的查詢。
MyBatis的出現(xiàn)解決了這些問題,為Java開發(fā)人員提供了一個強大的數(shù)據(jù)庫訪問框架,它背后的核心理念是將SQL語句從Java代碼中解耦,同時提供了豐富的映射和查詢功能。
MyBatis的特點
MyBatis具有許多優(yōu)點,使其成為數(shù)據(jù)庫訪問的首選框架之一:
SQL和Java代碼的分離: MyBatis允許將SQL語句從Java代碼中獨立出來,存儲在XML文件或注解中,使代碼更易維護和管理。
強大的參數(shù)映射: MyBatis支持多種參數(shù)映射方式,包括基本類型、POJO對象和Map等,使得傳遞參數(shù)變得靈活。
靈活的結果映射: 可以將查詢結果映射到Java對象中,支持一對一、一對多和多對多等關系映射。
自動資源管理: MyBatis自動管理數(shù)據(jù)庫連接的打開和關閉,減輕了開發(fā)人員的負擔。
動態(tài)SQL支持: MyBatis允許在SQL中使用動態(tài)條件,根據(jù)不同情況生成不同的SQL語句。
性能優(yōu)化: MyBatis提供了緩存機制,可以提高查詢性能,同時還支持延遲加載。
豐富的插件機制: 可以通過插件擴展MyBatis的功能,滿足不同項目的需求。
在數(shù)據(jù)庫中,數(shù)據(jù)通常存儲在多個相關聯(lián)的表中,這些表之間存在各種復雜的關系,如一對一、一對多和多對多。為了有效地操作這些復雜的數(shù)據(jù)模型,引入了關聯(lián)關系映射的概念,它在復雜數(shù)據(jù)模型中扮演著至關重要的角色。
什么是關聯(lián)關系映射?
關聯(lián)關系映射是將多個表之間的關聯(lián)關系映射到程序中的對象模型的過程。它的核心目標是:
- 將數(shù)據(jù)庫表之間的關系抽象成對象之間的關系。
- 允許通過對象操作來進行數(shù)據(jù)庫操作,而不是直接使用SQL語句。
這個概念的核心思想是將數(shù)據(jù)庫的復雜性隱藏在應用程序的背后,使開發(fā)人員能夠更自然地處理數(shù)據(jù),而不必深入了解數(shù)據(jù)庫的結構和關系。
為什么關聯(lián)關系映射在復雜數(shù)據(jù)模型中重要?
在復雜的數(shù)據(jù)模型中,表之間的關系往往非常復雜,可能包括:
一對一關系: 例如,一個用戶只有一個個人詳細信息,或一個訂單只有一個送貨地址。
一對多關系: 例如,一個作者可以有多本書,一個班級可以有多名學生。
多對多關系: 例如,多名學生可以選擇多門課程,需要通過關聯(lián)表進行映射。
在處理這些復雜的關系時,直接使用原始的SQL查詢和結果集映射將變得非常繁瑣和復雜。這里是為什么關聯(lián)關系映射如此重要的原因:
抽象復雜性: 關聯(lián)關系映射將數(shù)據(jù)庫的復雜性抽象成了對象模型,使開發(fā)人員無需深入了解數(shù)據(jù)庫細節(jié),從而簡化了開發(fā)過程。
提高可維護性: 通過將關系映射到對象,可以更容易地維護代碼,因為對象模型更加直觀和可理解。
提高開發(fā)效率: 關聯(lián)關系映射框架可以自動生成大部分數(shù)據(jù)庫操作代碼,減少了手動編寫SQL語句的工作量。
增加靈活性: 關聯(lián)關系映射允許進行高級查詢和復雜操作,而不需要深入了解SQL的復雜性。
降低錯誤風險: 通過將關系映射到對象,可以減少手動編寫SQL時可能引入的錯誤,如拼寫錯誤或SQL注入。
總之,關聯(lián)關系映射在復雜數(shù)據(jù)模型中是非常重要的,它提供了一種更高級、更抽象的方式來處理數(shù)據(jù)庫操作,使開發(fā)人員能夠更輕松地應對復雜性,提高代碼的可維護性和開發(fā)效率。這正是許多現(xiàn)代應用程序開發(fā)中不可或缺的一部分。
2. 一對一關系映射
一對一關系映射是指兩個實體之間存在唯一的對應關系,即一個實體只能與另一個實體相對應。例如,一個人只能有一個身份證號碼,一個身份證號碼也只能對應一個人。
一對一關系映射: 在數(shù)據(jù)庫中,可以通過在一個實體表中添加一個外鍵來映射一對一關系。例如,假設我們有兩個實體表:Person(人)和IDCard(身份證)。每個人只能有一個身份證,而每個身份證也只能對應一個人。我們可以在Person表中添加一個外鍵IDCardID,將其與IDCard表的主鍵IDCardID關聯(lián)起來。這樣,每個Person實體都會有一個唯一的IDCardID,從而建立了一對一的關系。
配置generatoeConfig文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" > <generatorConfiguration> <!-- 引入配置文件 --> <properties resource="jdbc.properties"/> <!--指定數(shù)據(jù)庫jdbc驅動jar包的位置--> <classPathEntry location="C:\\temp2\\mvn_repository\\mysql\\mysql-connector-java\\5.1.44\\mysql-connector-java-5.1.44.jar"/> <!-- 一個數(shù)據(jù)庫一個context --> <context id="infoGuardian"> <!-- 注釋 --> <commentGenerator> <property name="suppressAllComments" value="true"/><!-- 是否取消注釋 --> <property name="suppressDate" value="true"/> <!-- 是否生成注釋代時間戳 --> </commentGenerator> <!-- jdbc連接 --> <jdbcConnection driverClass="${jdbc.driver}" connectionURL="${jdbc.url}" userId="${jdbc.username}" password="${jdbc.password}"/> <!-- 類型轉換 --> <javaTypeResolver> <!-- 是否使用bigDecimal, false可自動轉化以下類型(Long, Integer, Short, etc.) --> <property name="forceBigDecimals" value="false"/> </javaTypeResolver> <!-- 01 指定javaBean生成的位置 --> <!-- targetPackage:指定生成的model生成所在的包名 --> <!-- targetProject:指定在該項目下所在的路徑 --> <javaModelGenerator targetPackage="com.zking.model" targetProject="src/main/java"> <!-- 是否允許子包,即targetPackage.schemaName.tableName --> <property name="enableSubPackages" value="false"/> <!-- 是否對model添加構造函數(shù) --> <property name="constructorBased" value="true"/> <!-- 是否針對string類型的字段在set的時候進行trim調(diào)用 --> <property name="trimStrings" value="false"/> <!-- 建立的Model對象是否 不可改變 即生成的Model對象不會有 setter方法,只有構造方法 --> <property name="immutable" value="false"/> </javaModelGenerator> <!-- 02 指定sql映射文件生成的位置 --> <sqlMapGenerator targetPackage="com.zking.mapper" targetProject="src/main/java"> <!-- 是否允許子包,即targetPackage.schemaName.tableName --> <property name="enableSubPackages" value="false"/> </sqlMapGenerator> <!-- 03 生成XxxMapper接口 --> <!-- type="ANNOTATEDMAPPER",生成Java Model 和基于注解的Mapper對象 --> <!-- type="MIXEDMAPPER",生成基于注解的Java Model 和相應的Mapper對象 --> <!-- type="XMLMAPPER",生成SQLMap XML文件和獨立的Mapper接口 --> <javaClientGenerator targetPackage="com.zking.mapper" targetProject="src/main/java" type="XMLMAPPER"> <!-- 是否在當前路徑下新加一層schema,false路徑com.oop.eksp.user.model, true:com.oop.eksp.user.model.[schemaName] --> <property name="enableSubPackages" value="false"/> </javaClientGenerator> <!-- 配置表信息 --> <!-- schema即為數(shù)據(jù)庫名 --> <!-- tableName為對應的數(shù)據(jù)庫表 --> <!-- domainObjectName是要生成的實體類 --> <!-- enable*ByExample是否生成 example類 --> <!--<table schema="" tableName="t_book" domainObjectName="Book"--> <!--enableCountByExample="false" enableDeleteByExample="false"--> <!--enableSelectByExample="false" enableUpdateByExample="false">--> <!--<!– 忽略列,不生成bean 字段 –>--> <!--<!– <ignoreColumn column="FRED" /> –>--> <!--<!– 指定列的java數(shù)據(jù)類型 –>--> <!--<!– <columnOverride column="LONG_VARCHAR_FIELD" jdbcType="VARCHAR" /> –>--> <!--</table>--> <table schema="" tableName="t_hibernate_book" domainObjectName="HBook" enableCountByExample="false" enableDeleteByExample="false" enableSelectByExample="false" enableUpdateByExample="false"> </table> <table schema="" tableName="t_hibernate_book_category" domainObjectName="HBookCategory" enableCountByExample="false" enableDeleteByExample="false" enableSelectByExample="false" enableUpdateByExample="false"> </table> <table schema="" tableName="t_hibernate_category" domainObjectName="HCategory" enableCountByExample="false" enableDeleteByExample="false" enableSelectByExample="false" enableUpdateByExample="false"> </table> <table schema="" tableName="t_hibernate_order" domainObjectName="Order" enableCountByExample="false" enableDeleteByExample="false" enableSelectByExample="false" enableUpdateByExample="false"> </table> <table schema="" tableName="t_hibernate_order_item" domainObjectName="OrderItem" enableCountByExample="false" enableDeleteByExample="false" enableSelectByExample="false" enableUpdateByExample="false"> </table> </context> </generatorConfiguration>
OrderItemVo
package com.liao.vo; import com.liao.model.Order; import com.liao.model.OrderItem; public class OrderItemVo extends OrderItem { private Order order; public Order getOrder() { return order; } public void setOrder(Order order) { this.order = order; } }
OrderItemMapper.xml
<resultMap id="OrderItemMap" type="com.liao.vo.OrderItemVo" > <result column="order_item_id" property="orderItemId" ></result> <result column="product_id" property="productId" ></result> <result column="quantity" property="quantity" ></result> <result column="oid" property="oid" ></result> <association property="order" javaType="com.liao.model.Order"> <result column="order_id" property="orderId" ></result> <result column="order_no" property="orderNo" ></result> </association> </resultMap> <select id="selectByBiid" resultMap="OrderItemMap" parameterType="java.lang.Integer" > SELECT * FROM t_hibernate_order o , t_hibernate_order_item oi WHERE o.order_id = oi.oid AND oi.order_item_id = #{oiid} </select>
OrderItemBiz
package com.liao.biz; import com.liao.vo.OrderItemVo; public interface OrderItemBiz { OrderItemVo selectByBiid(Integer oiid); }
實現(xiàn)OrderItemBiz接口,創(chuàng)建 OrderItemBizImpl
package com.liao.biz; import com.liao.mapper.OrderItemMapper; import com.liao.vo.OrderItemVo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class OrderItemBizImpl implements OrderItemBiz { @Autowired private OrderItemMapper orderItemMapper; @Override public OrderItemVo selectByBiid(Integer oiid) { return orderItemMapper.selectByBiid(oiid); } }
測試
package com.liao.biz; import com.liao.vo.OrderItemVo; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={"classpath:spring-context.xml"}) public class Test01 { ? ? @Autowired ? ? private OrderItemBiz orderItemBiz; ? ? @Before ? ? public void setUp() throws Exception { ? ? } ? ? @After ? ? public void tearDown() throws Exception { ? ? } ? ? @Test ? ? public void selectByBiid() { ? ? ? ? OrderItemVo orderItemVo = orderItemBiz.selectByBiid(27); ? ? ? ? System.out.println(orderItemVo); ? ? ? ? System.out.println(orderItemVo.getOrder()); ? ? } }
3. 一對多關系映射
一對多關系映射是指一個實體可以與多個實體相對應,而多個實體只能與一個實體相對應。例如,一個班級可以有多個學生,但一個學生只能屬于一個班級。
一對多關系映射: 在數(shù)據(jù)庫中,可以通過在多的一方實體表中添加一個外鍵來映射一對多關系。例如,假設我們有兩個實體表:Department(部門)和Employee(員工)。一個部門可以有多個員工,而一個員工只能屬于一個部門。我們可以在Employee表中添加一個外鍵DepartmentID,將其與Department表的主鍵DepartmentID關聯(lián)起來。這樣,每個Employee實體都會有一個對應的DepartmentID,從而建立了一對多的關系。
OrdeVo
package com.liao.vo; import com.liao.model.Order; import com.liao.model.OrderItem; import java.util.ArrayList; import java.util.List; public class OrderVo extends Order { ? ? private List<OrderItem> orderItems = new ArrayList<>(); ? ? public List<OrderItem> getOrderItems() { ? ? ? ? return orderItems; ? ? } ? ? public void setOrderItems(List<OrderItem> orderItems) { ? ? ? ? this.orderItems = orderItems; ? ? } }
OrderMapper.xml
<resultMap id="OrderVoMap" type="com.liao.vo.OrderVo"> ? ? <result column="order_id" property="orderId" ></result> ? ? <result column="order_no" property="orderNo" ></result> ? ? <collection property="orderItems" ofType="com.liao.model.OrderItem"> ? ? ? <result column="order_item_id" property="orderItemId" ></result> ? ? ? <result column="product_id" property="productId" ></result> ? ? ? <result column="quantity" property="quantity" ></result> ? ? ? <result column="oid" property="oid" ></result> ? ? </collection> ? </resultMap> ? <select id="selectByOid" resultMap="OrderVoMap" parameterType="java.lang.Integer" > ? ? ?SELECT * FROM ? ? ?t_hibernate_order o , ? ? ?t_hibernate_order_item oi ? ? ?WHERE o.order_id = oi.oid ? ? ? AND o.order_id = #{oid} ? </select>
在自動生成的 OrderMapper接口中進行增加以下代碼,如下:
OrderVo selectByOid(@Param("oid") Integer oid);
OrderBiz 接口
package com.liao.biz; import com.liao.vo.OrderVo; public interface OrderBiz { ? ? OrderVo selectByOid(Integer oid); }
實現(xiàn) OrderBiz 接口 創(chuàng)建 OrderBizImpl
package com.liao.biz; import com.liao.mapper.OrderMapper; import com.liao.vo.OrderVo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class OrderBizImpl implements OrderBiz { ? ? @Autowired ? ? private OrderMapper orderMapper; ? ? @Override ? ? public OrderVo selectByOid(Integer oid) { ? ? ? ? return orderMapper.selectByOid(oid); ? ? } }
測試
? @Autowired ? ? private OrderBiz orderBiz; ? ? @Test ? ? public void selectByOid() { ? ? ? ? OrderVo orderVo = orderBiz.selectByOid(7); ? ? ? ? System.out.println(orderVo); ? ? ? ? orderVo.getOrderItems().forEach(System.out::println);
4. 多對多關系映射
多對多關系映射是指兩個實體之間存在多對多的對應關系,即一個實體可以與多個實體相對應,同時一個實體也可以與多個實體相對應。例如,一個學生可以選擇多門課程,而一門課程也可以有多個學生選修。在數(shù)據(jù)庫中,多對多關系通常需要通過引入第三個實體(中間表)來實現(xiàn)。
多對多關系映射: 在數(shù)據(jù)庫中,多對多關系通常需要通過引入第三個實體(中間表)來實現(xiàn)。例如,假設我們有兩個實體表:Student(學生)和Course(課程)。一個學生可以選擇多門課程,而一門課程也可以有多個學生選修。我們可以創(chuàng)建一個名為StudentCourse的中間表,其中包含兩個外鍵:StudentID和CourseID,分別與Student表和Course表的主鍵關聯(lián)起來。這樣,每個學生可以在StudentCourse表中有多個對應的CourseID,同時每門課程也可以在StudentCourse表中有多個對應的StudentID,從而建立了多對多的關系。
HBookMapper.xml
<resultMap id="HBookVoMap" type="com.liao.vo.HbookVo" > <result column="book_id" property="bookId"></result> <result column="book_name" property="bookName"></result> <result column="price" property="price"></result> <collection property="categories" ofType="com.liao.model.Category"> <result column="category_id" property="categoryId"></result> <result column="category_name" property="categoryName"></result> </collection> </resultMap> <select id="selectByBookId" resultMap="HBookVoMap" parameterType="java.lang.Integer" > SELECT * FROM t_hibernate_book b, t_hibernate_book_category bc , t_hibernate_category c WHERE b.book_id = bc.bid AND bc.cid = c.category_id AND b.book_id = #{bid} </select>
HBookMapper
HbookVo selectByBookId(@Param("bid") Integer bid);
創(chuàng)建 HBookBiz
package com.liao.biz; import com.liao.vo.HbookVo; import org.apache.ibatis.annotations.Param; public interface HBookBiz { ? ? HbookVo selecByBookId(@Param("bid") Integer bid); }
實現(xiàn) HBookBiz 接口,創(chuàng)建 HBookBizImpl
package com.liao.biz; import com.liao.mapper.HBookMapper; import com.liao.vo.HbookVo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class HBookBizImpl implements HBookBiz { ? ? @Autowired ? ? private HBookMapper hBookMapper; ? ? @Override ? ? public HbookVo selecByBookId(Integer bid) { ? ? ? ? return hBookMapper.selectByBookId(bid); ? ? } }
測試
?@Autowired ? ? private HBookBiz hbookBiz; ? ? @Test ? ? public void selectByBookId() { ? ? ? ? HbookVo hBookVo = hbookBiz.selecByBookId(8); ? ? ? ? System.out.println(hBookVo); ? ? ? ? hBookVo.getCategories().forEach(System.out::println);
5. 總結
MyBatis是一個強大的數(shù)據(jù)庫訪問框架,其中的關聯(lián)關系映射是其核心功能之一。在處理復雜的數(shù)據(jù)模型時,MyBatis關聯(lián)關系映射具有重要性和靈活性,如下所總結:
重要性:
1. 數(shù)據(jù)模型的抽象:
- MyBatis將數(shù)據(jù)庫表之間的關系抽象成對象之間的關系,使開發(fā)人員無需深入了解數(shù)據(jù)庫的復雜性,從而簡化了開發(fā)過程。
2. 提高可維護性:
- 通過將關系映射到對象,代碼更加直觀和可理解,使得代碼的維護和修改變得更加容易。
3. 提高開發(fā)效率:
- MyBatis自動生成大部分數(shù)據(jù)庫操作代碼,減少了手動編寫SQL語句的工作量,提高了開發(fā)效率。
4. 增加靈活性:
- 關聯(lián)關系映射框架允許進行高級查詢和復雜操作,而不需要深入了解SQL的復雜性,從而提供了更大的靈活性。
5. 降低錯誤風險:
- 通過將關系映射到對象,可以減少手動編寫SQL時可能引入的錯誤,如拼寫錯誤或SQL注入,提高了代碼的質量和安全性。
靈活性:
1. 一對一、一對多和多對多關系:
- MyBatis支持各種關系映射,包括一對一、一對多和多對多關系,使得能夠輕松地處理不同類型的關聯(lián)數(shù)據(jù)。
2. 動態(tài)SQL:
- MyBatis允許在SQL中使用動態(tài)條件,根據(jù)不同情況生成不同的SQL語句,提供了更大的靈活性。
3. 自定義查詢:
- 可以使用自定義SQL查詢來滿足特定需求,無需受限于框架生成的SQL語句。
4. 延遲加載:
- MyBatis支持延遲加載,允許在需要時加載關聯(lián)數(shù)據(jù),提高性能并減少不必要的數(shù)據(jù)檢索。
綜上所述,MyBatis的關聯(lián)關系映射在復雜數(shù)據(jù)模型中至關重要,因為它提供了一種更高級、更抽象的方式來處理數(shù)據(jù)庫操作,同時也提供了豐富的配置和擴展選項,使開發(fā)人員能夠以最靈活的方式滿足不同項目的需求。它不僅提高了代碼的可維護性和開發(fā)效率,還降低了錯誤風險,使開發(fā)人員能夠更輕松地應對復雜性,是現(xiàn)代應用程序開發(fā)中不可或缺的工具之一。
到此這篇關于mybatis關聯(lián)關系映射的實現(xiàn)的文章就介紹到這了,更多相關mybatis關聯(lián)關系映射內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot 實戰(zhàn) 之 優(yōu)雅終止服務的方法
本篇文章主要介紹了SpringBoot 實戰(zhàn) 之 優(yōu)雅終止服務的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05try-with-resource優(yōu)雅關閉io流的方法
這篇文章主要給大家介紹了關于try-with-resource優(yōu)雅關閉io流的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-01-01SpringBoot Mybatis動態(tài)數(shù)據(jù)源切換方案實現(xiàn)過程
這篇文章主要介紹了SpringBoot+Mybatis實現(xiàn)動態(tài)數(shù)據(jù)源切換方案過程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-04-04從Mybatis-Plus開始認識SerializedLambda的詳細過程
這篇文章主要介紹了從Mybatis-Plus開始認識SerializedLambda,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2024-07-07