本文主要講了使用Mybatis實現關聯查詢,分為一對一和一對多兩種情況,最後並對ResultMap進行一個簡要說明。
下面是兩表,一個是顧客表,一個是車票表。一個顧客可以對應多張車票,但是一張車票只能對應一個顧客
t_customer:顧客表,一個顧客可以對應多張車票
t_ticket:車票表,一張車票只能對應一個顧客
1、創建數據表及插入初始數據
創建數據表
use test; DROP TABLE IF EXISTS t_customer; CREATE TABLE t_customer( customerId INT PRIMARY KEY AUTO_INCREMENT, customerName VARCHAR(20) NOT NULL, customerTel INT NOT NULL )ENGINE=InnoDB DEFAULT CHARSET=utf8; DROP TABLE IF EXISTS t_ticket; CREATE TABLE t_ticket( ticketId INT PRIMARY KEY AUTO_INCREMENT, ticketAddress VARCHAR(50) NOT NULL, ticketPrice INT NOT NULL, ticketCId INT NOT NULL )ENGINE=InnoDB DEFAULT CHARSET=utf8;
use test; insert into t_customer values(1,'小王',1888327654); insert into t_customer values(2,'天天',3456546354); insert into t_customer values(3,'阿大',123345566); insert into t_ticket values(1,'武漢到重慶',100,1); insert into t_ticket values(2,'北京到上海',200,1); insert into t_ticket values(3,'深圳到廣州',50,1);
select c.*,t.* from t_customer c JOIN t_ticket t ON (c.customerId=t.ticketCId) where c.customerName ='小王';
結果如下:
1、新建java工程,導入需要的包,最後整個工程目錄 如下:
2、創建表對應的類:
Customer.java:
package com.mucfc.model; import java.util.List; /** *顧客信息類 *@author linbingwen *@2015年5月13日8:30:12 */ public class Customer { private Integer customerId; private String customerName; private Integer customerTel; private Listtickets;//使用一個List來表示車票 public List getTickets() { return tickets; } public void setTickets(List tickets) { this.tickets = tickets; } public Integer getCustomerId() { return customerId; } public void setCustomerId(Integer customerId) { this.customerId = customerId; } public String getCustomerName() { return customerName; } public void setCustomerName(String customerName) { this.customerName = customerName; } public Integer getCustomerTel() { return customerTel; } public void setCustomerTel(Integer customerTel) { this.customerTel = customerTel; } @Override public String toString() { return "Customer [customerId=" + customerId + ", customerName=" + customerName + ", customerTel=" + customerTel+"]"; } }
Ticket.java:
package com.mucfc.model; /** *車票信息類 *@author linbingwen *@2015年5月13日8:30:12 */ public class Ticket { private Integer ticketId; private String ticketAddress; private Integer ticketPrice; private Integer ticketCId; private Customer customer;//使用一個customer來表示顧客 public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } public Integer getTicketId() { return ticketId; } public void setTicketId(Integer ticketId) { this.ticketId = ticketId; } public String getTicketAddress() { return ticketAddress; } public void setTicketAddress(String ticketAddress) { this.ticketAddress = ticketAddress; } public Integer getTicketPrice() { return ticketPrice; } public void setTicketPrice(Integer ticketPrice) { this.ticketPrice = ticketPrice; } public Integer getTicketCId() { return ticketCId; } public void setTicketCId(Integer ticketCId) { this.ticketCId = ticketCId; } @Override public String toString() { return "Ticket [ticketId=" + ticketId + ", ticketAddress=" + ticketAddress + ", ticketPrice=" + ticketPrice + ", ticketCId=" + ticketCId + "]"; } }注意Customer.java:中有個list,list來存放車票,Ticket.java中有一個 customer。
3、定義sql映射文件
(1)首先是一對多關聯:
MyBatis中使用collection標簽來解決一對一的關聯查詢,collection標簽可用的屬性如下:property:指的是集合屬性的值ofType:指的是集合中元素的類型column:所對應的外鍵字段名稱select:使用另一個查詢封裝的結果
<?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.mucfc.model.CustomerMapper"> <!-- 定義數據庫字段與實體對象的映射關系 --> <resultMap type="Customer" id="customerBean"> <id column="customerId" property="customerId"/> <result column="customerName" property="customerName"/> <result column="customerTel" property="customerTel"/> <!-- 一對多的關系 --> <!-- property: 指的是集合屬性的值, ofType:指的是集合中元素的類型 --> <collection property="tickets" ofType="Ticket"> <id column="ticketId" property="ticketId"/> <result column="ticketAddress" property="ticketAddress"/> <result column="ticketPrice" property="ticketPrice"/> <result column="ticketCId" property="ticketCId"/> </collection> </resultMap> <!-- 根據id查詢Person, 關聯將Orders查詢出來 --> <select id="selectCustomerByName" parameterType="string" resultMap="customerBean"> select c.*,t.* from t_customer c,t_ticket t where c.customerId=t.ticketCId and c.customerName =#{customerName}; </select> </mapper>
MyBatis中使用association標簽來解決一對一的關聯查詢,association標簽可用的屬性如下:property:對象屬性的名稱javaType:對象屬性的類型column:所對應的外鍵字段名稱select:使用另一個查詢封裝的結果
<?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.mucfc.model.TicketMapper"> <!-- 定義數據庫字段與實體對象的映射關系 --> <resultMap type="Ticket" id="ticketBean"> <id column="ticketId" property="ticketId" /> <result column="ticketAddress" property="ticketAddress" /> <result column="ticketPrice" property="ticketPrice" /> <result column="ticketCId" property="ticketCId" /> <!-- 一對一的關系 --> <!-- property: 指的是屬性的值, javaType:指的是元素的類型 --> <association property="customer" javaType="Customer"> <id column="customerId" property="customerId" /> <result column="customerName" property="customerName" /> <result column="customerTel" property="customerTel" /> </association> </resultMap> <!-- 根據id查詢ticket, 關聯將Customer查詢出來 --> <select id="selectTicketById" parameterType="int" resultMap="ticketBean"> select c.*,t.* from t_customer c,t_ticket t where c.customerId=t.ticketCId and t.ticketId =#{ticketId} </select> </mapper>
<?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> <!-- 設置別名 --> <typeAliases> <typeAlias alias="Customer" type="com.mucfc.model.Customer"/> <typeAlias alias="Ticket" type="com.mucfc.model.Ticket" /> </typeAliases> <!-- 配置數據源相關的信息 --> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="christmas258@"/> </dataSource> </environment> </environments> <!-- 列出映射文件 --> <mappers> <mapper resource="com/mucfc/model/CustomerMapper.xml" /> <mapper resource="com/mucfc/model/TicketMapper.xml" /> </mappers> </configuration>
package com.mucfc.test; import java.io.Reader; import java.util.List; 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 com.mucfc.model.Customer; import com.mucfc.model.Ticket; public class Test { private static SqlSessionFactory sqlSessionFactory; private static Reader reader; static { try { reader = Resources.getResourceAsReader("mybatis-config.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); } catch (Exception e) { e.printStackTrace(); } } /* * 一對一關聯查詢 */ public static void selectTicketById(int id) { SqlSession session = null; try { session = sqlSessionFactory.openSession(); Ticket ticket = (Ticket) session.selectOne( "com.mucfc.model.TicketMapper.selectTicketById", id); if (ticket == null) System.out.println("null"); else { System.out.println(ticket); System.out.println(ticket.getCustomer()); } } finally { session.close(); } } /* * 一對多關聯查詢 */ public static void selectCustomerByName(String string) { SqlSession session = null; try { session = sqlSessionFactory.openSession(); Customer customer = (Customer) session .selectOne( "com.mucfc.model.CustomerMapper.selectCustomerByName", string); if (customer == null) System.out.println("null"); else { System.out.println(customer); Listtickets = customer.getTickets(); for (Ticket ticket : tickets) { System.out.println(ticket); } } } finally { session.close(); } } public static void main(String[] args) { System.out.println("==============一對一查詢,根據車票來查顧客==============="); selectTicketById(1); System.out.println("==============多對一查詢,根據顧客來查車票==============="); selectCustomerByName("小王"); } }
結果顯示,查詢正確。
MyBatis中在查詢進行select映射的時候,返回類型可以用resultType,也可以用resultMap,resultType是直接表示返回類型的,而resultMap則是對外部ResultMap的引用,但是resultType跟resultMap不能同時存在。在MyBatis進行查詢映射的時候,其實查詢出來的每一個屬性都是放在一個對應的Map裡面的,其中鍵是屬性名,值則是其對應的值。當提供的返回類型屬性是resultType的時候,MyBatis會將Map裡面的鍵值對取出賦給resultType所指定的對象對應的屬性。所以其實MyBatis的每一個查詢映射的返回類型都是ResultMap,只是當我們提供的返回類型屬性是resultType的時候,MyBatis對自動的給我們把對應的值賦給resultType所指定對象的屬性,而當我們提供的返回類型是resultMap的時候,因為Map不能很好表示領域模型,我們就需要自己再進一步的把它轉化為對應的對象,這常常在復雜查詢中很有作用。
當Java接口與XML文件在一個相對路徑下時,可以不在myBatis配置文件的mappers中聲明:
<!-- 列出映射文件 --> <mappers> <mapper resource="com/mucfc/model/CustomerMapper.xml" /> <mapper resource="com/mucfc/model/TicketMapper.xml" /> </mappers>
1. cache – 配置給定模式的緩存 2. cache-ref – 從別的模式中引用一個緩存 3. resultMap – 這是最復雜而卻強大的一個元素了,它描述如何從結果集中加載對象 4. sql – 一個可以被其他語句復用的SQL 塊 5. insert – 映射INSERT 語句 6. update – 映射UPDATE 語句 7. delete – 映射DELEETE 語句 8. select - 映射SELECT語句
resultMap 是MyBatis 中最重要最強大的元素了。你可以讓你比使用JDBC 調用結果集省掉90%的代碼,也可以讓你做許多JDBC 不支持的事。現實上,要寫一個等同類似於交互的映射這樣的復雜語句,可能要上千行的代碼。ResultMaps 的目的,就是這樣簡單的語句而不需要多余的結果映射,更多復雜的語句,除了只要一些絕對必須的語句描述關系以外,再也不需要其它的。
resultMap屬性:type為java實體類;id為此resultMap的標識。
resultMap可以設置的映射:
1. constructor – 用來將結果反射給一個實例化好的類的構造器 a) idArg – ID 參數;將結果集標記為ID,以方便全局調用 b) arg –反射到構造器的通常結果 2. id – ID 結果,將結果集標記為ID,以方便全局調用 3. result – 反射到JavaBean 屬性的普通結果 4. association – 復雜類型的結合;多個結果合成的類型 a) nested result mappings – 幾resultMap 自身嵌套關聯,也可以引用到一個其它上 5. collection –復雜類型集合a collection of complex types 6. nested result mappings – resultMap 的集合,也可以引用到一個其它上 7. discriminator – 使用一個結果值以決定使用哪個resultMap a) case – 基本一些值的結果映射的case 情形 i. nested result mappings –一個case 情形本身就是一個結果映射,因此也可以包括一些相同的元素,也可以引用一個外部resultMap。