Selecting Data

Now that we have configured Hibernate in a Spring application and mentioned that we are not going to be using SQL but HQL, we can dive in and implement the DAO that actually returns some meaningful data.

Simple Mappings

First let's go back to our Test table and Test domain objects, create a simple TestDao interface, and implement it in HibernateTestDao (see Listing 9-15).

Listing 9-15: TestDao Interface

image from book
package com.apress.prospring.ch9.data;      import java.util.List;      import com.apress.prospring.ch9.domain.Test;      public interface TestDao {          public List getAll();          public Test getById(int testId);          public void save(Test test);          public void delete(int testId); }
image from book

In Listing 9-16, we implement only the getAll() and getById(int) methods; we leave the others as stubs.

Listing 9-16: TestDao Hibernate Implementation

image from book
package com.apress.prospring.ch9.data;      import java.util.List;      import org.springframework.orm.hibernate.support.HibernateDaoSupport;      import com.apress.prospring.ch9.domain.Test;          public class HibernateTestDao extends HibernateDaoSupport implements TestDao {          public List getAll() {         return getHibernateTemplate().find("from Test");     }          public Test getById(int testId) {         return (Test)getHibernateTemplate().load(Test.class,              new Integer(testId));     }          public void save(Test test) {     }          public void delete(int testId) {     }      }
image from book

HibernateDaoSupport is a convenience superclass that allows us to use the getHibernate- Template() method, which returns HibernateTemplate, which, in turn, delegates calls to Hibernate methods.

Let's take a look at what's going on in the TestDao methods implemented in the HibernateTestDao class. The getAll() method calls the find(String) method on HibernateTemplate. This method automatically prefixes the select statement with select <alias>, therefore all you need to specify as a parameter to the find call is from Test. The getById(int) method calls the load () method on HibernateTemplate. This method takes two parameters: the class that will be returned, and a primary key, in our case, testId. The latter parameter returns an object, but you can safely cast it to Test and return the selected value.

To make sure that all the code we've written so far actually runs, we create a simple Main class, which builds Spring application context from an XML file on a classpath. Before we can do this, we have to make one last modification to the applicationContext.xml file—add the testDao bean (see Listing 9-17).

Listing 9-17: Modified applicationContext.xml File

image from book
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" ¿ "http://www.springframework.org/dtd/spring-beans.dtd">      <beans>          <bean  … />      <bean  … />          <bean bold">testDao" bold">com.apress.prospring.ch9.data.HibernateTestDao">         <property name="sessionFactory"><ref local="sessionFactory"/></property>     </bean> </beans>
image from book

And this is it. We have the database ready, we have configured the Hibernate sessionFactory, and we have configured the testDao bean that implements the TestDao interface. Spring sets its sessionFactory property to an instance of the sessionFactory bean. We can give the code we have written so far a good test in Listing 9-18.

Listing 9-18: Main Class Implementation

image from book
package com.apress.prospring.ch9;      import java.util.Iterator; import java.util.List;      import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;      import com.apress.prospring.ch9.data.TestDao; import com.apress.prospring.ch9.domain.Test;      public class Main {          private ApplicationContext context;              private void test() {         TestDao testDao = (TestDao)context.getBean("testDao");         List tests = testDao.getAll();              for (Iterator i = tests.iterator(); i.hasNext();) {             Test test = (Test)i.next();             System.out.println(test);         }     }          private void run() {         System.out.println("Initializing application");         context = new ClassPathXmlApplicationContext("applicationContext.xml");                  test();                  System.out.println("Done");     }          public static void main(String[] args) {         new Main().run();     }      }
image from book

Here, you can see that the context is built in the run() method, and the test() method gets the TestDao implementation and calls getAll() to return a List of Test domain objects. Finally, we iterate over the contents of the list and print the individual items.

The result of running Ant using the build.xml script produces the following output:

Buildfile: d:\projects\pro-spring\ch9\build.xml init: compile: run:      [java] Initializing application      ...      [java] INFO: Creating shared instance of singleton bean 'sessionFactory'      [java] Sep 2, 2004 11:30:16 AM net.sf.hibernate.cfg.Environment <clinit>      [java] INFO: Hibernate 2.1.6      [java] Sep 2, 2004 11:30:16 AM net.sf.hibernate.cfg.Environment <clinit>      [java] INFO: hibernate.properties not found      [java] Sep 2, 2004 11:30:16 AM net.sf.hibernate.cfg.Environment <clinit>      [java] INFO: using CGLIB reflection optimizer      [java] Sep 2, 2004 11:30:16 AM net.sf.hibernate.cfg.Binder bindRootClass      [java] INFO: Mapping class: com.apress.prospring.ch9.domain.Test -> Test      [java] Sep 2, 2004 11:30:16 AM ¿     org.springframework.orm.hibernate.LocalSessionFactoryBean afterPropertiesSet      [java] INFO: Building new Hibernate SessionFactory      [java] Sep 2, 2004 11:30:16 AM net.sf.hibernate.cfg.¿ Configuration secondPassCompile      [java] INFO: processing one-to-many association mappings      [java] Sep 2, 2004 11:30:16 AM net.sf.hibernate.cfg.¿ Configuration secondPassCompile      [java] INFO: processing one-to-one association property references      [java] Sep 2, 2004 11:30:16 AM net.sf.hibernate.cfg.¿ Configuration secondPassCompile      [java] INFO: processing foreign key constraints      [java] Sep 2, 2004 11:30:16 AM net.sf.hibernate.dialect.Dialect <init>      [java] INFO: Using dialect: net.sf.hibernate.dialect.PostgreSQLDialect      [java] Sep 2, 2004 11:30:16 AM net.sf.hibernate.cfg.¿ SettingsFactory buildSettings      [java] INFO: Use outer join fetching: true      [java] Sep 2, 2004 11:30:16 AM ¿     net.sf.hibernate.connection.ConnectionProviderFactory newConnectionProvider      [java] INFO: Initializing connection provider: org.springframework.orm.¿ hibernate.LocalDataSourceConnectionProvider      [java] Sep 2, 2004 11:30:16 AM ¿     net.sf.hibernate.transaction.TransactionManagerLookupFactory ¿     getTransactionManagerLookup      [java] Sep 2, 2004 11:30:17 AM net.sf.hibernate.cfg.¿ SettingsFactory buildSettings      [java] INFO: Use scrollable result sets: true      [java] Sep 2, 2004 11:30:17 AM net.sf.hibernate.cfg.¿ SettingsFactory buildSettings      [java] INFO: Use JDBC3 getGeneratedKeys(): false      [java] Sep 2, 2004 11:30:17 AM net.sf.hibernate.cfg.¿ SettingsFactory buildSettings      [java] INFO: Optimize cache for minimal puts: false      [java] Sep 2, 2004 11:30:17 AM net.sf.hibernate.cfg.¿ SettingsFactory buildSettings      [java] INFO: Query language substitutions: {}      [java] Sep 2, 2004 11:30:17 AM net.sf.hibernate.cfg.¿ SettingsFactory buildSettings      [java] INFO: cache provider: net.sf.hibernate.cache.EhCacheProvider      [java] Sep 2, 2004 11:30:17 AM net.sf.hibernate.cfg.¿ Configuration configureCaches      [java] INFO: instantiating and configuring caches      [java] Sep 2, 2004 11:30:17 AM net.sf.hibernate.impl.SessionFactoryImpl <init>      [java] Sep 2, 2004 11:30:17 AM net.sf.hibernate.impl.¿ SessionFactoryObjectFactory addInstance      [java] INFO: Not binding factory to JNDI, no JNDI name configured      [java] Sep 2, 2004 11:30:17 AM ¿     org.springframework.orm.hibernate.HibernateTransactionManager ¿     afterPropertiesSet      ...      [java] Test { testId=1, name=foobar, runDate=2004-01-01 00:00:00.0}      [java] Done BUILD SUCCESSFUL Total time: 2 seconds 

