您的位置:首页 > 编程语言 > Java开发

spring2.5整合hibernate3.3的泛型Dao并加入spring jdbc的支持

2009-08-22 22:20 519 查看
以前写的一个改进版泛型dao,在这里
。基本实现了0代码编写dao。现在又加入了spring jdbc的支持,使得dao即可以用实体对象进行数据存取,有可以用jdbc的底层化操作删除,更新。结构见图:



具体代码和上图对应:

DaoTest.java

package com.test;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.hibernate.entityclass.Daotest;
import com.tinylight.dao.base.IBaseDao;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class DaoTest {

@Resource(name="demoDao")
private IBaseDao<Daotest,Integer> demoDao;

@Test
public void test(){

}
}


BaseDao.java

/**
*
*/
package com.tinylight.dao.base;
import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.StatelessSession;
import org.springframework.orm.hibernate3.HibernateTemplate;
import com.tinylight.dao.hibernate.GenericDao;
import com.tinylight.dao.hibernate.GenericEntityDao;
import com.tinylight.dao.jdbc.SimpleJdbcDao;
import com.tinylight.dao.support.Page;
/**
* @author scott.Cgi
* @since  2009-5-12
* 提供dao的所有操作<br>
* 实现类由spring注入:<br>
* {@link com.tinylight.dao.hibernate.GenericEntityDao}
* {@link com.tinylight.dao.hibernate.GenericDao}
* {@link com.tinylight.dao.jdbc.SimpleJdbcDao}
*/
public class BaseDao<T,PK extends Serializable> implements IBaseDao<T,PK>{
protected Class<T> entityClass;// DAO所管理的Entity类型.
private GenericEntityDao<T,PK> gedao;
private GenericDao gdao;
private SimpleJdbcDao sjdao;

public Class<T> getEntityClass() {return entityClass;}
public void setEntityClass(Class<T> entityClass) {this.entityClass = entityClass;}

public GenericEntityDao<T, PK> getGedao() {return gedao;}
public void setGedao(GenericEntityDao<T, PK> gedao) {this.gedao = gedao;}

public GenericDao getGdao() {return gdao;}
public void setGdao(GenericDao gdao) {this.gdao = gdao;}

public SimpleJdbcDao getSjdao() {return sjdao;}
public void setSjdao(SimpleJdbcDao sjdao) {this.sjdao = sjdao;}
/**
*让spring提供构造函数注入
*/
public BaseDao(Class<T> type) {
this.entityClass = type;
}

public BaseDao(){}

public void clear() {
gdao.clear();
}

public Query createQuery(String hql, Object... values) {
return gdao.createQuery(hql, values);
}

public void delete(T entityObject) {
gedao.delete(entityObject);
}

public void deleteById(PK id) {
gedao.deleteById(id);
}

public void evict(T entityObject) {
gedao.evict(entityObject);
}

public List<T> find(String hql, Object... values) {
return gdao.find(hql, values);
}

public List<T> findByNamedParams(String hql, String[] paramNames,
Object... values) {
return gdao.findByNamedParams(hql, paramNames, values);
}

public void flush() {
gdao.flush();
}

public List<T> getAll() {
return gedao.getAll();
}

public T getById(PK id) {
return gedao.getById(id);
}

public Session getNativeHibernateSession() {
return gdao.getNativeHibernateSession();
}

public StatelessSession getNativeStatelessHibernateSession() {
return gdao.getNativeStatelessHibernateSession();
}

public HibernateTemplate getSpringHibernateTemplate() {
return gdao.getSpringHibernateTemplate();
}

public Iterator<T> iterator(String hql, Object... values) {
return gdao.iterator(hql, values);
}

public SimpleJdbcDao jdbc() {
return sjdao;
}

public T load(PK id) {
return gedao.load(id);
}

public void load(T entityObject, PK id) {
gedao.load(entityObject, id);
}

public T merge(T entityObject) {
return gedao.merge(entityObject);
}

public SQLQuery nativeSqlQuery(String sql) {
return gdao.nativeSqlQuery(sql);
}

public Page<T> pagedQuery(String countHql,String hql, int pageNo, int pageSize,
Object... values) {
return gdao.pagedQuery(countHql,hql, pageNo, pageSize, values);
}

public Page<T> pagedQueryByStartNo(String countHql,String hql, int startNo, int pageSize,
Object... values) {
return gdao.pagedQueryByStartNo(countHql,hql, startNo, pageSize, values);
}

public void refresh(T entityObject) {
gedao.refresh(entityObject);
}

public void save(T entityObject) {
gedao.save(entityObject);
}

}


IBaseDao.java

/**
*
*/
package com.tinylight.dao.base;
import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.StatelessSession;
import org.springframework.orm.hibernate3.HibernateTemplate;
import com.tinylight.dao.jdbc.SimpleJdbcDao;
import com.tinylight.dao.support.Page;
/**
* @author scott.Cgi
* @since  2009-5-12
*
*/
public interface IBaseDao<T,PK extends Serializable> {
/**
* 根据主键类型的id获取实体对象,立即执行查询返回对象,数据库没有匹配则返回null
*/
public T getById(PK id);

/**
* 获取实体类型的全部对象
*/
public List<T> getAll();

/**
* 获取实体对象的代理,如果数据库没有匹配则异常,实体类有关联其它对象则延时加载
* @param id
* @return
*/
public T load(PK id);

/**
* 把数据加载到指定的非持久化实例上
* @param entityObject
* @param id
*/
public void load(T entityObject,PK id);

/**
* 删除对象.
*/
public void delete(T entityObject);

/**
* 根据id删除对象
* @param id
*/
public void deleteById(PK id);

/**
* 强迫装载对象和它的集合,使用了触发器的数据字段比较适合使用
* @param entityObject
*/
public void refresh(T entityObject);

/**
* 消除与 Hibernate Session 的关联
* @param entityObject
*/
public void evict(T entityObject);

/**
* 保存对象.<br>
* 如果对象已在本session中持久化了,不做任何事。<br>
* 如果另一个seesion拥有相同的持久化标识,抛出异常。<br>
* 如果没有持久化标识属性,调用save()。<br>
* 如果持久化标识表明是一个新的实例化对象,调用save()。<br>
* 如果是附带版本信息的(version或timestamp)且版本属性表明为新的实例化对象就save()。<br>
* 否则调用update()重新关联托管对象
* @param entityObject
*/
public void save(T entityObject);

/**
* 如果对象已在本session中持久化了,覆盖原有的<br>
* 如果session中没有对应对象,从数据库加载<br>
* 如果是脱管对象,则什么都不做
* @param entityObject
* @return
*/
public T merge(T entityObject);

/**
* 根据hql查询,直接使用HibernateTemplate的find函数.
* @param <T>
* @param hql
* @param values
* @return
*/
public  List<T> find(String hql, Object... values);

/**
* 根据命名参数查询
* @param <T>
* @param hql 带有命名参数的hql语句
* @param paramNames 命名参数的名字
* @param values  命名参数的值<br>
* <b>例如:</b><br>
* findByNamedParams("from Test where t1 = :t",new String[]{"t"},tValue);
* @return
*/
public  List<T> findByNamedParams(String hql,String[] paramNames,Object...values);

/**
* 创建Query对象.<br>
* 对于需要first,max,fetchsize,cache,cacheRegion等诸多设置的函数,可以在返回Query后自行设置.
* @param hql
* @param values
* @return
*/
public Query createQuery(String hql,Object... values);

/**
* 执行一些必须的sql语句把内存中的对象同步到数据库中
*/
public void flush();

/**
* 清除对象缓存
*/
public void clear();

/**
* 返回iterator接口类型的结果
* @param <T>
* @param hql
* @param values
* @return
*/
public  Iterator<T> iterator(String hql,Object...values);

/**
* @return 当前上下文的原生Hibernate session对象,依然受到spring事务管理不需要手动close
*/
public Session getNativeHibernateSession();

/**
* @return 当前上下文的原生Hibernate StatelessSession对象<br>
* 此对象不级联关联实例,忽略集合不触发Hibernate事件模型和拦截器,没有一级缓存,没有持久化上下文,接近JDBC.
*/
public StatelessSession getNativeStatelessHibernateSession();

/**
* 执行本地查询获得SQLQuery对象<br>
* 可以调用addEntity(*.class).list();获得对应实体list集合<br>
* addEntity.add(*.class).addJoin(*.class).list();获得一对多代理对象<br>
* 更多用法见google
* @param sql
* @return
*/
public SQLQuery nativeSqlQuery(String sql);

/**
* @param <T>
* @param countHql 计算数据总条数的hql语句(就是带count(*)的hql)
* @param hql
* @param pageNo 页面号
* @param pageSize 页面容量
* @param values
* @return
*/
public  Page<T> pagedQuery(String countHql,String hql, int pageNo, int pageSize, Object... values);

/**
* @param <T>
* @param countHql 计算数据总条数的hql语句(就是带count(*)的hql)
* @param hql
* @param startNo 分页从哪一条数据开始
* @param pageSize 页面容量
* @param values
* @return
*/
public  Page<T> pagedQueryByStartNo(String countHql,String hql, int startNo, int pageSize, Object... values);

/**
* @return 获得spring的HibernateTemplate拥有更多的功能
*/
public HibernateTemplate getSpringHibernateTemplate();

/**
* @return 获得jdbc操作的超绚酷dao
*/
public SimpleJdbcDao jdbc();
}


GenericDao.java

/**
*
*/
package com.tinylight.dao.hibernate;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.StatelessSession;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import com.tinylight.dao.support.Page;
/**
* 继承自spring的HibernateDaoSupport<br>
* 提供了和具体实体类无关的数据库操作
* @author scott.Cgi
* @since  2009-5-10
*
*/
public class GenericDao extends HibernateDaoSupport {

/**
* 根据hql查询,直接使用HibernateTemplate的find函数.
* @param <T>
* @param hql
* @param values
* @return
*/
@SuppressWarnings("unchecked")
public <T> List<T> find(String hql, Object... values) {
return this.getHibernateTemplate().find(hql, values);
}

/**
* 根据命名参数查询
* @param <T>
* @param hql 带有命名参数的hql语句
* @param paramNames 命名参数的名字
* @param values  命名参数的值<br>
* <b>例如:</b><br>
* findByNamedParams("from Test where t1 = :t",new String[]{"t"},tValue);
* @return
*/
@SuppressWarnings("unchecked")
public <T> List<T> findByNamedParams(String hql,String[] paramNames,Object...values){
return this.getHibernateTemplate().findByNamedParam(hql, paramNames, values);
}

/**
* 创建Query对象.<br>
* 对于需要first,max,fetchsize,cache,cacheRegion等诸多设置的函数,可以在返回Query后自行设置.
* @param hql
* @param values
* @return
*/
public Query createQuery(String hql,Object... values) {
//这里的false表示不创建session保证,当前操作在spring同一个事务的管理下
Query query = this.getSession(false).createQuery(hql);
if (values != null) {
for (int i = 0; i < values.length; i++) {
query.setParameter(i, values[i]);
}
}
return query;
}

/**
* 执行一些必须的sql语句把内存中的对象同步到数据库中
*/
public void flush() {
this.getHibernateTemplate().flush();
}

/**
* 清除对象缓存
*/
public void clear() {
this.getHibernateTemplate().clear();
}

/**
* 返回iterator接口类型的结果
* @param <T>
* @param hql
* @param values
* @return
*/
@SuppressWarnings("unchecked")
public <T> Iterator<T> iterator(String hql,Object...values){
return	this.getHibernateTemplate().iterate(hql, values);
}

/**
* @return 当前上下文的原生Hibernate session对象,依然受到spring事务管理不需要手动close
*/
public Session getNativeHibernateSession(){
return this.getSessionFactory().getCurrentSession();
}

/**
* @return 当前上下文的原生Hibernate StatelessSession对象<br>
* 此对象不级联关联实例,忽略集合不触发Hibernate事件模型和拦截器,没有一级缓存,没有持久化上下文,接近JDBC.
*/
public StatelessSession getNativeStatelessHibernateSession(){
return this.getSessionFactory().openStatelessSession();
}

/**
* 执行本地查询获得SQLQuery对象<br>
* 可以调用addEntity(*.class).list();获得对应实体list集合<br>
* addEntity.add(*.class).addJoin(*.class).list();获得一对多代理对象<br>
* 更多用法见google
* @param sql
* @return
*/
public SQLQuery nativeSqlQuery(String sql){
return this.getSession(false).createSQLQuery(sql);
}

/**
* @param <T>
* @param countHql 计算数据总条数的hql语句(就是带count(*)的hql)
* @param hql
* @param pageNo 页面号
* @param pageSize 页面容量
* @param values
* @return
*/
@SuppressWarnings("unchecked")
public <T> Page<T> pagedQuery(String countHql,String hql, int pageNo, int pageSize, Object... values) {
// Count查询
List<T> countlist = this.getHibernateTemplate().find(countHql, values);
long totalCount = (Long) countlist.get(0);
if (totalCount < 1)
return new Page<T>();
// 当前页的开始数据索引
long startIndex = Page.getStartOfPage(pageNo, pageSize);
Query query = this.createQuery(hql, values);
List<T> list = query.setFirstResult((int) startIndex).setMaxResults(pageSize).list();
return new Page<T>(startIndex, totalCount, pageSize, list);
}

/**
* @param <T>
* @param countHql 计算数据总条数的hql语句(就是带count(*)的hql)
* @param hql
* @param startNo 分页从哪一条数据开始
* @param pageSize 页面容量
* @param values
* @return
*/
@SuppressWarnings("unchecked")
public <T> Page<T> pagedQueryByStartNo(String countHql,String hql, int startNo, int pageSize, Object... values){
// Count查询
List<T> countlist = getHibernateTemplate().find(countHql, values);
long totalCount = (Long) countlist.get(0);
if (totalCount < 1)
return new Page();

int startIndex = startNo;
Query query = createQuery(hql, values);
List<T> list = query.setFirstResult(startIndex).setMaxResults(pageSize).list();
return new Page<T>(startIndex, totalCount, pageSize, list);
}

/**
* @return 获得spring的HibernateTemplate拥有更多的功能
*/
public HibernateTemplate getSpringHibernateTemplate(){
return this.getHibernateTemplate();
}
}


GenericEntityDao.java

/**
*
*/
package com.tinylight.dao.hibernate;
import java.io.Serializable;
import java.util.List;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
/**
* 负责为单个Entity对象提供CRUD操作的Hibernate DAO基类.<br>
* 子类只要在类定义时指定所管理Entity的Class<br>
* 即拥有对单个Entity对象的CRUD操作.
* @author scott.Cgi
* @since  2009-5-11
*
*/
public class GenericEntityDao<T,PK extends Serializable> extends HibernateDaoSupport {

protected Class<T> entityClass;// DAO所管理的Entity类型.
public void setEntityClass(Class<T> type){//注入实体类型
this.entityClass=type;
}
public Class<T> getEntityClass(){
return this.entityClass;
}

public GenericEntityDao(){}
public GenericEntityDao(Class<T> entityClass){this.entityClass = entityClass;}
/**
* 根据主键类型的id获取实体对象,立即执行查询返回对象,数据库没有匹配则返回null
*/
@SuppressWarnings("unchecked")
public T getById(PK id) {
return (T)this.getHibernateTemplate().get(this.entityClass, id);
}

/**
* 获取实体类型的全部对象
*/
@SuppressWarnings("unchecked")
public List<T> getAll() {
return (List<T>)(this.getHibernateTemplate().loadAll(this.entityClass));
}

/**
* 获取实体对象的代理,如果数据库没有匹配则异常,实体类有关联其它对象则延时加载
* @param id
* @return
*/
@SuppressWarnings("unchecked")
public T load(PK id){
return (T)this.getHibernateTemplate().load(this.entityClass, id);
}

/**
* 把数据加载到指定的非持久化实例上
* @param entityObject
* @param id
*/
public void load(T entityObject,PK id){
this.getHibernateTemplate().load(entityObject, id);
}

/**
* 删除对象.
*/
public void delete(T entityObject) {
this.getHibernateTemplate().delete(entityObject);
}

/**
* 根据id删除对象
* @param id
*/
public void deleteById(PK id){
this.delete(this.getById(id));
}

/**
* 强迫装载对象和它的集合,使用了触发器的数据字段比较适合使用
* @param entityObject
*/
public void refresh(T entityObject){
this.getHibernateTemplate().refresh(entityObject);
}

/**
* 消除与 Hibernate Session 的关联
* @param entityObject
*/
public void evict(T entityObject){
this.getHibernateTemplate().evict(entityObject);
}

/**
* 保存对象.<br>
* 如果对象已在本session中持久化了,不做任何事。<br>
* 如果另一个seesion拥有相同的持久化标识,抛出异常。<br>
* 如果没有持久化标识属性,调用save()。<br>
* 如果持久化标识表明是一个新的实例化对象,调用save()。<br>
* 如果是附带版本信息的(version或timestamp)且版本属性表明为新的实例化对象就save()。<br>
* 否则调用update()重新关联托管对象
* @param entityObject
*/
public void save(T entityObject){
this.getHibernateTemplate().saveOrUpdate(entityObject);
}

/**
* 如果对象已在本session中持久化了,覆盖原有的<br>
* 如果session中没有对应对象,从数据库加载<br>
* 如果是脱管对象,则什么都不做
* @param entityObject
* @return
*/
@SuppressWarnings("unchecked")
public T merge(T entityObject){
return (T)this.getHibernateTemplate().merge(entityObject);
}

}


SimpleJdbcDao.java

/**
*
*/
package com.tinylight.dao.jdbc;
import java.sql.Connection;
import java.sql.SQLException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.jdbc.support.rowset.SqlRowSet;
/**
* 继承spring的SimpleJdbcDaoSupport
* 提供对数据库jdbc级别的操作
* 内部使用spring的SimpleJdbcTemplate与JdbcTemplate
* @author scott.Cgi
* @since  2009-5-7
*/
public class SimpleJdbcDao extends SimpleJdbcDaoSupport {

/**
* 提供对表的更改和删除操作
* @param sql 要执行的sql语句
* @param args 变参
* @return 影响的行数
*/
public int update(String sql,Object...args){
return this.getSimpleJdbcTemplate().update(sql, args);
}

/**
* 批量更新多条记录
* @param sql 多条sql组成的数组(不带参数的)
* @see 带参数的见: <br>
* getJdbcTemplate().batchUpdate(String[] sql,BatchPreparedStatementSetter pss)
* @return 影响行数数组
*/
public int[] batchUpdate(String[] sql){
return this.getJdbcTemplate().batchUpdate(sql);
}

/**
* 获取行数
* @param countSql 计算行数的sql语句
* @return
*/
public long countRows(String countSql){
return this.getJdbcTemplate().queryForLong(countSql);
}

/**
* 获取本地的Connection对象
* @return
*/
public Connection getNativeConn(){

//从当前线程绑定的数据连接获取连接
Connection conn = DataSourceUtils.getConnection(this.getJdbcTemplate().getDataSource());
try {
conn = this.getJdbcTemplate().getNativeJdbcExtractor().getNativeConnection(conn);
} catch (SQLException e) {
e.printStackTrace();
return null;
}

return conn;
}

/**
* 获得断开数据库连接的行集,大结果集会消耗内存,受到maxSize的限制
* @param sql 要执行的sql语句带?占位符
* @param params 填充占位符的数组
* @param types 填充参数类型(java.sql.Types中的常量)
* 例如:new int[]{Types.VARCHAR,Types.DATE}
* @return 影响的行数<br>
* <b>注:</b> params和types同时为空,sql为不带?占位符;仅仅types为空时,由spring去猜测类型
*/
public SqlRowSet queryForRowSet(String sql,Object[] params,int[] types){

if(params != null && types != null){
return this.getJdbcTemplate().queryForRowSet(sql, params, types);
}else if(params != null && types == null){
return this.getJdbcTemplate().queryForRowSet(sql, params);
}else {
return this.getJdbcTemplate().queryForRowSet(sql);
}
}

/**
* 提供对表的更改和删除操作
* @param hql 使用了命名参数的sql语句
* @param sps 例如:<br>
* new BeanPropertySqlParamterSource(javaBean其属性要和命名参数对应);<br>
* new MapSqlParameterSource().add("命名参数",参数对应的值).add()...可以链式调用
* @return KeyHolder主键持有者对象;如果是新增数据,KeyHolder持有新增的主键值<br>
* 有3个方法可调用:<br>getKey()一个数字主键<br>
* getKeys()复合主键Map结构<br>
* getKeyList()多个主键由多个Map组成的List
*/
public KeyHolder updateNamedParamer(String hql,SqlParameterSource sps){
KeyHolder keyHolder = new GeneratedKeyHolder();
this.getSimpleJdbcTemplate().getNamedParameterJdbcOperations().update(hql, sps, keyHolder);
return keyHolder;
}

/**
* 执行sql语句,如创建表等
* @param sql
*/
public void executeSql(String sql){
this.getJdbcTemplate().execute(sql);
}

/**
* @return 获得spring的JdbcTemplate使用更多功能
*/
public JdbcTemplate getSpringJdbcTemplate(){
return this.getJdbcTemplate();
}

/**
* 引入jdk5.0语法的JdbcTemplate的简化版本
* @return 获得spring的SimpleJdbcTemplate使用更多功能
*/
public  SimpleJdbcTemplate getSpringSimplaJdbcTemplate(){
return this.getSimpleJdbcTemplate();
}
}


Page.java

package com.tinylight.dao.support;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
/**
* 分页对象.包含当前页数据及分页信息如总记录数.
*
* @author scott.Cgi
* @since  2008-6-29
*/
public class Page<T> implements Serializable {
private static final long serialVersionUID = -5624189033006412710L;
private static long DEFAULT_PAGE_SIZE = 20;
private long pageSize = DEFAULT_PAGE_SIZE; // 每页的记录数
private long start; // 当前页第一条数据在List中的位置,从0开始
private List<T> data = Collections.emptyList(); // 当前页中存放的记录
private long totalCount = 0; // 总记录数
/**
* 构造方法,只构造空页.
*/
public Page() {
this(0l, 0l, DEFAULT_PAGE_SIZE, Collections.<T>emptyList());
}
/**
* 默认构造方法.
*
* @param start	 本页数据在数据库中的起始位置
* @param totalSize 数据库中总记录条数
* @param pageSize  本页容量
* @param data	  本页包含的数据
*/
public Page(long start, long totalSize, long pageSize, List<T> data) {
this.pageSize = pageSize;
this.start = start;
this.totalCount = totalSize;
this.data = data;
}
/**
* 取总记录数.
*/
public long getTotalCount() {
return this.totalCount;
}
/**
* 取总页数.
*/
public long getTotalPageCount() {
if (totalCount % pageSize == 0)
return totalCount / pageSize;
else
return totalCount / pageSize + 1;
}
/**
* 取每页数据容量.
*/
public Long getPageSize() {
return pageSize;
}
/**
* 取当前页中的记录.
*/
public List<T> getResult() {
return data;
}
/**
* 取该页当前页码,页码从1开始.
*/
public long getCurrentPageNo() {
return start / pageSize + 1;
}
/**
* 该页是否有下一页.
*/
public boolean hasNextPage() {
return this.getCurrentPageNo() < this.getTotalPageCount();
}
/**
* 该页是否有上一页.
*/
public boolean hasPreviousPage() {
return this.getCurrentPageNo() > 1;
}
/**
* 获取任一页第一条数据在数据集的位置,每页条数使用默认值.
*
*/
protected static long getStartOfPage(long pageNo) {
return getStartOfPage(pageNo, DEFAULT_PAGE_SIZE);
}
/**
* 获取任一页第一条数据在数据集的位置.
*
* @param pageNo   从1开始的页号
* @param pageSize 每页记录条数
* @return 该页第一条数据
*/
public static long getStartOfPage(long pageNo, long pageSize) {
return (pageNo - 1) * pageSize;
}
}


applicationContext-annotation.xml

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.directwebremoting.org/schema/spring-dwr http://www.directwebremoting.org/schema/spring-dwr-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> 
<context:annotation-config/>
</beans>


applicationContext-list.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <description>导入applicationContext文件列表,可随时通过注释disable不需要的模块</description>
<!-- 导入spring aop配置文件 -->
<import resource="applicationContext-tx.xml" />
<!-- 导入spring dao配置文件 -->
<import resource="tinylight-dao.xml" />

</beans>


applicationContext-tx.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 使用aop/tx命名空间 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 配置事务管理器bean,使用HibernateTransactionManager事务管理器 -->
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<!-- 为事务管理器注入sessionFactory" -->
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!-- 通过aop定义事务增强切面 -->
<aop:config>
<!-- 使用强大的切点表达式语言轻松定义目标方法 -->
<aop:pointcut id="serviceMethod"
expression="execution(* com.tinylight.dao.base.IBaseDao.*(..))" />
<!-- 引用事务增强 -->
<aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice" />
</aop:config>
<!-- 事务增强 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<!-- 属性事务定义 -->
<tx:attributes>
<!--OpenSessionInViewFilter在getSession的时候,会把获取回来的session的flush mode 设为FlushMode.NEVER。
然后把该sessionFactory绑定到TransactionSynchronizationManager,使request的整个过程都使用同一个session,
在请求过后再接除该sessionFactory的绑定,最后closeSessionIfNecessary根据该session是否已和transaction绑定来决定是否关闭session。
在这个过程中,若HibernateTemplate 发现自当前session有不是readOnly的transaction,就会获取到FlushMode.AUTO Session,使方法拥有写权限。
也即是,如果有不是readOnly的transaction就可以由Flush.NEVER转为Flush.AUTO,拥有insert,update,delete操作权限,如果没有transaction,
并且没有另外人为地设flush model的话,则doFilter的整个过程都是Flush.NEVER。所以受transaction保护的方法有写权限,没受保护的则没有  -->
<tx:method name="*" />
</tx:attributes>
</tx:advice>

</beans>


applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <!-- 使用外部文件配置数据源的属性 -->
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<!-- 外部文件地址 -->
<value>classpath:database_conn.properties</value>
</list>
</property>
<property name="fileEncoding" value="utf-8" />
</bean>
<!-- 配置数据源 -->
<bean id="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${driverClassName}" />
<property name="jdbcUrl" value="${url}"/>
<property name="user" value="${username}"/>
<property name="password" value="${password}"/>

<!--连接池中保留的最小连接数。-->
<property name="minPoolSize" value="5" />

<!--连接池中保留的最大连接数。Default: 15 -->
<property name="maxPoolSize" value="20" />

<!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
<property name="initialPoolSize" value="10" />

<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
<property name="maxIdleTime" value="60" />

<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
<property name="acquireIncrement" value="5" />

<!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements
属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。
如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0-->
<property name="maxStatements" value="0"/>
<!--每60秒检查所有连接池中的空闲连接。Default: 0 -->
<property name="idleConnectionTestPeriod" value="60"/>

<!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
<property name="acquireRetryAttempts" value="0" />
<!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效
保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试
获取连接失败后该数据源将申明已断开并永久关闭。Default: false-->
<property name="breakAfterAcquireFailure" value="true" />

<!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的
时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
等方法来提升连接测试的性能。Default: false -->
<property name="testConnectionOnCheckout" value="false" />
</bean>
<!-- hibernate3 sessionfactory配置
使用AnnotationSessionFactoryBean创建基于JPA注解的SessionFactory-->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<!-- 引用数据源 -->
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="namingStrategy">
<bean class="org.hibernate.cfg.ImprovedNamingStrategy" />
</property>
<!-- hibernate的属性具体见hibernate文档 -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<!-- 非0值 指定jdbc抓取数量的大小调用Statement.setFetchSize() -->
<prop key="hibernate.jdbc.fetch_size">${hibernate.jdbc.fetch_size}</prop>
<!-- jdbc批量更新 建议5到30 -->
<prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop>
<!--说明一下:如果不设置查询缓存,那么hibernate只会缓存使用load()方法获得的单个持久化对象
如果想缓存使用findall()、list()、Iterator()、createCriteria()、createQuery()
等方法获得的数据结果集的话就需要设置hibernate.cache.use_query_cache true 才行  -->
<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
<prop key="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider
</prop>
<prop key="hibernate.cache.provider_configuration_file_resource_path">
${hibernate.ehcache_config_file}
</prop>
</props>
</property>

<property name="packagesToScan" value="com.hibernate.entityclass" />
</bean>

<!-- 加载spring功能列表文件 -->
<import resource="applicationContext-list.xml"/>
</beans>


database_conn.properties

#jdbc settings
driverClassName=org.gjt.mm.mysql.Driver
url=jdbc/:mysql/://127.0.0.1/:3306/mytest
username=root
password=123456
#hibernate settings
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.cache.use_query_cache=false
hibernate.jdbc.fetch_size=10
hibernate.jdbc.batch_size=5
hibernate.ehcache_config_file=ehcache.xml


ehcache.xml

<ehcache>
<!-- Sets the path to the directory where cache .data files are created.

If the path is a Java System Property it is replaced by
its value in the running VM.

The following properties are translated:
user.home - User's home directory
user.dir - User's current working directory
java.io.tmpdir - Default temp file path -->
<diskStore path="java.io.tmpdir" />
<!--Default Cache configuration. These will applied to caches programmatically created through
the CacheManager.

The following attributes are required:

maxElementsInMemory            - Sets the maximum number of objects that will be created in memory
eternal                        - Sets whether elements are eternal. If eternal,  timeouts are ignored and the
element is never expired.
overflowToDisk                 - Sets whether elements can overflow to disk when the in-memory cache
has reached the maxInMemory limit.

The following attributes are optional:
timeToIdleSeconds              - Sets the time to idle for an element before it expires.
i.e. The maximum amount of time between accesses before an element expires
Is only used if the element is not eternal.
Optional attribute. A value of 0 means that an Element can idle for infinity.
The default value is 0.
timeToLiveSeconds              - Sets the time to live for an element before it expires.
i.e. The maximum time between creation time and when an element expires.
Is only used if the element is not eternal.
Optional attribute. A value of 0 means that and Element can live for infinity.
The default value is 0.
diskPersistent                 - Whether the disk store persists between restarts of the Virtual Machine.
The default value is false.
diskExpiryThreadIntervalSeconds- The number of seconds between runs of the disk expiry thread. The default value
is 120 seconds.
-->
<cache name="org.hibernate.cache.StandardQueryCache"
maxElementsInMemory="50"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="7200"
overflowToDisk="true" />
<cache name="org.hibernate.cache.UpdateTimestampsCache"
maxElementsInMemory="5000"
eternal="true"
overflowToDisk="true" />
<!--
默认的Cache配置。用来实现CacheManager.add(String cacheName)创建的缓存
memoryStoreEvictionPolicy:内存存储与释放策略。有三个值:
LRU -least recently used
LFU -least frequently used
FIFO-first in first out, the oldest element by creation time
diskPersistent :是否持久化磁盘缓存。
当这个属性的值为true时,系统在初始化的时候会在磁盘中查找文件名为cache名称
后缀名为index的的文件,如CACHE_FUNC.index
-->
<defaultCache maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LFU"
/>
<!-- See http://ehcache.sourceforge.net/documentation/#mozTocId258426 for how to configure caching for your objects -->
</ehcache>


log4j.properties

log4j.rootLogger=INFO, stdout, logfile
log4j.logger.org.springframework=WARN
log4j.logger.org.hibernate=WARN
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%d] %-5p /: %m%n
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
log4j.appender.logfile.File=${webAppRootKey}/superDao.log
log4j.appender.logfile.MaxFileSize=512KB
# Keep three backup files.
log4j.appender.logfile.MaxBackupIndex=3
# Pattern to output: date priority [category] - message
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=[%d] %p [%c] - %m%n


tinyLight-dao.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <description>tinyLight Dao配置</description>
<!-- 定义JdbcTemplate Bean(线程安全,执行底层sql语句) -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 设置数据源 -->
<property name="dataSource" ref="dataSource" />
<!-- 设置jdbcTemplate创建的statement查询数据时最大的超时时间,默认0 -->
<property name="queryTimeout" value="0" />
<!-- 设置底层ResultSet每次从数据库返回的行数,默认0,Oracle默认100 -->
<property name="fetchSize" value="0" />
<!-- 设置底层ResultSet从数据库返回的最大行数,默认0 -->
<property name="maxRows" value="0" />
<!-- 是否忽略sql警告信息,默认true,false JdbcTemplate将会抛出SQLWarningException -->
<property name="ignoreWarnings" value="true" />
<property name="nativeJdbcExtractor" ref="nativeJdbcExtractor" />
</bean>
<!-- 定义DBCP数据源的JDBC本地对象抽取器 -->
<bean id="nativeJdbcExtractor" lazy-init="true"
class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor" />
<!-- 定义封装了jdbc操作数据的dao -->
<bean id="simpleJdbcDao" class="com.tinylight.dao.jdbc.SimpleJdbcDao">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
<!-- 定义了与实体相关的dao -->
<bean id="genericEntityDao" class="com.tinylight.dao.hibernate.GenericEntityDao"
scope="prototype" lazy-init="true">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!-- 定义了与实体无关的dao -->
<bean id="genericDao" class="com.tinylight.dao.hibernate.GenericDao">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!--使用泛型DAO作为抽象基类-->
<bean id="baseDao" class="com.tinylight.dao.base.BaseDao"
abstract="true" depends-on="genericEntityDao,genericDao">
<property name="gedao">
<ref bean="genericEntityDao" />
</property>
<property name="gdao">
<ref bean="genericDao" />
</property>
<property name="sjdao">
<ref bean="simpleJdbcDao"/>
</property>
</bean>
<!--
当然这里也可以不必为每一个实体类的配置像下面这样的代码,
那就要在spring注解注入dao到service类的时候,加上下面这个方法:
/**
* spring bean的后处理器,如果子类是spring初始化的bean,则在初始化后设置注解dao的实体类类型
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
@PostConstruct
@SuppressWarnings("unchecked")
protected void preparedDao() throws IllegalArgumentException, IllegalAccessException{
Class<? extends BaseService> cl = this.getClass();
for(Field f : cl.getDeclaredFields()){
log.info("Service类注解属性名称  = {},类型 = {}",f.getName(),f.getGenericType());
if(f.isAnnotationPresent(Resource.class) && f.getAnnotation(Resource.class).name().equals("baseDao")){
f.setAccessible(true);//修改private修饰权限
Type[] params = ((ParameterizedType)f.getGenericType()).getActualTypeArguments();
log.info("实体类的参数类型  = {}",params[0].toString());
((IBaseDao<?,?>)f.get(this)).changeEntityClass((Class)params[0]);//设置实体类类型
f.setAccessible(false);//恢复private修饰权限
}
}
}
这样就可以为每一个实体类加下面这段xml配置了,当然dao是不在学要写一条代码啦
-->

<!-- 配置实体Demodata的DAO -->
<bean id="demoDao" parent="baseDao">
<constructor-arg>
<value>com.hibernate.entityclass.Daotest</value>
</constructor-arg>
</bean>

</beans>


这个svn有源代码,有兴趣可以看看.

http://xeducation.googlecode.com/svn/trunk

是myeclipse的工程
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: