All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.main.java.overview.html Maven / Gradle / Ivy

Go to download

Generic Dao is a Java package which allows a developer to skip writing DAOs for their persistence objects when they are using Spring and/or Hibernate. The package was originally created by Aaron Zeckoski for the Evaluation System project but was repackaged to make it distributable by request. It is used in the RSF framework (http://www2.caret.cam.ac.uk/rsfwiki/). Note about the BeanUtils provided dependency: BeanUtils is not required if you are not using it in your project. Note about the Hibernate provided dependency: Hibernate is not required if you are not using it in your project.

The newest version!


This package is designed to make it easier and faster for developers to write their DAOs
without having to rewrite the same old boring save/delete/etc functions over
and over for each persistent type but also not having to have implementation dependencies 
in their DAO interfaces. It also allows for good control over which persistent
objects are usable within the DAO and is easy to extend so you can add your own
DAO methods.
The package includes functionality for all the basic ORM CRUD type methods along with search methods and batch methods. The JDBC part of the package includes support for caching all the DAO methods (which could also be used with the hibernate part but hibernate has its own caching so you should probably use that). It also includes interceptor points for before and after all read and write methods. For simpler use cases, you can write your POJOs, make them persistent, create your DDL and not have to write a single line of DAO code.
The package is built on and depends on the spring framework.
The main website is currently here: Generic DAO Package

Usage may seem complex at first but it is actually fairly simple and is highly configurable.

There are 3 ways to use this package depending on your needs.
A) {@link org.sakaiproject.genericdao.api.BasicGenericDao} use (minimal methods)
B) {@link org.sakaiproject.genericdao.api.GeneralGenericDao} use (more advanced methods)
C) Extended Dao use (advanced methods plus your own)
Specific steps for each method are outlined below.

Using the jar package in your web application:
This is fairly easy and is just like using any other jar (with a few exceptions for Sakai developers which I mention below). Either drop the jar into your war file or use maven 2 to include it (as shown below). The jar package includes all source code which you are free to modify if you desire.

The jar is located in the following maven 2 repository for now:
https://source.sakaiproject.org/maven2/

Here is the direct link to the location of the package:
https://source.sakaiproject.org/maven2/org/sakaiproject/generic-dao/

You just need to add the following dependency to the your maven pom.xml file where the package is accessed (probably your service or dao): (replace the version number with the correct current one for the package, check the sakaiproject maven 2 repo for the latest tag)

<!-- generic DAO --> <dependency> <groupId>org.sakaiproject</groupId> <artifactId>generic-dao</artifactId> <version>1.0</version> <url>https://source.sakaiproject.org/maven2/org/sakaiproject/generic-dao/</url> </dependency>

NOTE: For users of previous versions who are working in Sakai:
It is no longer required to put generic-dao in the tomcat shared lib area and in fact you should not do that anymore. The correct way to handle this in Sakai is demonstrated in the blogwow app. Here are the conversion steps:

  1. Move your DAO api from your shared API into your IMPL (component implementation)
  2. In your component bean for your DAO transaction handling, change org.springframework.transaction.interceptor.TransactionProxyFactoryBean to org.sakaiproject.genericdao.springutil.CurrentClassLoaderTxProxyFactoryBean

You will still need to put your persistent objects and HBMs in shared or in the same classloader as the hibernate SessionFactory.

<!-- generic DAO --> <dependency> <groupId>org.sakaiproject</groupId> <artifactId>generic-dao</artifactId> <version>${sakai.generic-dao.version}</version> <url>https://source.sakaiproject.org/maven2/org/sakaiproject/generic-dao/</url> <scope>provided</scope> </dependency>

NOTE: We recommend you look at the automated tests in the source as well (/src/test), they contain sample spring config files and sample persistent objects and configurations and are a good place to start if you want sample code, this is especially important if you are using JDBC since the examples below are of use in hibernate

A) {@link org.sakaiproject.genericdao.api.BasicGenericDao} use
If you want to use the {@link org.sakaiproject.genericdao.api.BasicGenericDao} which has fairly simple but most likely high performance functionality (save/delete/find/etc) then you should do the following in your spring config file (components.xml in Sakai):

  • NOTE: Replace "*yourappname*" with your application name
  • NOTE: Replace "*YourObject*" with your persistent object(s)
  • Spring JDBC Usage:
    Create your DAO bean and provide it with a datasource and the configuration settings. In this example, autoDDL indicates the the DDL statements should be run, if this is false they will not be executed. databaseType indicates the type of database that you are using, this should be one of the type keys (e.g. HSQLDB, MYSQL, ORACLE, etc.)
    The key thing is to define your persistent object by using data mappers. One mapper for each persistent object. You can define a mapper programmatically by implementing the DataMapper interface or just use the SimpleDataMapper and put your entire configuration in spring as shown below.

    <bean id="org.sakaiproject.*yourappname*.dao.GenericDaoTarget" class="org.sakaiproject.genericdao.springjdbc.JdbcBasicGenericDao"> <property name="dataSource" ref="javax.sql.DataSource" /> <property name="autoDDL" ref="true" /> <property name="databaseType" ref="MYSQL" /> <property name="dataMappers"> <list> <bean class="org.sakaiproject.genericdao.springjdbc.SimpleDataMapper"> <property name="persistentClassname" value="org.sakaiproject.*yourappname*.dao.Person" /> <property name="tableName" value="YOUR_PERSON_TABLE" /> <property name="usePropertyNamesForColumns" value="true" /> <property name="DBTypeToFile"> <map> <entry key="HSQLDB" value="hsqldb/person.sql" /> <entry key="MYSQL" value="mysql/person.sql" /> <entry key="ORACLE" value="oracle/person.sql" /> <entry key="DB2" value="db2/person.sql" /> </map> </property> </bean> </list> </property> </bean> NOTE: Sakai:
    If you are using Sakai then you can use the built in beans from the EntityBroker project to easily get the auto.ddl and database types from the Sakai SQLService and ServerConfigurationService. <bean id="org.sakaiproject.*yourappname*.dao.GenericDaoTarget" class="org.sakaiproject.genericdao.springjdbc.JdbcBasicGenericDao"> ... <property name="autoDDL" ref="sakaiAutoDDL" /> <property name="databaseType" ref="sakaiDatabaseType" /> ... </bean> Here is another example of generic-dao using JDBC but this time using custom written DataMapper classes. This time the dao bean is wrapped in a transaction proxy which uses a transaction manager bean. The dao bean also includes optional interceptor and caching beans. <bean id="org.sakaiproject.*yourappname*.TransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="javax.sql.DataSource" /> </bean> <bean id="org.sakaiproject.*yourappname*.dao.GenericDao" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager" ref="org.sakaiproject.*yourappname*.TransactionManager" /> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> <property name="target"> <bean class="org.sakaiproject.genericdao.springjdbc.JdbcBasicGenericDao"> <property name="dataSource" ref="javax.sql.DataSource" /> <property name="dataMappers"> <list> <bean class="org.sakaiproject.*yourappname*.dao.PersonDataMapper" /> <bean class="org.sakaiproject.*yourappname*.dao.AddressDataMapper" /> </list> </property> <property name="interceptor" ref="org.sakaiproject.*yourappname*.dao.YourInterceptor" /> <property name="cacheProvider" ref="org.sakaiproject.*yourappname*.dao.YourCacheProvider" /> </bean> </property> </bean> NOTE: If you are using Sakai then you must org.sakaiproject.genericdao.springutil.CurrentClassLoaderTxProxyFactoryBean from the generic-dao utils instead of org.springframework.transaction.interceptor.TransactionProxyFactoryBean.

    Hiberate Usage:
    1) Update your spring config file for hibernate usage (for these examples we will assume you are using the Hibernate implementations):
    spring config xml example:

    <!-- Add your HBM files to the Sakai global session factory --> <bean id="org.sakaiproject.*yourappname*.AdditionalHibernateMappingsImpl" class="org.sakaiproject.springframework.orm.hibernate.impl.AdditionalHibernateMappingsImpl"> <property name="mappingResources"> <list> <value>org/sakaiproject/*yourappname*/hbm/*YourObject*.hbm.xml</value> </list> </property> </bean>
    OR if you are not using Sakai:
    Note that you will need to use the SessionFactory and TransactionManager that you created here instead of the Sakai ones used in the examples below.
    <!-- create a data source --> <bean id="*yourappname*DataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"> <value>org.hsqldb.jdbcDriver</value> </property> <property name="url"> <value>jdbc:hsqldb:.</value> </property> <property name="username"> <value>sa</value> </property> <property name="password"> <value></value> </property> </bean> <!-- create a SessionFactory bean from the data source and point it at our HBMs --> <bean id="*yourappname*SessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <property name="dataSource" ref="testDataSource" /> <property name="mappingResources"> <list> <value>org.sakaiproject.*yourappname*.model.*YourObject*</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop> <prop key="hibernate.show_sql">false</prop> <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop> <prop key="hibernate.query.substitutions">true 1, false 0</prop> <prop key="hibernate.hbm2ddl.auto">create</prop> </props> </property> </bean> <!-- Create a transaction manager from the SessionFactory --> <bean id="*yourappname*TransactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="*yourappname*SessionFactory" /> </bean>

    2) Update the remainder of the spring config file to include the necessary beans for the DAO

    <!-- create the DAO itself but as a target --> <bean id="org.sakaiproject.*yourappname*.dao.GenericDaoTarget" class="org.sakaiproject.genericdao.hibernate.HibernateBasicGenericDao"> <property name="sessionFactory" ref="org.sakaiproject.springframework.orm.hibernate.GlobalSessionFactory" /> <property name="persistentClasses"> <list> <value>org.sakaiproject.*yourappname*.model.*YourObject*</value> </list> </property> </bean> <!-- put the DAO in a transaction proxy --> <bean id="org.sakaiproject.*yourappname*.dao.GenericDao" class="org.sakaiproject.genericdao.springutil.CurrentClassLoaderTxProxyFactoryBean"> <property name="transactionManager" ref="org.sakaiproject.springframework.orm.hibernate.GlobalTransactionManager" /> <property name="target" ref="org.sakaiproject.*yourappname*.dao.GenericDaoTarget" /> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> NOTE: If you are not using Sakai then you can either use the CurrentClassLoaderTxProxyFactoryBean or the traditional org.springframework.transaction.interceptor.TransactionProxyFactoryBean here, either one is fine. If you are using Sakai then you MUST use the CurrentClassLoaderTxProxyFactoryBean as shown because of the multi classloader environment of Sakai

    3) Inject the GenericDao into your application logic bean. To do this you will need to add the following bean to your spring config file:

    <bean id="org.sakaiproject.*yourappname*.logic.YourAppLogic" class="org.sakaiproject.*yourappname*.logic.impl.YourAppLogicImpl"> <property name="genericDao" ref="org.sakaiproject.*yourappname*.dao.GenericDao" /> </bean>

    4) Modify your logic classes to accept the injected dao and then you can access the simple DAO methods. Here is an example of how to do that:

    If this is one of your application logic classes:

    	public class YourAppLogicImpl {
    	
    		private BasicGenericDao genericDao;
    		public void setGenericDao(BasicGenericDao genericDao) {
    			this.genericDao = genericDao;
    		}
    	
    		public void someMethod() {
    			YourObject yo = new YourObject("some text");
    			genericDao.save(yo);
    		}
    	
    	}
    

    B) {@link org.sakaiproject.genericdao.api.GeneralGenericDao} use
    If you decide you need more functionality that the {@link org.sakaiproject.genericdao.api.BasicGenericDao} provides, then it is easy to make the {@link org.sakaiproject.genericdao.api.GeneralGenericDao} available to your application logic.

    1) Define your HBMs and the GeneralGenericDao bean in your spring config file.
    Here is an example of the spring config file:

    <!-- Add your HBM files to the Sakai global session factory --> <bean id="org.sakaiproject.*yourappname*.AdditionalHibernateMappingsImpl" class="org.sakaiproject.springframework.orm.hibernate.impl.AdditionalHibernateMappingsImpl"> <property name="mappingResources"> <list> <value>org/sakaiproject/*yourappname*/hbm/*YourObject*.hbm.xml</value> </list> </property> </bean> <!-- Now create the bean for the complex DAO (using the all-in-one anonymous inner bean syntax) --> <bean id="org.sakaiproject.*yourappname*.dao.GeneralGenericDao" class="org.sakaiproject.genericdao.springutil.CurrentClassLoaderTxProxyFactoryBean"> <property name="transactionManager" ref="org.sakaiproject.springframework.orm.hibernate.GlobalTransactionManager" /> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> <property name="target"> <bean class="org.sakaiproject.genericdao.hibernate.HibernateGeneralGenericDao" init-method="init"> <property name="sessionFactory" ref="org.sakaiproject.springframework.orm.hibernate.GlobalSessionFactory" /> <property name="persistentClasses"> <list> <value>org.sakaiproject.*yourappname*.model.*YourObject*</value> </list> </property> </bean> </property> </bean>

    2) Inject the {@link org.sakaiproject.genericdao.api.GeneralGenericDao} into your application logic bean. To do this you will need to add the following bean to your spring config file:

    <bean id="org.sakaiproject.*yourappname*.logic.YourAppLogic" class="org.sakaiproject.*yourappname*.logic.impl.YourAppLogicImpl"> <property name="genericDao" ref="org.sakaiproject.*yourappname*.dao.GeneralGenericDao" /> </bean>

    3) Modify your application logic bean to work with the injection. Note that {@link org.sakaiproject.genericdao.api.GeneralGenericDao} provides access to the same functions as {@link org.sakaiproject.genericdao.api.BasicGenericDao} along with a large number of additional classes.

    For example, if this is one of your application logic classes:

    	public class YourAppLogicImpl {
    	
    		private GeneralGenericDao genericDao;
    		public void setGenericDao(GeneralGenericDao genericDao) {
    			this.genericDao = genericDao;
    		}
    	
    		public void someMethod() {
    			YourObject yo = new YourObject("some text");
    			genericDao.save(yo);
    		}
    	
    	}
    

    C) Extended Dao use
    If you decide you want to extend the {@link org.sakaiproject.genericdao.api.GeneralGenericDao} then it is not to difficult. Just create a new interface that extends {@link org.sakaiproject.genericdao.api.GeneralGenericDao} and a class that extends {@link org.sakaiproject.genericdao.hibernate.HibernateGeneralGenericDao} or whichever implementation of {@link org.sakaiproject.genericdao.api.GeneralGenericDao} that you want.

    1) Create the new interface for you application Dao:

    	import org.sakaiproject.genericdao.api.GeneralGenericDao;
    	public interface YourAppDao extends GeneralGenericDao {
    	}
    

    2) Create the implementation of your new interface:

    	import org.sakaiproject.*yourappname*.dao.YourAppDao;
    	import org.sakaiproject.genericdao.hibernate.HibernateGeneralGenericDao;
    	public class YourAppDaoImpl
    		extends HibernateGeneralGenericDao
    			implements YourAppDao {
    	}
    

    3) Update the spring config file so that you replace the {@link org.sakaiproject.genericdao.api.GeneralGenericDao} bean (or add this if you do not have one) with something like this:

    <bean id="org.sakaiproject.*yourappname*.dao.YourAppDao" class="org.sakaiproject.genericdao.springutil.CurrentClassLoaderTxProxyFactoryBean"> <property name="transactionManager" ref="org.sakaiproject.springframework.orm.hibernate.GlobalTransactionManager" /> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> <property name="target"> <bean class="org.sakaiproject.*yourappname*.dao.YourAppDaoImpl" init-method="init"> <property name="sessionFactory" ref="org.sakaiproject.springframework.orm.hibernate.GlobalSessionFactory" /> <property name="persistentClasses"> <list> <value>org.sakaiproject.*yourappname*.model.*YourObject*</value> </list> </property> </bean> </property> </bean>

    4) To inject your new DAO into the logic bean, you will need to add (or update) the logic bean in your spring config file:

    <bean id="org.sakaiproject.*yourappname*.logic.YourAppLogic" class="org.sakaiproject.*yourappname*.logic.impl.YourAppLogicImpl"> <property name="genericDao" ref="org.sakaiproject.*yourappname*.dao.YourAppDao" /> </bean>

    5) Update your logic class to use your DAO class type:

    	public class YourAppLogicImpl {
    	
    		private YourAppDao genericDao;
    		public void setGenericDao(YourAppDao genericDao) {
    			this.genericDao = genericDao;
    		}
    	
    		public void someMethod() {
    			YourObject yo = new YourObject("some text");
    			genericDao.save(yo);
    		}
    	
    	}
    

    Note: If you decide that you want to use hibernate lazy loading you will need to create and use a wrapper class and a set of beans as shown below. The method shown works in RSF. If you are using some other presentation layer you will have to adapt it. I do not recommend you depend on lazy loading in your usage though.
    Sample Wrapper Class:

    package org.sakaiproject.genericdao.wrapper;
    
    import uk.org.ponder.util.RunnableInvoker;
    import org.sakaiproject.*yourappname*.dao.YourAppDao;
    
    /**
     * This wraps our dao so that it can be accessed lazily
     * @author Aaron Zeckoski ([email protected])
     */
    public class ModelAccessWrapperInvoker implements RunnableInvoker {
    
    	private YourAppDao genericDao;
    	public void setGenericDao(YourAppDao genericDao) {
    		this.genericDao = genericDao;
    	}
    
    	/* (non-Javadoc)
    	 * @see uk.org.ponder.util.RunnableInvoker#invokeRunnable(java.lang.Runnable)
    	 */
    	public void invokeRunnable(Runnable toinvoke) {
    		genericDao.invokeTransactionalAccess(toinvoke);
    	}
    
    }
    

    Then you will need to add some wrapper classes to the RSF applicationContext.xml like so:
    
    
    	
    
    
    
    	
    		
    	
    	
    
    




    © 2015 - 2024 Weber Informatics LLC | Privacy Policy