DDL作為SQL的一個(gè)子集,是專門用于數(shù)據(jù)定義的語言,也就是我們所說的對(duì)數(shù)據(jù)庫表/模式的操作。最為常見的就是修改表的結(jié)構(gòu),比如添加字段,修改字段類型,為字段改名等。那么我們來看看如何使用iBatis來進(jìn)行DDL操作。
前面介紹的iBatis操作數(shù)據(jù)庫都屬于DML范疇,比如select,update,delete等。那么操作DDL我們使用的是statement標(biāo)簽,我們來看看對(duì)我們之前示例的訂單項(xiàng)表來進(jìn)行修改:
<statement id="addColumn">
alter table orderitem add column type VARCHAR(50);
</statement>
下面編寫程序來調(diào)用這個(gè)語句:package ibatis;
import java.io.IOException;
import java.io.Reader;
import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;
public class DDLDemo {
private static String config = "ibatis/SqlMapConfig.xml";
private static Reader reader;
private static SqlMapClient sqlMap;
static {
try {
reader = Resources.getResourceAsReader(config);
} catch (IOException e) {
e.printStackTrace();
}
sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
}
public static void main(String[] args) throws Exception {
sqlMap.update("OrderItem.addColumn", null);
}
}
我們使用SqlMapClient的update方法來調(diào)用statement語句,那么執(zhí)行完后,我們可以看到數(shù)據(jù)表被修改了??赡懿煌臄?shù)據(jù)庫并不支持這種方式的修改,但用MySQL 5.5來測(cè)試是成功的,我們得到了如下的數(shù)據(jù)庫表結(jié)構(gòu): 現(xiàn)在,我們?yōu)闉閠ype設(shè)置值,個(gè)人訂單為indi,團(tuán)體訂單為group,然后我們來介紹iBatis的映射繼承特性。
繼承是面向?qū)ο蟮木幊讨械淖罨镜母拍睿覀冞@里不對(duì)繼承的概念做過多的介紹,只是來看看在iBatis中對(duì)映射繼承的做法。
iBatis的resultMap可以使用<discriminator>標(biāo)簽來支持繼承體系。使用鑒別器標(biāo)簽可以根據(jù)數(shù)據(jù)庫中某字段的值來確定要實(shí)例化類的類型。那么我們來看一下oderitem關(guān)于映射繼承的示例,首先我們修改orderItem模型類,添加type屬性:
package ibatis.model;
public class OrderItem implements java.io.Serializable {
private Integer orderItemId;
private String itemName;
private int quantity;
private float price;
private String type;
private Integer orderId;
public OrderItem() {
}
public OrderItem(Integer orderItemId, String itemName, int quantity,
float price, String type, Integer orderId) {
super();
this.orderItemId = orderItemId;
this.itemName = itemName;
this.quantity = quantity;
this.price = price;
this.orderId = orderId;
}
//getters and setters
public String toString() {
return "OrderItem [itemName=" + itemName + ", orderId=" + orderId
+ ", orderItemId=" + orderItemId + ", price=" + price
+ ", quantity=" + quantity + ", type=" + type + "]";
}
}
那么resultMap的映射文件我們可以寫為: <resultMap class="ibatis.model.OrderItem" id="orderItem">
<result property="orderItemId" column="orderItemId" />
<result property="orderId" column="orderId" />
<result property="itemName" column="itemName" />
<result property="quantity" column="quantity" />
<result property="price" column="price" />
<result property="type" column="type" />
<discriminator column="type" javaType="java.lang.String">
<subMap resultMap="Individual" value="individual" />
<subMap resultMap="Group" value="group" />
</discriminator>
</resultMap>
<resultMap class="ibatis.model.Individual" id="Individual"
extends="orderItem">
<result property="username" column="username" />
</resultMap>
<resultMap class="ibatis.model.Group" id="Group" extends="orderItem">
<result property="company" column="company" />
</resultMap>
很容易理解discriminator為我們選擇type的類型,并查找子映射,這里我們?cè)趏rderitem表中添加兩個(gè)字段,username表示individual的訂單的用戶名,company表示group的訂單的公司名稱,就很好理解了。 package ibatis.model;
public class Individual extends OrderItem {
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return super.toString() + "Individual [username=" + username + "]";
}
}
我們可以這么來理解,個(gè)體訂單是訂單的一個(gè)子類,其中我們要標(biāo)識(shí)下該訂單的用戶名稱,那么我們就在這個(gè)類中定義一個(gè)username屬性,給出getter和setter方法,加上toString()方法,便于我們后續(xù)測(cè)試來打印其內(nèi)容。同理,我們可以得到Group類: package ibatis.model;
public class Group extends OrderItem {
private String company;
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
@Override
public String toString() {
return super.toString() + "Group [company=" + company + "]";
}
}
其道理和Individual類相同,這里不再解釋了。下面編寫一個(gè)查詢語句: <select id="getOrderItemById" resultMap="orderItem">
select * from orderitem where orderitemId=1
</select>
為了測(cè)試,我們將SQL直接給定,那么后面就需要編寫測(cè)試代碼了,也很簡(jiǎn)單,我們來看一下: package ibatis;
import java.io.IOException;
import java.io.Reader;
import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;
public class DiscriminatorDemo {
private static String config = "ibatis/SqlMapConfig.xml";
private static Reader reader;
private static SqlMapClient sqlMap;
static {
try {
reader = Resources.getResourceAsReader(config);
} catch (IOException e) {
e.printStackTrace();
}
sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
}
public static void main(String[] args) throws Exception {
Object obj = sqlMap.queryForObject("OrderItem.getOrderItemById");
System.out.println(obj.getClass().getName());
System.out.println(obj);
}
}
在主函數(shù)內(nèi),我們通過sqlMapClient獲取到這條查詢語句,不需要任何參數(shù),它的返回值我們先定義成Object類型,方便后續(xù)操作,之后我們打印出該Object類的名稱,看看到底是哪種類型,最后打印出這個(gè)對(duì)象所包含的內(nèi)容,執(zhí)行語句,我們得到如下結(jié)果:
可以看到orderitemId為1時(shí),這是一個(gè)個(gè)人訂單,最終的Object為Individual類型,我們可以打印出OrderItem和子類Individual的信息,那么下單人也會(huì)打印出來。同理,我們查詢一個(gè)團(tuán)體訂單,可以得到如下結(jié)果:
ibatis.model.Group
OrderItem [itemName=Lenovo X201, orderId=2, orderItemId=3, price=5000.0, quantity=1, type=group]Group [company=soft]
這也是我們期望的結(jié)果。請(qǐng)記住iBatis僅僅是一個(gè)SQL Mapping框架,而不是ORM框架,iBatis本身不知道也不關(guān)心我們類的關(guān)系和數(shù)據(jù)表之間的映射關(guān)系。那么你可以隨意使用鑒別器,只要合適業(yè)務(wù),即可使用。
更多建議: