iBatis开发详解(10)---操作DDL和映射继承
DDL作为SQL的一个子集,是专门用于数据定义的语言,也就是我们所说的对数据库表/模式的操作。最为常见的就是修改表的结构,比如添加字段,修改字段类型,为字段改名等。那么我们来看看如何使用iBatis来进行DDL操作。
前面介绍的iBatis操作数据库都属于DML范畴,比如select,update,delete等。那么操作DDL我们使用的是statement标签,我们来看看对我们之前示例的订单项表来进行修改:
<statement id="addColumn">
alter table orderitem add column type VARCHAR(50);
</statement>
下面编写程序来调用这个语句: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方法来调用statement语句,那么执行完后,我们可以看到数据表被修改了。可能不同的数据库并不支持这种方式的修改,但用MySQL 5.5来测试是成功的,我们得到了如下的数据库表结构: 现在,我们为为type设置值,个人订单为indi,团体订单为group,然后我们来介绍iBatis的映射继承特性。
继承是面向对象的编程中的最基本的概念,我们这里不对继承的概念做过多的介绍,只是来看看在iBatis中对映射继承的做法。
iBatis的resultMap可以使用<discriminator>标签来支持继承体系。使用鉴别器标签可以根据数据库中某字段的值来确定要实例化类的类型。那么我们来看一下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的订单的公司名称,就很好理解了。 来看一下这里我们定义的两个类Individual和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()方法,便于我们后续测试来打印其内容。同理,我们可以得到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);
}
}
在主函数内,我们通过sqlMapClient获取到这条查询语句,不需要任何参数,它的返回值我们先定义成Object类型,方便后续操作,之后我们打印出该Object类的名称,看看到底是哪种类型,最后打印出这个对象所包含的内容,执行语句,我们得到如下结果: ibatis.model.Individual
OrderItem [itemName=Moto MB525, orderId=1, orderItemId=1, price=1000.0, quantity=1, type=individual]Individual [username=Sarin]
可以看到orderitemId为1时,这是一个个人订单,最终的Object为Individual类型,我们可以打印出OrderItem和子类Individual的信息,那么下单人也会打印出来。同理,我们查询一个团体订单,可以得到如下结果:
ibatis.model.Group
OrderItem [itemName=Lenovo X201, orderId=2, orderItemId=3, price=5000.0, quantity=1, type=group]Group [company=soft]
这也是我们期望的结果。请记住iBatis仅仅是一个SQL Mapping框架,而不是ORM框架,iBatis本身不知道也不关心我们类的关系和数据表之间的映射关系。那么你可以随意使用鉴别器,只要合适业务,即可使用。
更多建议: