Announcement Announcement Module
Collapse
No announcement yet.
Combining Hibernate and JDBC DAOs Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Combining Hibernate and JDBC DAOs

    I have read the Spring reference documentation and the J2EE without EJB book, but I am still in search of a good answer to this question:

    Using one of the examples in the book on pg. 286

    I have various Spring web controllers in my application. These controllers use DAO to conduct the persistence operations. 90% of my DB work is accomplished using Hibernate and the HibernateDAOSupport class. The other 10% has complex read-only SQL operations using the JdbcDAOSupport class. Methods from both DAO's apply to orders and should be contained in a single DAO. The same case applies to users, groups, etc. What is the suggested pattern for abstracting together both data access technologies into a single DAO? It makes sense to me that I should be able to use the features of both of these Spring DAO support classes in a single subclass.

    I don't like the idea of putting all the methods of both order DAO's into a facade interface and then auto-wiring both DAO's to the implementation of that facade interface. This means I have to change up to 4 method signatures if one method is changed. I have been toying with the idea of a automatic proxy class for the facade that assimilates the 2 DAO's automatically, but I want to keep the strong typing and program to a well-defined interface.

    Any ideas suggestions?

    Thanks.

  • #2
    Rosco,

    A couple of methods come to mind for this. The first is to simply create a DAO using HibernateDaoSupport and then use an instance of JdbcTemplate for any methods that you want to write using JDBC. The second is to have your Hibernate DAO contain a static inner class that extends JdbcDaoSupport and implement your JDBC logic here. From there you can simply have your main dao maintain an instance of your inner dao and redirect applicable calls to it.

    Rob

    Comment


    • #3
      Rob,

      Thanks for the quick reply. I didn't think of this approach and it makes sense. Thanks for you help.

      -Rosco

      Comment


      • #4
        you can using plain jdbc.

        like this.

        In a HibernateDaoSupport,
        this.getHibernateTemplate().getSession().connectio n().Createstatement().
        exec***

        Comment


        • #5
          ...have your Hibernate DAO contain a static inner class that extends JdbcDaoSupport and implement your JDBC logic here. From there you can simply have your main dao maintain an instance of your inner dao and redirect applicable calls to it.
          Sounds like a great idea. If I use the inner class JdbcDaoSupport strategy, I believe I will need to pass a DataSource to the inner class (i.e. a JdbcDaoSupport), in addition to passing a SessionFactory to the outer class (i.e. a HibernateDaoSupport). Will I need to provide both a DataSource setter AND a SessionFactory setter in the outer class for the container to call? Or, is there an easy way to get a DataSource from a SessionFactory (or a SessionFactory from a DataSource)?

          Cheers,
          Joe

          Comment


          • #6
            Will I need to provide both a DataSource setter AND a SessionFactory setter in the outer class for the container to call? Or, is there an easy way to get a DataSource from a SessionFactory (or a SessionFactory from a DataSource)?
            I think I answered my own question. From studying the API's a little more closely, I discovered org.springframework.orm.hibernate.SessionFactoryUt ils.getDataSource(). This allowed me to derive the DataSource from the SessionFactory so my DAO only needed a setter for SessionFactory. That was too easy...is there any downside to this technique????

            If it's helpful to anyone else who wants to use some JDBC (for example, Spring's JDBC operation objects) inside their Hibernate DAO, here's an excerpt of my code:

            Code:
            package mypackage;
            
            // various imports here...
            
            public class HibernateLocationDao extends HibernateDaoSupport implements LocationDao
            {
              private LocationsQuery locationsQuery;
              
              // overrides base class
              protected void initDao() throws Exception
              {
                super.initDao();
                
                // Here I get the DataSource from the SessionFactory so my DAO does NOT need a 
                // setDataSource() method. Note that setSessionFactory() is inherited from HibernateDaoSupport.
                locationsQuery = new LocationsQuery(SessionFactoryUtils.getDataSource(getSessionFactory()));
              }
              
              public Collection getLocations() throws DataAccessException
              {
                return locationsQuery.execute();
              }
              
              public Collection getCountries() throws DataAccessException
              {
                return getHibernateTemplate().find("from Country country order by country.name");
              }
            
              public Country loadCountry(long id) throws DataAccessException
              {
                return (Country) getHibernateTemplate().load(Country.class, new Long(id));
              }
            
              public void saveCountry(Country country) throws DataAccessException
              {
                getHibernateTemplate().saveOrUpdate(country);    
              }
              
              class LocationsQuery extends MappingSqlQuery  {
                    
                private static final String LOCATIONS_SQL = 
                  "SELECT blah blah blah...";    
                
                protected LocationsQuery(DataSource ds) {
                  super(ds, LOCATIONS_SQL);
                  compile();
                }
                    
                protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
                  Location location = new Location();
                  location.setId(rs.getLong("id"));
                  // other location setter calls here...
                  return location;
                }        
              }  
            }
            Here's the relevant part of my bean configuration file:

            Code:
            <bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
              <property name="mappingResources">
                <list>
                  <value>location.hbm.xml</value>
                </list>
              </property>
              <property name="hibernateProperties">
                <props>
                  <prop key="hibernate.dialect">net.sf.hibernate.dialect.DB2Dialect</prop>
                </props>
              </property>
              <property name="dataSource">
                <ref bean="dataSource"/>
              </property>
            </bean>
            
            <bean id="locationDao" class="com.cbconstantini.spring.locationapp.dao.HibernateLocationDao">
              <property name="sessionFactory">
                <ref local="sessionFactory"/>
              </property>
            </bean>

            Comment


            • #7
              You can use SessionFactoryUtils.getDataSource(), then use jdbcTemplate and the like, and Spring will actually end up using the same connection (assuming you are in a transaction), as the connection will have been bound to the thread even by the Hibernate convenience classes. You can also just pass in a jdbcTemplate (with the same datasource) to your DAO, or alternately the dataSource itself.

              Comment


              • #8
                Cool! Thanks for the tips, Colin.

                Comment


                • #9
                  Can we use stored-procedure for this approach?

                  Hi all,

                  Those discussions are very helpful. I have a similar situation. For some part of my DAOImpls, I would like to use stored procedures; other part i am using Hibernate. Is it possible I can use this approach to call store procedures? If not possible, what is the best way to deal with my situation?

                  Thanks very much

                  Comment

                  Working...
                  X