mybatis關(guān)系映射之一對(duì)多和多對(duì)一
本實(shí)例使用用戶和訂單的例子做說(shuō)明: 一個(gè)用戶可以有多個(gè)訂單, 一個(gè)訂單只對(duì)應(yīng)一個(gè)用戶。(其中應(yīng)用到注釋)
1.代碼的結(jié)構(gòu)
2. 建表語(yǔ)句:
CREATE DATABASE test; USE test; CREATE TABLE person( personId VARCHAR(36) PRIMARY KEY, personName VARCHAR(64), personAddress VARCHAR(128), personTel VARCHAR(11) ); CREATE TABLE orders( orderId VARCHAR(36) PRIMARY KEY, orderNumber VARCHAR(20), orderPrice INT, pid VARCHAR(36) ); INSERT INTO person VALUES('1', '木子', '湖北', '110'); INSERT INTO person VALUES('2', '木子大大', '武漢', '120'); INSERT INTO person VALUES('1', '木子苗苗', '天門(mén)', '119'); INSERT INTO orders VALUES('1', '001', 100, '1'); INSERT INTO orders VALUES('2', '002', 200, '1'); INSERT INTO orders VALUES('3', '003', 300, '2'); INSERT INTO orders VALUES('4', '004', 400, '2'); INSERT INTO orders VALUES('5', '005', 500, '3'); SELECT p.*, o.* FROM person p JOIN orders o ON (p.personId=o.pid) WHERE p.personId = '1' ; *指顯示所有字段
3. 用戶實(shí)體:
package com.mybatis.domain; import java.util.List; import lombok.Data; @Data//注釋(Person為單方) public class Person { private String personid; private String personname; private String personaddress; private String persontel; //這個(gè)代表多方里面的內(nèi)容(Orders) private List<Orders> orders; @Override public String toString() { return "Person [personid=" + personid + ", personname=" + personname + ", personaddress=" + personaddress + ", persontel=" + persontel + ", orders=" + orders + "]"; } }
4. 訂單實(shí)體:
package com.mybatis.domain; import lombok.Data; @Data//(Orders為多方) public class Orders { private String orderid; private String ordernumber; private Integer orderprice; //對(duì)象(單方Person)與外鍵進(jìn)行關(guān)聯(lián) private Person person; }
5.寫(xiě)PersonMapper.java的接口
package com.mybatis.dao.mapper; import com.mybatis.domain.Orders; import com.mybatis.domain.Person; import java.util.List; public interface PersonMapper { int deleteByPrimaryKey(String personid); int insert(Person record); Person selectByPrimaryKey(String personid); List<Person> selectAll(); int updateByPrimaryKey(Person record); //一對(duì)多查詢(根據(jù)id查詢) public List<Orders> findPersonAndOrders(String pid); //一對(duì)多查詢返回一個(gè)對(duì)象 public Person selectPersonById(String id); }
6. 一對(duì)多實(shí)體配置: PersonMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.mybatis.dao.mapper.PersonMapper" > <resultMap id="PersonResultMap" type="com.mybatis.domain.Person" > <id column="personId" property="personid" jdbcType="VARCHAR" /> <result column="personName" property="personname" jdbcType="VARCHAR" /> <result column="personAddress" property="personaddress" jdbcType="VARCHAR" /> <result column="personTel" property="persontel" jdbcType="VARCHAR" /> <!-- 一對(duì)多的關(guān)系(這個(gè)是關(guān)聯(lián)集合)這個(gè)是Orders里面的多方 --> <!-- property: 指的是集合屬性的名, ofType:指的是集合中元素的類型的路徑 (實(shí)現(xiàn)類)--> <collection property="orders" ofType="com.mybatis.domain.Orders"> <!-- id有一個(gè)單獨(dú)標(biāo)簽 --> <id column="orderId" property="orderid"/> <!--column指sql中字段的名字 property指java中對(duì)應(yīng)sql中屬性的名 --> <result column="orderNumber" property="ordernumber"/> <result column="orderPrice" property="orderprice"/> </collection> </resultMap> <!-- 根據(jù)id查詢Person, 關(guān)聯(lián)將Orders查詢出來(lái)(注意放置的位置) --> <select id="findPersonAndOrders" parameterType="String" resultMap="PersonResultMap"> SELECT p.*,o.* FROM person o,orders b WHERE o.personid=#{pid}; </select> <select id="selectPersonById" parameterType="string" resultMap="PersonResultMap"> select p.*, o.* from person p, orders o where p.personId = o.pid and p.personId = #{id} </select> </mapper>
7.寫(xiě)OrdersMapper.java的接口
package com.mybatis.dao.mapper; import com.mybatis.domain.Orders; import java.util.List; public interface OrdersMapper { int deleteByPrimaryKey(String orderid); int insert(Orders record); Orders selectByPrimaryKey(String orderid); List<Orders> selectAll(); int updateByPrimaryKey(Orders record); //多查一 根據(jù)id public Orders selectOrderById(String oid); //多查一 根據(jù)orderNumber public Orders selectOrderNumber(String number); }
8.多對(duì)一實(shí)體配置:OrdersMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.mybatis.dao.mapper.OrdersMapper" > <resultMap id="OrdersResultMap" type="com.mybatis.domain.Orders" > <id column="orderId" property="orderid" jdbcType="VARCHAR" /> <result column="orderNumber" property="ordernumber" jdbcType="VARCHAR" /> <result column="orderPrice" property="orderprice" jdbcType="INTEGER" /> <!-- <result column="pid" property="pid" jdbcType="VARCHAR" /> --> <!-- 多對(duì)一的關(guān)系 這個(gè)是Person里面的單方 --> <!-- property: 指的是屬性的值, javaType:指的是屬性的類型的路徑 (實(shí)現(xiàn)類)--> <association property="person" javaType="com.mybatis.domain.Person"> <!--注意:在此column和property的值要一樣都為Person的屬性 --> <id column="personid" property="personid"/> <result column="personname" property="personname"/> <result column="personaddress" property="personaddress"/> <result column="persontel" property="persontel"/> </association> </resultMap> <!-- 根據(jù)id查詢Order, 關(guān)聯(lián)將Person查詢出來(lái) --> <select id="selectOrderById" parameterType="string" resultMap="OrdersResultMap"> select p.*, o.* from person p, orders o where p.personId = o.pid and o.orderId = #{oid} </select> <!-- 根據(jù)orderNumber查詢Order, 關(guān)聯(lián)將Person查詢出來(lái) --> <select id="selectOrderNumber" parameterType="string" resultMap="OrdersResultMap"> select p.*, o.* from person p, orders o where p.personId = o.pid and o.orderId = #{number} </select> </mapper>
9.其他配置
db.properties配置(sql語(yǔ)句的基本鏈接) db.driver=com.mysql.jdbc.Driver db.url=jdbc:mysql://localhost:3306/wang1?useUnicode=true&characterEncoding=utf8 db.username=root db.password=123456 log4j.properties配置(注釋) # Global logging configuration log4j.rootLogger=DEBUG, stdout # Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n mybatis.xml(逆向生成domain、dao層) <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- mybatis核心配置文件 --> <!-- 加載java的配置文件或者聲明屬性信息 --> <properties resource="db.properties"> </properties> <!-- alias別名 --> <typeAliases> <!--這里需要修改 domain層的路徑--> <typeAlias type="com.mybatis.domain.Person" alias="person" /> <typeAlias type="com.mybatis.domain.Orders" alias="orders" /> </typeAliases> <!-- 配置mybatis的環(huán)境信息,與spring整合,該信息由spring來(lái)管理 如果說(shuō)我們需要連接數(shù)據(jù)庫(kù),那么必須在mybatis中配置環(huán)境 運(yùn)行環(huán)境 --> <environments default="development"> <environment id="development"> <!-- 配置JDBC事務(wù)控制,由mybatis進(jìn)行管理 --> <transactionManager type="JDBC"></transactionManager> <!-- 配置數(shù)據(jù)源,采用mybatis連接池 --> <dataSource type="POOLED"> <property name="driver" value="${db.driver}" /> <property name="url" value="${db.url}" /> <property name="username" value="${db.username}" /> <property name="password" value="${db.password}" /> </dataSource> </environment> </environments> <!-- 加載映射文件(注意反\)--> <mappers> <!--這里需要修改 dao層的路徑--> <mapper resource="com\mybatis\dao\mapper\PersonMapper.xml"/> <mapper resource="com\mybatis\dao\mapper\OrdersMapper.xml"/> </mappers> </configuration> generatorConfig.xml配置(對(duì)MySQL進(jìn)行操作)下面標(biāo)紅部分根據(jù)自己建立的進(jìn)行修改 <?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> D盤(pán)中要有此包mysql-connector-java-5.1.7-bin.jar <classPathEntry location="D:\mysql-connector-java-5.1.7-bin.jar" /> <context id="mysql" defaultModelType="hierarchical" targetRuntime="MyBatis3Simple"> <!-- 自動(dòng)識(shí)別數(shù)據(jù)庫(kù)關(guān)鍵字,默認(rèn)false,如果設(shè)置為true,根據(jù)SqlReservedWords中定義的關(guān)鍵字列表; 一般保留默認(rèn)值,遇到數(shù)據(jù)庫(kù)關(guān)鍵字(Java關(guān)鍵字),使用columnOverride覆蓋 --> <property name="autoDelimitKeywords" value="false" /> <!-- 生成的Java文件的編碼 --> <property name="javaFileEncoding" value="UTF-8" /> <!-- beginningDelimiter和endingDelimiter:指明數(shù)據(jù)庫(kù)的用于標(biāo)記數(shù)據(jù)庫(kù)對(duì)象名的符號(hào),比如ORACLE就是雙引號(hào),MYSQL默認(rèn)是`反引號(hào); --> <property name="beginningDelimiter" value="`" /> <property name="endingDelimiter" value="`" /> <!-- 注釋生成器 --> <commentGenerator> <property name="suppressDate" value="true"/> <property name="suppressAllComments" value="true" /> </commentGenerator> <!-- 必須要有的,使用這個(gè)配置鏈接數(shù)據(jù)庫(kù) @TODO:是否可以擴(kuò)展 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/wang1" userId="root" password="123456"> <!-- 這里面可以設(shè)置property屬性,每一個(gè)property屬性都設(shè)置到配置的Driver上 --> </jdbcConnection> <!-- java模型創(chuàng)建器,是必須要的元素 負(fù)責(zé):1,key類(見(jiàn)context的defaultModelType);2,java類;3,查詢類 targetPackage:生成的類要放的包,真實(shí)的包受enableSubPackages屬性控制; targetProject:目標(biāo)項(xiàng)目,指定一個(gè)存在的目錄下,生成的內(nèi)容會(huì)放到指定目錄中,如果目錄不存在,MBG不會(huì)自動(dòng)建目錄 --> <javaModelGenerator targetPackage="com.mybatis.domain" targetProject="mybatis03/src"> <!-- for MyBatis3/MyBatis3Simple 自動(dòng)為每一個(gè)生成的類創(chuàng)建一個(gè)構(gòu)造方法,構(gòu)造方法包含了所有的field;而不是使用setter; --> <property name="constructorBased" value="false" /> <!-- for MyBatis3 / MyBatis3Simple 是否創(chuàng)建一個(gè)不可變的類,如果為true, 那么MBG會(huì)創(chuàng)建一個(gè)沒(méi)有setter方法的類, 取而代之的是類似constructorBased的類 --> <property name="immutable" value="false" /> </javaModelGenerator> <!-- 生成SQL map的XML文件生成器, 注意,在Mybatis3之后,我們可以使用mapper.xml文件+Mapper接口(或者不用mapper接口), 或者只使用Mapper接口+Annotation,所以,如果 javaClientGenerator配置中配置了需要生成XML的話,這個(gè)元素就必須配置 targetPackage/targetProject:同javaModelGenerator --> <sqlMapGenerator targetPackage="com.mybatis.dao.mapper" targetProject="mybatis03/src"> <!-- 在targetPackage的基礎(chǔ)上,根據(jù)數(shù)據(jù)庫(kù)的schema再生成一層package,最終生成的類放在這個(gè)package下,默認(rèn)為false --> <property name="enableSubPackages" value="true" /> </sqlMapGenerator> <!-- 對(duì)于mybatis來(lái)說(shuō),即生成Mapper接口,注意,如果沒(méi)有配置該元素,那么默認(rèn)不會(huì)生成Mapper接口 targetPackage/targetProject:同javaModelGenerator type:選擇怎么生成mapper接口(在MyBatis3/MyBatis3Simple下): 1,ANNOTATEDMAPPER:會(huì)生成使用Mapper接口+Annotation的方式創(chuàng)建(SQL生成在annotation中),不會(huì)生成對(duì)應(yīng)的XML; 2,MIXEDMAPPER:使用混合配置,會(huì)生成Mapper接口,并適當(dāng)添加合適的Annotation,但是XML會(huì)生成在XML中; 3,XMLMAPPER:會(huì)生成Mapper接口,接口完全依賴XML; 注意,如果context是MyBatis3Simple:只支持ANNOTATEDMAPPER和XMLMAPPER --> <javaClientGenerator targetPackage="com.mybatis.dao.mapper" type="XMLMAPPER" targetProject="mybatis03/src"> <!-- 在targetPackage的基礎(chǔ)上,根據(jù)數(shù)據(jù)庫(kù)的schema再生成一層package,最終生成的類放在這個(gè)package下,默認(rèn)為false --> <property name="enableSubPackages" value="true" /> <!-- 可以為所有生成的接口添加一個(gè)父接口,但是MBG只負(fù)責(zé)生成,不負(fù)責(zé)檢查 <property name="rootInterface" value=""/> --> </javaClientGenerator> <!--逆向生成的文件--> <table tableName="person" delimitIdentifiers="true"> <!-- 參考 javaModelGenerator 的 constructorBased屬性 --> <property name="constructorBased" value="false" /> <generatedKey column="id" sqlStatement="JDBC"/> </table> <table tableName="orders" delimitIdentifiers="true"> <!-- 參考 javaModelGenerator 的 constructorBased屬性 --> <property name="constructorBased" value="false" /> <generatedKey column="id" sqlStatement="JDBC"/> </table> </context> </generatorConfiguration>
10.測(cè)試文件
package com.mybatis.test; import java.io.InputStream; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Iterator; import java.util.List; import lombok.Data; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Before; import org.junit.Test; import com.mybatis.dao.mapper.OrdersMapper; import com.mybatis.dao.mapper.PersonMapper; import com.mybatis.domain.Orders; import com.mybatis.domain.Person; public class TestStudentMapper { SqlSessionFactory sessionFactory = null; // 這方法之前 @Before public void setup() throws Exception { String resource = "mybatis.xml"; // 這個(gè)是加載配置文件 InputStream inputStream = Resources.getResourceAsStream(resource); // 得到會(huì)話工廠 sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } //查詢一對(duì)多 根據(jù)這個(gè)person里面的id號(hào)就能查詢出這個(gè)用戶有多少個(gè)訂單記錄 // @Test public void testSelectPersonById(){ SqlSession sq = sessionFactory.openSession(); // 得到dao層的實(shí)現(xiàn)類 PersonMapper u = sq.getMapper(PersonMapper.class); Person person = u.selectPersonById("2"); System.out.println(person); } //多對(duì)一 根據(jù)多對(duì)一id進(jìn)行查詢 // @Test//多對(duì)一關(guān)聯(lián)查詢 public void testSelectOrderById(){ SqlSession sq = sessionFactory.openSession(); // 得到dao層的實(shí)現(xiàn)類 OrdersMapper u = sq.getMapper(OrdersMapper.class); Orders od = u.selectOrderById( "2"); System.out.println(od.getPerson().getPersonname()); System.out.println(od.getPerson().getPersonaddress()); } @Test//多對(duì)一關(guān)聯(lián)查詢 public void testSelectOrderNumber(){ SqlSession sq = sessionFactory.openSession(); // 得到dao層的實(shí)現(xiàn)類 OrdersMapper u = sq.getMapper(OrdersMapper.class); Orders od = u.selectOrderNumber("001"); System.out.println(od.getPerson().getPersonname()); System.out.println(od.getPerson().getPersonaddress()); } }
如有問(wèn)題請(qǐng)多多指教!希望給您帶來(lái)幫助!祝您生活愉快。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
相關(guān)文章
Java 字節(jié)數(shù)組(byte[])和整型(int)的相互轉(zhuǎn)換
在Java編程中,有時(shí)需要將字節(jié)類型(byte)轉(zhuǎn)換為整數(shù)類型(int),或者反過(guò)來(lái)轉(zhuǎn)換,本文主要介紹了Java 字節(jié)數(shù)組(byte[])和整型(int)的相互轉(zhuǎn)換,感興趣的可以了解一下2023-12-12Java增強(qiáng)for循環(huán)的增刪操作代碼
Foreach循環(huán)(Foreach loop)是計(jì)算機(jī)編程語(yǔ)言中的一種控制流程語(yǔ)句,通常用來(lái)循環(huán)遍歷數(shù)組或集合中的元素,本文通過(guò)實(shí)例演示普通for循環(huán)和foreach循環(huán)使用,java增強(qiáng)for循環(huán)的操作代碼感興趣的朋友一起看看吧2024-02-02spring bean.xml文件p標(biāo)簽使用報(bào)錯(cuò)的解決
這篇文章主要介紹了spring bean.xml文件p標(biāo)簽使用報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08SpringBoot中如何進(jìn)行統(tǒng)一異常處理
大家好,本篇文章主要講的是SpringBoot中如何進(jìn)行統(tǒng)一異常處理,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下2022-02-02idea無(wú)法打斷點(diǎn),單擊或雙擊代碼行左側(cè)區(qū)域無(wú)效的解決
這篇文章主要介紹了idea無(wú)法打斷點(diǎn),單擊或雙擊代碼行左側(cè)區(qū)域無(wú)效的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09SpringBoot之解決多個(gè)定時(shí)任務(wù)阻塞的問(wèn)題
這篇文章主要介紹了SpringBoot之解決多個(gè)定時(shí)任務(wù)阻塞的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04Springboot如何優(yōu)雅地進(jìn)行字段校驗(yàn)
這篇文章主要給大家介紹了關(guān)于Springboot如何優(yōu)雅地進(jìn)行字段校驗(yàn)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01Java反射(JDK)與動(dòng)態(tài)代理(CGLIB)詳解
下面小編就為大家?guī)?lái)一篇淺談Java反射與動(dòng)態(tài)代理。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2021-08-08