Search This Blog

Monday, 5 September 2011

Configuring via properties or XML ??

The way to run Hibernate is to create a SessionFactory object. The SessionFactory Object is responsible for providing us with Hibernate sessions to perform the various db Operations. In minimal words, the Session factory is responsible for internally managing all db related operations for us. Before using a session factory it has to be configured for use.
For this a Configuration object is used. There are two (standard or commonly used )ways of creating the Configuration object -
  • via a properties file 
  • via an XML Configuration.
The code to make an application Hibernate Ready is:
Configuration configuration = new Configuration();     //Line 1
configuration = configuration.configure();    //Line 2 
SessionFactory sessionFactory = configuration.buildSessionFactory(); 
Before running this code, I also added a sample hibernate.properties to the project class path.
hibernate.connection.driver_class = org.postgresql.Driver
hibernate.connection.url = jdbc:mysql://localhost:3306/menagerieDb
hibernate.connection.username = nonExistingUser
hibernate.connection.password = invalidPwd
hibernate.dialect = org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
hibernate.format_sql=true
The username and password seen above are invalid. If Hibernate were to be used with these it would never get a database connection.
Now to create the more common hibernate.cfg.xml file.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
            "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
            "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">root</property>
        <property name="hibernate.connection.url">
                    jdbc:mysql://localhost:3306/menagerieDb</property>
        <property name="hibernate.hbm2ddl.auto">validate</property> 
        <property name="show_sql">true</property> 

        <mapping resource="com/menagerie/domain/entity/Owner.hbm.xml" />
        <mapping resource="com/menagerie/domain/entity/Pet.hbm.xml" />

    </session-factory>
