在Configuration類中,我們通過add方法添加一個映射,而add方法又把這個任務交給了Binder類的bindrooR方法。
protected void add(org.dom4j.Document doc) throws Exception {
try {
Binder.bindRoot( doc, createMappings() );
}
catch (MappingException me) {
log.error("Could not compile the mapping document", me);
throw me;
}
}
首先,我們來看一段映射配置:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="net.sf.hibernate.examples.quickstart.Cat" table="CAT">
<!-- A 32 hex character is our surrogate key. It's automatically
generated by Hibernate with the UUID pattern. -->
<id name="id" type="string" unsaved-value="null" >
<column name="CAT_ID" sql-type="char(32)" not-null="true"/>
<generator class="uuid.hex"/>
</id>
<!-- A cat has to have a name, but it shouldn' be too long. -->
<property name="name">
<column name="NAME" sql-type="varchar(16)" not-null="true"/>
</property>
<property name="sex"/>
<property name="weight"/>
</class>
</hibernate-mapping>
我們結合這個映射設定檔來看看bindRoot方法(由於方法過長,這裡只截取其中處理class的一部分):
/**//**
* 傳入一個描述映射關係的Document用以填充Mapping
*/
public static void bindRoot(Document doc, Mappings model) throws MappingException {
// 取得根結點,即 hibernate-mapping 結點
Element hmNode = doc.getRootElement();
// 取結點的屬性值
Attribute schemaNode = hmNode.attribute("schema");
model.setSchemaName( (schemaNode==null) ? null : schemaNode.getValue() );
//
// 取得所有的class子結點。
// 由此可以看出,一個設定檔可以配置多個class的映射。
Iterator nodes = hmNode.elementIterator("class");
while ( nodes.hasNext() ) {
Element n = (Element) nodes.next();
// 至此為止,又將權利下放到了bindRootClass方法。
// 這是重構長方法的一種辦法。
RootClass rootclass = new RootClass();
Binder.bindRootClass(n, rootclass, model);
model.addClass(rootclass);
}
//
}
所有讀取配置資訊的工作都是使用上面這種模式:一步一步地把責任往下放,這種做法好處就在於使程式結構清晰,可惜在Binder類中做的還是不夠——方法還是太長。
因為後面的代碼牽涉到的內容還太多,所以暫時跟蹤到此,待mapping包分析完成再來看它。