DDL作為SQL的一個子集,是專門用于數(shù)據(jù)定義的語言,也就是我們所說的對數(shù)據(jù)庫表/模式的操作。最為常見的就是修改表的結(jié)構(gòu),比如添加字段,修改字段類型,為字段改名等。那么我們來看看如何使用iBatis來進行DDL操作。
前面介紹的iBatis操作數(shù)據(jù)庫都屬于DML范疇,比如select,update,delete等。那么操作DDL我們使用的是statement標簽,我們來看看對我們之前示例的訂單項表來進行修改:
<statement id="addColumn">
alter table orderitem add column type VARCHAR(50);
</statement>
下面編寫程序來調(diào)用這個語句: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來測試是成功的,我們得到了如下的數(shù)據(jù)庫表結(jié)構(gòu): 現(xiàn)在,我們?yōu)闉閠ype設置值,個人訂單為indi,團體訂單為group,然后我們來介紹iBatis的映射繼承特性。
繼承是面向?qū)ο蟮木幊讨械淖罨镜母拍?,我們這里不對繼承的概念做過多的介紹,只是來看看在iBatis中對映射繼承的做法。
iBatis的resultMap可以使用<discriminator>標簽來支持繼承體系。使用鑒別器標簽可以根據(jù)數(shù)據(jù)庫中某字段的值來確定要實例化類的類型。那么我們來看一下oderitem關于映射繼承的示例,首先我們修改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的類型,并查找子映射,這里我們在orderitem表中添加兩個字段,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 + "]";
}
}
我們可以這么來理解,個體訂單是訂單的一個子類,其中我們要標識下該訂單的用戶名稱,那么我們就在這個類中定義一個username屬性,給出getter和setter方法,加上toString()方法,便于我們后續(xù)測試來打印其內(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類相同,這里不再解釋了。下面編寫一個查詢語句: <select id="getOrderItemById" resultMap="orderItem">
select * from orderitem where orderitemId=1
</select>
為了測試,我們將SQL直接給定,那么后面就需要編寫測試代碼了,也很簡單,我們來看一下: 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類的名稱,看看到底是哪種類型,最后打印出這個對象所包含的內(nèi)容,執(zhí)行語句,我們得到如下結(jié)果:
可以看到orderitemId為1時,這是一個個人訂單,最終的Object為Individual類型,我們可以打印出OrderItem和子類Individual的信息,那么下單人也會打印出來。同理,我們查詢一個團體訂單,可以得到如下結(jié)果:
ibatis.model.Group
OrderItem [itemName=Lenovo X201, orderId=2, orderItemId=3, price=5000.0, quantity=1, type=group]Group [company=soft]
這也是我們期望的結(jié)果。請記住iBatis僅僅是一個SQL Mapping框架,而不是ORM框架,iBatis本身不知道也不關心我們類的關系和數(shù)據(jù)表之間的映射關系。那么你可以隨意使用鑒別器,只要合適業(yè)務,即可使用。
更多建議: