package com.xmp.web2.dao;
public class BaseDAOHibernate extends HibernateDaoSupport implements DAO {
private static final Log LOGGER = LogFactory.getLog(BaseDAOHibernate.class);
protected DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void saveObject(final Object object) {
getHibernateTemplate().saveOrUpdate(object);
}
public Object getObject(final Class clazz, final Serializable id) {
Object object = getHibernateTemplate().get(clazz, id);
return object;
}
public List getObjects(final Class clazz) {
return getHibernateTemplate().loadAll(clazz);
}
public void removeObject(final Class clazz, final Serializable id) {
getHibernateTemplate().delete(getObject(clazz, id));
}
public List findObject(final Class clazz, final String columnName, final String articleID) {
return getHibernateTemplate().find("from " + clazz.getName() + " tableAlias where tableAlias." + columnName + " in ( " + articleID + " )");
}
/**
* Accepts a HQL and ordered map of parameters.
*
* @param query
* @param parameters
* @return
*/
public List search(String query, LinkedHashMap parameters) throws xmpWebException {
boolean keepSessionOpen=false;
return search(query, parameters, keepSessionOpen);
}
/**
* Accepts a HQL and ordered map of parameters.
* The caller of this method should explicitly close the session.
* @param query
* @param parameters
* @parm keepSessionOpen -boolean to instruct if the session should be closed or not.
* @return
*/
protected List search(String query, LinkedHashMap parameters, boolean keepSessionOpen) throws xmpWebException {
List objList = null;
Session session = null;
try {
if (LOGGER.isInfoEnabled()) {
LOGGER.info(new StringBuilder().append("Searching ( query = ").append(query).append(" ,parameters =").append(parameters).append(")").toString());
}
session = getHibernateTemplate().getSessionFactory().openSession();
Query queryObj = session.createQuery(query);
queryObj.setCacheable(true);
if (parameters != null) {
for (Iterator iter = parameters.keySet().iterator(); iter.hasNext();) {
String key = (String) iter.next();
Object value = parameters.get(key);
queryObj.setParameter(key, value);
}
}
objList = queryObj.list();
} catch (Exception e) {
String msg = new StringBuilder("Search failed ( query = ").append("Searching ( query = ").append(query).append(" ,parameters =").append(parameters).append(")").toString();
LOGGER.error(msg, e);
throw new xmpWebException(msg, e);
} finally {
if (!keepSessionOpen) {
if (session != null && session.isOpen())
session.close();
}
}
return objList;
}
/**
* Accepts a HQL and ordered map of parameters. Useful with pagination as it
* accepts pageNo and pagesize.
*
* @param query
* @param parameters
* @param pageNo - The starting page number
* @param pageSize - The max record size.
* @return
*/
protected List searchAdvanced(final String query, final LinkedHashMap parameters, final int pageNo, final int pageSize) throws xmpWebException {
boolean keepSessionOpen = false;
return searchAdvanced(query, parameters, pageNo, pageSize, keepSessionOpen);
}
/**
* Accepts a HQL and ordered map of parameters. Useful with pagination as it
* accepts pageNo and pagesize.
*
* @param query
* @param parameters
* @param pageNo - The starting page number
* @param pageSize - The max record size.
* @param keepSessionOpen - boolean to identify if session needs to be kept open or not.
* @return
*/
protected List searchAdvanced(final String query, final LinkedHashMap parameters, final int pageNo, final int pageSize, boolean keepSessionOpen) throws xmpWebException {
if (LOGGER.isInfoEnabled()) {
LOGGER.info(new StringBuilder("Searching with ( query = ").append(query).append(" ,parameters =").append(parameters).append(" ,pageNo =").append(pageNo).append(" ,pageSize= ").append(
pageSize).append(" )").toString());
}
Session session = null;
try {
session = getHibernateTemplate().getSessionFactory().openSession();
Query queryObject = session.createQuery(query);
// queryObj.setCacheable(true);
if (parameters != null) {
for (Iterator iter = parameters.keySet().iterator(); iter.hasNext();) {
String key = (String) iter.next();
Object value = parameters.get(key);
queryObject.setParameter(key, value);
}
}
queryObject.setMaxResults((pageSize < msg =" new" query = ").append(query).append(" parameters =").append(parameters).append(" pageno =").append(pageNo).append(" pagesize= ").append( pageSize).append(">
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
The above should solve most of the basic coding effort in DAO layer which we do 90% of the time.
Spring+Hibernate Junit testing:
Spring framework provides a nifty base class (AbstractTransactionalDataSourceSpringContextTests) that provides automatic transaction rollback, exposing a JDBC template to interact with the DB and auto wiring of beans.
Lets take a simple DAO class that save a User object to the database:
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
public void save(User user) {
getHibernateTemplate().save(user);
}
}
|
public class UserDaoTest extends AbstractTransactionalDataSourceSpringContextTests {
private UserDao userDao;
private SessionFactory sessionFactory = null;
protected String[] getConfigLocations() {
return new String[]{"test-spring-config.xml"};
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
/**
* Test the save method
*
*/
public void testSave(){
String query = "select count(*) from user where first_name = 'Firstname'";
int count = jdbcTemplate.queryForInt(query);
assertEquals("A user already exists in the DB", 0, count);
User user = new User();
user.setFirstName("Firstname");
userDao.saveUser(user);
// flush the session so we can get the record using JDBC template
SessionFactoryUtils.getSession(sessionFactory, false).flush();
count = jdbcTemplate.queryForInt(query);
assertEquals("User was not found in the DB", 1, count);
}
}
|
/**
* Overridden method from base class which gets called automatically
*/
protected void onSetUpBeforeTransaction() throws Exception {
super.onSetUpBeforeTransaction();
userDao = (UserDao) applicationContext.getBean("userDao");
}
|
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean name="userDao" class="com.dao.UserDaoImpl">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="mappingResources">
<list>
<value>hibernates/User.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL" />
<property name="username" value="test" />
<property name="password" value="test" />
</bean>
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>
</beans>
Useful stuff:
HQL many to many query for retreival
from UserTask ut where :journal in elements(ut.journals)