As you can see, the application selects all rows from the Test table and prints out every one. However, before it can do this, it needs to configure the Hibernate framework. The output lists messages Hibernate produces on startup.

One-to-Many and Many-to-Many Selects

The code you need to write for these mappings is exactly the same as for simple mappings. First, in Listing 9-19, we create the CustomerDao interface and its implementation, HibernateCustomerDao.

Listing 9-19: CustomerDao Interface and Its Implementation

image from book
package com.apress.prospring.ch9.data;      import java.util.List;      import com.apress.prospring.ch9.domain.Customer;      // in CustomerDao.java: public interface CustomerDao {     public List getAll();     public void save(Customer customer); }      // in HibernateCustomerDao public class HibernateCustomerDao      extends HibernateDaoSupport      implements CustomerDao {          public List getAll() {         return getHibernateTemplate().find("from Customer");     }     // other methods omitted for clarity }
image from book

The CustomerDao interface defines only two methods: getAll() and save(). Both methods are fairly self-explanatory and the implementation on the Java side is very simple—we let Hibernate and Spring do all the hard work. In Listing 9-20, we modify the applicationContext.xml file and the Main class to test the code we have.

Listing 9-20: Modified ApplicationContext.xml File

image from book
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" ¿ "http://www.springframework.org/dtd/spring-beans.dtd">      <beans>          <bean  … />      <bean  … />          <bean bold">customerDao"          bold">com.apress.prospring.ch9.data.HibernateCustomerDao">         <property name="sessionFactory"><ref local="sessionFactory"/></property>     </bean> </beans>
image from book

Finally, in Listing 9-21, we add the customer() method to the Main class and call it from the run() method.

Listing 9-21: Main Class Modification to Test the CustomerDao and Mappings

image from book
package com.apress.prospring.ch9;      public class Main {     public void customer() {         CustomerDao customerDao =             (CustomerDao)context.getBean("customerDao");         List customers = customerDao.getAll();         for (Iterator i = customers.iterator(); i.hasNext(); j++) {             Customer customer = (Customer)i.next();             System.out.println(customer);         }     }     // the rest of the code omitted for clarity }
image from book

The output produced by running the application is exactly what we expected: two Customer objects, with all their properties set.

Customer { customerId=1, firstName=Jan, lastName=Machacek,  addresses=[     CustomerAddress { customerAddressId=2, line1=Line 1, line2=Line 2,          city=Hradec Kralove, postCode=500 04 },      CustomerAddress { customerAddressId=1, line1=Line 1, line2=Line 2,          city=Manchester, postCode=M1 4HH }],  permissions=[     Permission { permissionId=2, name=Edit Customer },      Permission { permissionId=3, name=Delete Customer },      Permission { permissionId=1, name=View Customer }] } Customer { customerId=2, firstName=Rob, lastName=Harrop,  addresses=[     CustomerAddress { customerAddressId=3, line1=Line 1, line2=Line 2,          city=Denton, postCode=SK1 2AB }],  permissions=[Permission { permissionId=1, name=View Customer }] }

Advanced Selects

If you need to perform more advanced selects, you can take advantage of the features of HQL. We are not going to go into a detailed description here; but as an example, in Listing 9-22, we show a query that selects all the puny customers with just one permission.

Listing 9-22: More Complex Selects

image from book
package com.apress.prospring.ch9.data;      public class HibernateCustomerDao      extends HibernateDaoSupport      implements CustomerDao {          // other methods omitted for clarity          public List getAllWithOnlyOnePermission() {         return getHibernateTemplate().find(                 "from Customer as c having c.permissions.size = ?",                 new Object[] { new Integer(1) });     }      }
image from book

This code fragment clearly shows that you can use HQL to perform almost anything you can do with SQL; it also shows how to pass parameters to an HQL query. Just as you do with JDBC, you pass the parameters in as an array of Objects.



Pro Spring
Pro Spring
ISBN: 1590594614
EAN: 2147483647
Year: 2006
Pages: 189

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net