org.hibernate.cfg.Configurations根据xml文件配置整个工作过程中所需要的参数。一般
我们会用Configuration cfg = new Configuration().configure();创建一个配置类。那么,这句话到底做了什么呢?
首先,new Configuration()会做些什么呢?我们来看他的源码:
protected Configuration(SettingsFactory settingsFactory) {
System.out.println("Configuration(SettingsFactory settingsFactory)");
this.settingsFactory = settingsFactory;
reset();
}
//默认构造函数,先new SettingsFactory(),然后调用
//protected Configuration(SettingsFactory settingsFactory)
public Configuration() {
this(new SettingsFactory());
}
reset()初始化了很多变量,感兴趣的可以去看源代码,没有什么特别的地方。
接着,调用configure()方法!
public Configuration configure() throws HibernateException {
configure("/hibernate.cfg.xml");
return this;
}
可以看出,默认使用hibernate.cfg.xml文件,如果想用自定义的文件,可以调用
configure(“….xml”)方法。
public Configuration configure(String resource) throws HibernateException {
log.debug("configuring from resource: " + resource);
InputStream stream = getConfigurationInputStream(resource);
return doConfigure(stream, resource);
}
根据getConfigurationInputStream(resource)得到文件流,getConfigurationInputStream(resource)调用ConfigHelper.getResourceAsStream(resource)。
public static InputStream getResourceAsStream(String resource) {
String stripped = resource.startsWith("/") ?
resource.substring(1) : resource;
InputStream stream = null;
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader!=null) {
stream = classLoader.getResourceAsStream( stripped );
}
//这里的代码可能应该是stream = Environment.class.getResourceAsStream( resource );
if ( stream == null ) {
Environment.class.getResourceAsStream( resource );
}
if ( stream == null ) {
stream = Environment.class.getClassLoader().getResourceAsStream( stripped );
}
if ( stream == null ) {
throw new HibernateException( resource + " not found" );
}
return stream;
}
然后doConfigure(stream, resource)。
protected Configuration doConfigure(InputStream stream, String resourceName) throws HibernateException {
org.dom4j.Document doc;
try {
List errors = new ArrayList();
SAXReader saxReader = xmlHelper.createSAXReader(resourceName, errors, entityResolver);
doc = saxReader.read(new InputSource(stream));
if (errors.size() != 0) {
throw new MappingException(
"invalid configuration",
(Throwable) errors.get(0)
);
}
}
entityResolver在初始值为entityResolver = XMLHelper.DEFAULT_DTD_RESOLVER;在reset()的时候设置的。XMLHelper.DEFAULT_DTD_RESOLVE在XMLHelper默认是XMLHelper.DEFAULT_DTD_RESOLVER= new DTDEntityResolver();DTDEntityResolver是用来加载dtd文件的。别跟我说你不知道dtd是什么东西?它有3种加载方式:
1. 文件路径以http://hibernate.sourceforge.net/开头的文件,如
http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd,
它会把http://hibernate.sourceforge.net去掉,加上org/hibernate/,文件路径为
org/hibernate/hibernate-configuration-3.0.dtd,然后加载这个文件。
2. 文件路径以file://开头的文件,如
file://hibernate-configuration-3.0.dtd,
它会把file://去掉,路径为 hibernate-configuration-3.0.dtd,然后加载这个文件。
3.如果没有以上2种情况,则直接加载。就是路径名没有修改过。
整个过程在public InputSource resolveEntity(String publicId, String systemId)中实现。
systemId就是dtd的路径。大家可以去看看SAXReader 类自带的
protected static class SAXEntityResolver,比较比较。
在得到doc的值
doc = saxReader.read(new InputSource(stream));
后,调用protected Configuration doConfigure(org.dom4j.Document doc),这个函数主要是根据doc的到配置参数,然后存到properties中。
先是设置session-factory的名字:
Element sfNode = doc.getRootElement().element("session-factory");
String name = sfNode.attributeValue("name");
if (name != null) {
//保存到properties中!
properties.setProperty(Environment.SESSION_FACTORY_NAME, name);
}
然后是addProperties(sfNode),把 <property name=" "> </property>保存到properties中。
//这句话估计又是多余的
properties.setProperty(name, value);
if (!name.startsWith("hibernate")) {
properties.setProperty("hibernate." + name, value);
}
接着调用了parseSessionFactory(sfNode, name),把mapping,class-cache,collection-cache,listener,event等配置保存。到底它保存到哪,我也不全知道,只看了
protected void parseMappingElement(Element subelement, String name),根据配置加载了mapping的文件,最后使用HbmBinder : public static void bindRoot(Document doc, Mappings mappings, java.util.Map inheritedMetas)保存。bindRoot是对mapping中的xml文件进行解析。
HbmBinder和Configuration都有2000行以上的代码,在Hibernate中有很重要的地位。Configuration使用.cfg.xml,而HbmBinder则使用了.hbm.xml。
extractRootAttributes( hmNode, mappings )根据<hibernate-mapping>的配置,把分析的结果存入mapping。