</hibernate-configuration>
The cfg file holds valid credentials. I now executed the code and decided to trace the logs generated.
On Execution of Line 1:
0    [main] INFO  org.hibernate.cfg.Environment  - Hibernate 3.2.5
1    [main] INFO  org.hibernate.cfg.Environment  - loaded properties from 
resource hibernate.properties: {hibernate.connection.username=nonExistingUser, 
hibernate.connection.password=**********, 
hibernate.dialect=org.hibernate.dialect.MySQLDialect, 
hibernate.connection.url=jdbc:mysql://localhost:3306/menagerieDb
hibernate.bytecode.use_reflection_optimizer=false, 
hibernate.connection.driver_class=org.postgresql.Driver}
2    [main] INFO  org.hibernate.cfg.Environment  - Bytecode provider name : cglib
4    [main] INFO  org.hibernate.cfg.Environment  - using JDK 1.4 
java.sql.Timestamp handling
When a Configuration object is created, it searches in the class path for the default configuration file(hibernate.properties). If it finds hibernate.properties, it loads the properties from this file. 
NOTE: No attempt is made to set up any connection with database yet. 
On Execution of Line 2:
51   [main] INFO  org.hibernate.cfg.Configuration  - configuring from resource: / 
hibernate.cfg.xml
51   [main] INFO  org.hibernate.cfg.Configuration - Configuration resource:  
/hibernate.cfg.xml
92   [main] DEBUG org.hibernate.util.DTDEntityResolver  - trying to resolve 
system-id [http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd]
93   [main] DEBUG org.hibernate.util.DTDEntityResolver  - 
recognized hibernate namespace; attempting to resolve on classpath under org
/hibernate/
93   [main] DEBUG org.hibernate.util.DTDEntityResolver  - located [ 
http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd] in classpath
108  [main] DEBUG org.hibernate.cfg.Configuration  - 
connection.driver_class=com.mysql.jdbc.Driver
109  [main] DEBUG org.hibernate.cfg.Configuration  - 
dialect=org.hibernate.dialect.MySQLDialect
109  [main] DEBUG org.hibernate.cfg.Configuration  - 
hibernate.connection.username=root
109  [main] DEBUG org.hibernate.cfg.Configuration  - 
hibernate.connection.password=root
109  [main] DEBUG org.hibernate.cfg.Configuration  - 
hibernate.connection.url=jdbc:mysql://localhost:3306/menagerieDb
109  [main] DEBUG org.hibernate.cfg.Configuration  - 
hibernate.generate_statistics=false
109  [main] DEBUG org.hibernate.cfg.Configuration  - show_sql=true
109  [main] DEBUG org.hibernate.cfg.Configuration  - 
hibernate.cache.use_structured_entries=false
109  [main] DEBUG org.hibernate.cfg.Configuration  - 
hibernate.cache.use_second_level_cache=false
110  [main] DEBUG org.hibernate.cfg.Configuration  -  
null<-org.dom4j.tree.DefaultAttribute@4741d6 [
Attribute: name resource value "com/menagerie/domain/entity/Owner.hbm.xml"]
110  [main] INFO  org.hibernate.cfg.Configuration  - Reading mappings from 
resource : com/menagerie/domain/entity/Owner.hbm.xml
111  [main] DEBUG org.hibernate.util.DTDEntityResolver  - trying to resolve 
system-id [http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd]
111  [main] DEBUG org.hibernate.util.DTDEntityResolver  - recognized hibernate 
namespace; attempting to resolve on classpath under org/hibernate/
111  [main] DEBUG org.hibernate.util.DTDEntityResolver  - located [ 
http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd] in classpath
168  [main] INFO  org.hibernate.cfg.HbmBinder  - 
Mapping class: com.menagerie.domain.entity.Owner -> OWNER
172  [main] DEBUG org.hibernate.cfg.HbmBinder  - Mapped property: id -> ID
.....
181  [main] DEBUG org.hibernate.cfg.Configuration  - null<-org.dom4j.tree. 
DefaultAttribute@922804 [
Attribute: name resource value "com/menagerie/domain/entity/Pet.hbm.xml"]
181  [main] INFO  org.hibernate.cfg.Configuration  - Reading mappings from 
resource : com/menagerie/domain/entity/Pet.hbm.xml
182  [main] DEBUG org.hibernate.util.DTDEntityResolver  - trying to resolve 
system-id [http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd]
182  [main] DEBUG org.hibernate.util.DTDEntityResolver  - recognized hibernate 
namespace; attempting to resolve on classpath under org/hibernate/
182  [main] DEBUG org.hibernate.util.DTDEntityResolver  - located [ 
http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd] in classpath
194  [main] INFO  org.hibernate.cfg.HbmBinder  - Mapping class: 
com.menagerie.domain.entity.Pet -> PET
195  [main] DEBUG org.hibernate.cfg.HbmBinder  - Mapped property: id -> ID
195  [main] DEBUG org.hibernate.cfg.HbmBinder  - Mapped property: name -> NAME
....
233  [main] INFO  org.hibernate.cfg.Configuration  - Configured SessionFactory: 
null

[NOTE: Certain Logs have been removed for readability]
When the call is made to configure the newly created Configuration object, it searched for the configuration file hibernate.cfg.xml on the class-path. 
If the file is found it will load and read it and override any mappings that were read from the properties file.Thus the invalid connection details that we have specified in the properties file will not be used for any db connections. Instead the values specified in the cfg file will be used. Also the mapping documents specified in the cfg file are loaded and read. 
The fields in the Java Objects are mapped to the columns in the table ( all based on details in the mapping files. There is no contact with database yet).
In the last Line the session factory is declared as being configured and ready for use. Thus we can observe that :
  • Hibernate gives precedence to xml configuration over the property files approach.
  • In case the xml file is not present then Hibernate will use the values detected in the hibernate.properties.
  • The xml files also allows you to specify the mapping documents.
  • It is not necessary that the xml file used must have the name "hibernate.cfg.xml". An alternative file can also be provided eg :
  • configuration = configuration.configure("/options/hib.cfg.xml"); 
    
  • There is another ways to provide setting options to the Configuration object - via code.
    public static void main(String[] args) {
        new Configuration().configure().setProperty("show_sql", "false")
            .addResource("com/menagerie/domain/entity/Pet.hbm.xml")
            .addResource("com/menagerie/domain/entity/Owner.hbm.xml")
                 .buildSessionFactory();
    }
    
    Using this it is possible to set all configurations via code (Not a nice way though)

No comments:

Post a Comment