Hibernate source code-configuration file Loading Process Analysis
Hibernate suggests that Configuration and SessionFactory are Singleton in an application system, and Session is multiple.
When we execute the following code, hibernate starts to load the default configuration file.
new Configuration().configure()
Hibernate searches for the configuration file "hibernate. cfg. xml" in the root path of classath and parses it, as shown in process 1.
Figure 1: sequence of configuration file loading
Next we will analyze the configuration file loading process.
Step 1. Configuration. configure ()
This method is defined in the org/hibernate/cfg/Configuration. java file.
public Configuration configure() throws HibernateException {configure( "/hibernate.cfg.xml" );return this;}
Call the overload method configure ("/hibernate. cfg. xml") and pass in the default configuration file name as the real parameter.
Step 2. Configuration. doConfigure
This method is defined in the org/hibernate/cfg/Configuration. java file.
protected Configuration doConfigure(Document doc) throws HibernateException {Element sfNode = doc.getRootElement().element( "session-factory" );String name = sfNode.attributeValue( "name" );if ( name != null ) {properties.setProperty( Environment.SESSION_FACTORY_NAME, name );}addProperties( sfNode );parseSessionFactory( sfNode, name );Element secNode = doc.getRootElement().element( "security" );if ( secNode != null ) {parseSecurity( secNode );}log.info( "Configured SessionFactory: " + name );log.debug( "properties: " + properties );return this;}
This method transfers the configuration loading process to two indirect layer methods for processing. addProperties () and parseSessionFactory
Step 3. Configuration. addProperties
This method is defined in the org/hibernate/cfg/Configuration. java file.
private void addProperties(Element parent) {Iterator itr = parent.elementIterator( "property" );while ( itr.hasNext() ) {Element node = (Element) itr.next();String name = node.attributeValue( "name" );String value = node.getText().trim();log.debug( name + "=" + value );properties.setProperty( name, value );if ( !name.startsWith( "hibernate" ) ) {properties.setProperty( "hibernate." + name, value );}}Environment.verifyProperties( properties );}
This method parses the content of the property element in the configuration file and stores it in the properties member variable. properties is a Properties instance,
In the if condition, it is found that if the value of name does not start with "hibernate", it is automatically completed.
True
Oracle. jdbc. driver. OracleDriver
Jdbc: oracle: thin: @ 127.0.0.1: 1521: orcl
Diankun
Diankun
Org. hibernate. dialect. Oracle10gDialect
Update
Step 4. Configuration. parseSessionFactory
This method is defined in the org/hibernate/cfg/Configuration. java file.
private void parseSessionFactory(Element sfNode, String name) {Iterator elements = sfNode.elementIterator();while ( elements.hasNext() ) {Element subelement = (Element) elements.next();String subelementName = subelement.getName();if ( "mapping".equals( subelementName ) ) {parseMappingElement( subelement, name );}else if ( "class-cache".equals( subelementName ) ) {......}else if ( "collection-cache".equals( subelementName ) ) {......}else if ( "listener".equals( subelementName ) ) {parseListener( subelement );}else if ( "event".equals( subelementName ) ) {parseEvent( subelement );}}}
The sfNode parameter points to the session-factory element node.
The parameter name is the name attribute value of session-factory, which is equal to null.
The following configuration is added to the configuration file:
The branch that meets the condition "" mapping ". equals (subelementName )"
Step 5. Configuration. parseMappingElement
This method is defined in the org/hibernate/cfg/Configuration. java file.
private void parseMappingElement(Element mappingElement, String name) {final Attribute resourceAttribute = mappingElement.attribute( "resource" );......if ( resourceAttribute != null ) {final String resourceName = resourceAttribute.getValue();log.debug( "session-factory config [{}] named resource [{}] for mapping", name, resourceName );addResource( resourceName );}else if ( fileAttribute != null ) {......}else if ( jarAttribute != null ) {......}else if ( packageAttribute != null ) {......}else if ( classAttribute != null ) {......}else {throw new MappingException( "
element in configuration specifies no known attributes" );}}
We configure in hibernate. cfg. xml ,
Qualified resourceAttribute! = Null, call the addResource (resourceName) Method
Step 6. Configuration. addResource
This method is defined in the org/hibernate/cfg/Configuration. java file.
public Configuration addResource(String resourceName) throws MappingException {log.info( "Reading mappings from resource : " + resourceName );ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();InputStream resourceInputStream = null;if ( contextClassLoader != null ) {resourceInputStream = contextClassLoader.getResourceAsStream( resourceName );}if ( resourceInputStream == null ) {resourceInputStream = Environment.class.getClassLoader().getResourceAsStream( resourceName );}if ( resourceInputStream == null ) {throw new MappingNotFoundException( "resource", resourceName );}add( resourceInputStream, "resource", resourceName );return this;}
This method is simple. You can use the class loader to enable the input stream,
And forward the input stream to add (resourceInputStream, "resource", resourceName) for processing.
Step 7. Configuration. add
This method is defined in the org/hibernate/cfg/Configuration. java file.
public void add(XmlDocument metadataXml) {if ( inSecondPass || !isOrmXml( metadataXml ) ) {metadataSourceQueue.add( metadataXml );}else {final MetadataProvider metadataProvider = ( (MetadataProviderInjector) reflectionManager ).getMetadataProvider();JPAMetadataProvider jpaMetadataProvider = ( JPAMetadataProvider ) metadataProvider;List
classNames = jpaMetadataProvider.getXMLContext().addDocument( metadataXml.getDocumentTree() );for ( String className : classNames ) {try {metadataSourceQueue.add( reflectionManager.classForName( className, this.getClass() ) );}catch ( ClassNotFoundException e ) {throw new AnnotationException( "Unable to load class defined in XML: " + className, e );}}}}
Add (InputSource inputSource, String originType, String originName)
Add (InputSource inputSource, Origin origin)
The add () method is reloaded on the above two, and the call process is skipped.
In the add (XmlDocument metadataXml) method, we can see that it is used as a delegate,
It is handed over to the member variable metaperformancequeue for processing. metaperformancequeue is a metaperformancequeue instance and is the internal class of Configuration.
Step 8. metaperformancequeue. add
This method is defined in the org/hibernate/cfg/Configuration. java file.
public void add(XmlDocument metadataXml) {final Document document = metadataXml.getDocumentTree();final Element hmNode = document.getRootElement();Attribute packNode = hmNode.attribute( "package" );String defaultPackage = packNode != null ? packNode.getValue() : "";Set
entityNames = new HashSet
();findClassNames( defaultPackage, hmNode, entityNames );for ( String entity : entityNames ) {hbmMetadataByEntityNameXRef.put( entity, metadataXml );}this.hbmMetadataToEntityNamesMap.put( metadataXml, entityNames );}
MetadataXml points to a document root node
Function of the findClassNames (defaultPackage, hmNode, entityNames) method:
Stores the name attribute of the class Element in the object ing file in the entityNames local variable.
The value of the element in the entityNames set is used as the key, and the document root node is used as the value, which is stored in the member variable hb1_adatabyentitynamexref,
Hb1_adatabyentitynamexref is Map Instance
Use the document root node as the key, and set entityNames as the value, which is stored in the member variable hb1_adatatoentitynamesmap,
HbmMetadataToEntityNamesMap is LinkedHashMap > Instance,
protected class MetadataSourceQueue implements Serializable {private LinkedHashMap
> hbmMetadataToEntityNamesMap= new LinkedHashMap
>();private Map
hbmMetadataByEntityNameXRef = new HashMap
();//XClass are not serializable by defaultprivate transient List
annotatedClasses = new ArrayList
();//only used during the secondPhaseCompile pass, hence does not need to be serializedprivate transient Map
annotatedClassesByEntityNameMap = new HashMap
();private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {......}private void writeObject(java.io.ObjectOutputStream out) throws IOException {......}public void add(XmlDocument metadataXml) {final Document document = metadataXml.getDocumentTree();final Element hmNode = document.getRootElement();Attribute packNode = hmNode.attribute( "package" );String defaultPackage = packNode != null ? packNode.getValue() : "";Set
entityNames = new HashSet
();findClassNames( defaultPackage, hmNode, entityNames );for ( String entity : entityNames ) {hbmMetadataByEntityNameXRef.put( entity, metadataXml );}this.hbmMetadataToEntityNamesMap.put( metadataXml, entityNames );}}
The storage structure of hb1_adatabyentitynamexref and hb1_adatatoentitynamesmap, as shown in Figure 2:
Figure 2: storage structure of two maps