Spring Hibernate Fundamental Review (1)

Spring Hibernate Fundamental Review

Having been working with spring hibernate for a quite a while.
After few projects in practise, it looks quite different from what it was first
met.

 

Data source

 

<bean id=" dataSource "
class="org.springframework.jdbc.datasource.DriverManagerDataSource">

   <property
name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>

   <property
name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:xe</property>

   <property name="connection.username">admin</property>

   <property
name="connection.password"> admin</property>

</bean>

 

The preceding is an Oracle connection. For MySql

 

<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">

    <property
name="driverClassName" value="com.mysql.jdbc.Driver"/>

    <property
name="url" value="jdbc:mysql://mysql.hongliang.com:3306/myschema?useUnicode=true&amp;characterEncoding=UTF-8&amp;zeroDateTimeBehavior=convertToNull"/>

    <property
name="username" value="admin"/>

    <property
name="password" value="admin"/>

</bean>

 

For a JNDI

 

<bean id=" dataSource "
class="org.springframework.jndi.JndiObjectFactoryBean">

    <property
name="jndiName" value="java:comp/env/jdbc/myds"/>

</bean>

 

Hibernate SessionFactory

Application objects that need to access
resources just receive references to such pre-defined instances via bean
references. This could be configured in your hibernate.cfg.xml file or your
spring configuration file.

 

<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

    <property
name="dataSource " ref=" dataSource "/>

    <property
name="configLocation"
value="classpath:hibernate.cfg.xml"/>

    <property
name="mappingResources">

       
<list>

           
<value>/sql/NewsDaoSql.hbm.xml</value>

       
</list>

   
</property>

    <property
name="eventListeners">

       
<map>

           
<entry key="merge">

               
<bean
class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/>

            </entry>

       
</map>

</property>

    <property
name="hibernateProperties">

        <props>

               
<prop
key="dialect">org.hibernate.dialect.Oracle9Dialect</prop>

               
<prop key="show_sql">true</prop>

               
<prop key="format_sql">true</prop>

               
<prop key="use_sql_comments">true</prop>

               
<prop key="generate_statistics">true</prop>

        </props>

</property>

    <property
name="entityInterceptor">       

        <bean
class="com.hongliang.AuditInterceptor"/>

   
</property>

</bean>

 

This is quite straightforward
configuration.

  • configLocation tells
    where hibernate configuration file (hibernate.cfg.xml) located;
  • mappingResources indicate
    where  the additional resource that
    not specified in the file located in the
      configLocation.
    (This is very helpful especially when the configuration file is
    read only, such like from a library file)
  • eventListeners which
    ensure that when merge happens the persistent object always keep its id.
  • entityInterceptor  enables you to audit the operations on
    the database access (especially on failure), such as save and delete. Your
    AuditInterceptor
    class should extends org.hibernate.EmptyInterceptor.

 

Using Named Query

In the previous note “Call
SQL procedure and function with JDBC and Hibernate

demonstrated how to run the native procedure. To run the native Sql, it is a
lot easier by replacing the procedure call to SQL query

 

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

       
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

       
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"&gt;

<hibernate-mapping>

<sql-query
name="get_document" read-only="true">

                <return alias="document"
class="com.hongliang.Document"/>

                                SELECT
d.* from document d

                                WHERE d.id=:documentID

</sql-query>

</sql-query>

</hibernate-mapping>

 

Document document = (Document)
getSession().getNamedQuery(“get_document”).

setParameter(“documentID”,
documentID).uniqueResult();

 

The preceding code is used when DAO extends HibernateDaoSupport.
If you’d like to find out how to use name query with extending your DAO from
JdbcDaoSupport, check the article
Consistent abstract classes for DAO support”. You will find
out how to do that with JdbcTemplate and return the records as objects by
applying RowMapper. Please also be aware that the xml file stores the query has
different extension. The Hibernate one ends with .hbm.xml and the JDBC one end
just with .xml.  The following is an example how the JDBC named query
structured

<?xml version="1.0"
encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM
"http://java.sun.com/dtd/properties.dtd"&gt;
<properties>
    <comment>SQL’s for Apex DAO</comment>

    <entry key="getOpecVsNonOpecReport">

       
<![CDATA[

Select …

       
]]>
    </entry>

</properties>

 

Using Criteria

This is a simplified API for retrieving entities by composing
Criterion objects. This is a very convenient approach for functionality like
"search" screens where there is a variable number of conditions to be
placed upon the result set.

 

public List<Document> getLastMonthDocuments(String
metadataType){

     Criteria documentCriteria =
this.getSession().createCriteria(Document.class);

     documentCriteria.add(Expression.eq("recordStatus",
RecordStatus.ACTIVE));

     documentCriteria.add(Expression.sql("{alias}.publish
_date >=  DATE_ADD(now(), INTERVAL -30
DAY)"));

 

     Criteria
docMetadataCriteria = documentCriteria.createCriteria("documentMetadata");

     Criteria metadataCriteria =
docMetadataCriteria.createCriteria("metadata");

     metadataCriteria.add(Restrictions.eq("metadataType",
metadataType));

 

     documentCriteria.addOrder(Order.desc("createdAt")).addOrder(Order.desc("updatedAt"));

     return
documentCriteria.list();

}

 

This DAO method trying to fetch the list of document published in
the last 30 days. Since the return type is Document, the criteria will be built
based on Document
this.getSession().createCriteria(Document.class),
and then we can add the criteria on top of it.

 

Class Expression is extended form Restriction, which has its own
method sql(). In the preceding example, the criteria applied a constraint
expressed in SQL. Any occurrences of {alias} will be replaced by the table
alias (‘Document’ table in this case).

 

We can also build the sub criteria base on the properties of
return type. In the preceding example, Document has a
documentMetadata property, which
is a class that has a
metadata
property. We can built the sub criteria on the metadata’s property
metadataType by metadataCriteria.add(Restrictions.eq("metadataType",
metadataType))

When you try to add the sort order, you have to be aware which
criteria you want to apply (root or sub criteria). Once the criteria is set,
you can use it to your result (unique or list).

 

When the Hibernate Criteria API is not
appropriate

  • Externalised
    queries can be audited and optimised if necessary by the DBA
  • Named
    queries stored in the Hibernate mapping files are easier to maintain than
    queries scattered through the Java code
  • Hibernate
    Named Queries are easy to cache if necessary

 

Advertisements
This entry was posted in Hibernate. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s