spring mvc 系列2 泛型DAO(基于存储过程)

spring mvc 系列1 中:
感谢 ricoyu 提示
[quote]
1 楼 ricoyu 2010-10-02 引用
DAO层不要用◎Service,用◎Repository(没拼错的话)
[/quote]
基于事务管理,由于小弟一时大意忘了加上去,感谢 icanfly 提醒。
此版本已经修正以上BUG。

泛型需要JDK1.5以上,因此此版本需要运行在JDK1.5以上。
先看代码:

@Repository
public class BaseDao {
// 存储过程前缀
protected static String PROCEDURE_NAME_PREFIX = "st_";

/**
* 存储过程对应的表名,为空时,从操作对象类名中获取
* 存储过程命名方式:前缀_表名_后缀
* 操作对象如:ProductModel, ProductSellTableModel
* 对应获取表名为:productTable, ProductSellTable
*/
protected static String TABLE_NAME = null;

// 存储过程后缀
protected static String PROCEDURE_NAME_ADD_SUFFIX = "Add";
protected static String PROCEDURE_NAME_UPDATE_SUFFIX = "Update";
protected static String PROCEDURE_NAME_DELETE_SUFFIX = "Delete";
protected static String PROCEDURE_NAME_QUERY_BY_PRIMARY_KEY_SUFFIX = "QueryByPrimaryKey";

public BaseDao(){}

@Autowired
private SimpleJdbcTemplate simpleJdbcTemplate ;

//@Autowired是Spring提供的一种注入Bean的方法
@Autowired
private JdbcTemplate jdbcTemplate ;

public SimpleJdbcTemplate getSimpleJdbcTemplate() {
return simpleJdbcTemplate;
}

public void setSimpleJdbcTemplate(SimpleJdbcTemplate simpleJdbcTemplate) {
this.simpleJdbcTemplate = simpleJdbcTemplate;
}

public SimpleJdbcCall createSimpleJdbcCall() {
return new SimpleJdbcCall(this.jdbcTemplate);
}

public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}

public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}

/**
*
* @功能模块: executeProcedure
* @方法说明: 执行存储过程 将对象t转换成存储过程参数,并执行存储过程,执行存储过程后返回此对象操作后的信息
* @version: 1.0
* @param <T> 泛类型
* @param t 要操作的对象信息
* @param returnClass 返回的类型,如果为null 返回类型与查询类型一致
* @param procedureName 存储过程名称
* @return Map<"ReturningResultSet", Object>
* @throws
*/
@SuppressWarnings("unchecked")
protected <T> Map executeProcedure(Class returnClass, T t, String procedureName){
SimpleJdbcCall sjc = this.createSimpleJdbcCall();
sjc.getJdbcTemplate().setResultsMapCaseInsensitive(true);
sjc.withProcedureName(procedureName).returningResultSet("ReturningResultSet", BeanPropertyRowMapper.newInstance(returnClass==null?t.getClass():returnClass));

SqlParameterSource param = new BeanPropertySqlParameterSource(t);
return sjc.execute(param);
}

/**
*
* @功能模块: querySelf
* @方法说明: 执行存储过程 将对象t转换成存储过程参数,并执行存储过程,执行存储过程后返回此对象操作后的信息
* @version: 1.0
* @param <T> 泛类型
* @param t 要操作的对象信息
* @param procedureName 存储过程名称
* @return T 执行存储过程后返回的对象,与传入对象类型一致
* @throws
*/
@SuppressWarnings("unchecked")
protected <T> T querySelf(T t, String procedureName){
Map returnResultSet = executeProcedure(null, t, procedureName);
List list = (List)returnResultSet.get("ReturningResultSet");
if(list.size()>0){
return (T)list.get(0);
}else{
return null;
}
}



/**
*
* @功能模块: add
* @方法说明: 添加一个对象 将对象t转换成存储过程参数,并执行存储过程,执行存储过程后返回此对象操作后的信息
* @version: 1.0
* @param <T> 泛类型
* @param t 要添加的对象信息
* @param procedureName 存储过程名称
* @return T 泛类型(返回添加后的对象)
* @throws
*/
protected <T> T add(T t, String procedureName){
return this.querySelf(t, procedureName);
}

/**
*
* @功能模块: add
* @方法说明: 添加一个对象 将对象t转换成存储过程参数,并执行存储过程,执行存储过程后返回此对象操作后的信息
* @version: 1.0
* @param <T> 泛类型
* @param t 要添加的对象信息
* @return T 泛类型(返回添加后的对象)
* @throws
*/
public <T> T add(T t){
return add(t, getProcedureName(t.getClass(), PROCEDURE_NAME_ADD_SUFFIX));
}

/**
*
* @功能模块: update
* @方法说明: 按主键修改一个对象 将对象t转换成存储过程参数,并执行存储过程,执行存储过程后返回此对象操作后的信息
* @version: 1.0
* @param <T> 泛类型
* @param t 要修改的对象信息
* @param procedureName 存储过程名称
* @return T 泛类型(返回修改后的对象信息)
* @throws
*/
protected <T> T update(T t, String procedureName){
return this.querySelf(t, procedureName);
}

/**
*
* @功能模块: update
* @方法说明: 按主键修改一个对象 将对象t转换成存储过程参数,并执行存储过程,执行存储过程后返回此对象操作后的信息
* @version: 1.0
* @param <T> 泛类型
* @param t 要修改的对象信息
* @return T 泛类型(返回修改后的对象信息)
* @throws
*/
public <T> T update(T t){
return update(t, getProcedureName(t.getClass(), PROCEDURE_NAME_UPDATE_SUFFIX));
}

/**
*
* @功能模块: delete
* @方法说明: 按主键删除一个对象 将对象t转换成存储过程参数,并执行存储过程,执行存储过程后返回执行结果信息
* @version: 1.0
* @param <T> 泛型
* @param t 要删除的对象
* @param procedureName 存储过程名称
* @return Result 执行结果信息类
* @throws
*/
protected <T> Result delete(T t, String procedureName){
Map returnResultSet = executeProcedure(Result.class, t, procedureName);
List list = (List)returnResultSet.get("ReturningResultSet");
if(list!=null && list.size()>0){
return (Result)list.get(0);
}else{
return null;
}
}

/**
*
* @功能模块: delete
* @方法说明: 按主键删除一个对象 将对象t转换成存储过程参数,并执行存储过程,执行存储过程后返回执行结果信息
* @version: 1.0
* @param <T> 泛型
* @param t 要删除的对象
* @return Result 执行结果信息类
* @throws
*/
public <T> Result delete(T t){
return delete(t, getProcedureName(t.getClass(), PROCEDURE_NAME_DELETE_SUFFIX));
}

/**
*
* @功能模块: delete
* @方法说明: 按主键字符串删除多个对象 将对象t转换成存储过程参数,并执行存储过程,执行存储过程后返回执行结果信息
* @version: 1.0
* @param ids 要删除的对象ID,多个ID以逗号分割,如:1,2,3
* @return Result 执行结果信息类
* @throws
*/
protected Result delete(String ids, String procedureName){
SimpleJdbcCall sjc = this.createSimpleJdbcCall();
sjc.getJdbcTemplate().setResultsMapCaseInsensitive(true);
sjc.withProcedureName(procedureName).returningResultSet("ReturningResultSet", BeanPropertyRowMapper.newInstance(Result.class));

List list = (List)sjc.execute(ids).get("ReturningResultSet");
if(list!=null && list.size()>0){
return (Result)list.get(0);
}else{
return null;
}
}

/**
*
* @功能模块: query
* @方法说明: 按条件,排序,分页信息查询内容
* @version: 1.0
* @param <T> 泛型,查询的对象类型
* @param t 对象实例
* @param condition 条件
* @param order 排序
* @param pagination 分页信息
* @param procedureName 存储过程名称
* @return Map<"Pagination", PaginationModel>
* Map<"List", List<T>>
* @throws
*/
@SuppressWarnings("unchecked")
protected Map query(Class clazz, Map<String, Object> condition, String order, PaginationModel pagination, String procedureName){
SimpleJdbcCall sjc = this.createSimpleJdbcCall();
sjc.getJdbcTemplate().setResultsMapCaseInsensitive(true);
sjc.withProcedureName(procedureName).
returningResultSet("Pagination", BeanPropertyRowMapper.newInstance(PaginationModel.class)).
returningResultSet("List", BeanPropertyRowMapper.newInstance(clazz));

Map<String, Object> param = new HashMap<String, Object>();
param.putAll(condition==null?new HashMap():condition);
param.put("orderby", order==null?"":order);
param.put("pageSize", pagination.getPageSize());
param.put("currPage", pagination.getCurrPage());
Map returnResultSet = sjc.execute(param);

Map<String, Object> newResult = new HashMap<String, Object>();
newResult.put("List", returnResultSet.get("List"));

List list = (List)returnResultSet.get("Pagination");
if(list.size()>0){
newResult.put("Pagination", list.get(0));
}

return newResult;
}

/**
*
* @功能模块: query
* @方法说明: 按条件查询对象列表
* @version: 1.0
* @param <T> 泛型
* @param t 要查询的对象
* @param condition 条件
* @param procedureName 存储过程名称
* @return List 对象列表
* @throws
*/
@SuppressWarnings("unchecked")
protected List query(Class clazz, Map<String, Object> condition, String procedureName){
SimpleJdbcCall sjc = this.createSimpleJdbcCall();
sjc.getJdbcTemplate().setResultsMapCaseInsensitive(true);
sjc.withProcedureName(procedureName).
returningResultSet("List", BeanPropertyRowMapper.newInstance(clazz));
Map resultSet = sjc.execute(condition);
return (List)resultSet.get("List");
}


/**
*
* @功能模块: query
* @方法说明: 按对象主键进行查询 将对象t转换成存储过程参数,并执行存储过程进行查询,返回查询后的对象信息
* @version: 1.0
* @param <T> 泛类型
* @param t 要查询的对象信息
* @param procedureName 存储过程名称
* @return T 执行查询存储过程后返回的对象,与传入对象类型一致
* @throws
*/
protected <T> T query(T t, String procedureName){
return this.querySelf(t, procedureName);
}

/**
*
* @功能模块: query
* @方法说明: 按对象主键进行查询 将对象t转换成存储过程参数,并执行存储过程进行查询,返回查询后的对象信息
* @version: 1.0
* @param <T> 泛类型
* @param t 要查询的对象信息
* @return T 执行查询存储过程后返回的对象,与传入对象类型一致
* @throws
*/
public <T> T query(T t){
return query(t, getProcedureName(t.getClass(), PROCEDURE_NAME_QUERY_BY_PRIMARY_KEY_SUFFIX));
}

/**
*
* @功能模块: getProcedureName
* @方法说明: 根据查询的对象类,获取此操作此对象存储过程的名称
* @version: 1.0
* @param clazz 查询的对象类
* @param suffix 存储过程后缀
* @return String 存储过程名称
* @throws
*/
private String getProcedureName(Class clazz, String suffix){
String tableName = TABLE_NAME==null?getTableName(clazz.getSimpleName()):TABLE_NAME;
return PROCEDURE_NAME_PREFIX + tableName + (suffix==null?"":("".equals(suffix)?"":"_"+suffix));
}

/**
*
* @功能模块: getTableName
* @方法说明: 根据查询的对象类名,获取此对象类对应的表
* @version: 1.0
* @param className
* @return String
* @throws
*/
private String getTableName(String className){
if(className.endsWith("Model")){
String name = className.substring(0, className.length()-"Model".length());
return name.endsWith("Table")?name:name+"Table";
}else{
return className.endsWith("Table")?className:className+"Table";
}
}
}


此BaseDao封装了 添加、删除、修改、查询等基本方法。
其它子DAO继承此BaseDao即可,如有不同覆盖基类方法即可:

@Transactional
@Repository
public class TestDao extends BaseDao {

/**
*
* @功能模块: selectTestAll
* @方法说明: 按分页信息查询内容
* @version: 1.0
* @param <T> 泛型,查询的对象类型
* @param t 对象实例
* @param pagination 分页信息
* @param procedureName 存储过程名称
* @return Map<"Pagination", PaginationModel>
* Map<"List", List<T>>
* @throws
*/
public Map selectTestAll(PaginationModel paginationModel) {
return super.query(TestModel.class, null, null, paginationModel, "st_TestTable_QueryAll");
}

/**
*
* @功能模块: delete
* @方法说明: 按主键字符串删除多个对象 将ids转换成存储过程参数,并执行存储过程,执行存储过程后返回执行结果信息
* @version: 1.0
* @param ids 要删除的对象ID,多个ID以逗号分割,如:1,2,3
* @return Result 执行结果信息类
* @throws
*/
public Result delete(String ids){
return super.delete(ids, "st_TestTable_Delete");
}

}


[color=red]注:纯存储过程操作,不用加注解:@Transactional
@Transactional 为声名此对象需要事务管理。
[/color]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为什么我们要使用通用DAO接口呢,因为我们的数据库操作无非是增删改查,CRUD操作,我们不需要为每个实体去编写一个dao接口,对于相似的实体操作可以只编写一个通用接口,然后采用不同的实现! DAO已经成为持久层的标准模式,DAO使结构清晰,面向接口编程为代码提供了规范。而泛型DAO是一个类型安全的,代码精简的设计模式(相对于传统DAO),尤其在DAO组件数量庞大的时候,代码量的减少更加明显。 泛型DAO的核心是定义一个GenericDao接口,声明基本的CRUD操作: 用hibernate作为持久化解决方案的GenericHibernateDao实现类,被定义为抽象类,它提取了CRUD操作,这就是简化代码的关键,以便于更好的重用,这个就不给例子了,增删改都好写,查就需要各种条件了。 然后是各个领域对象的dao接口,这些dao接口都继承GenericDao接口,这样各个领域对象的dao接口就和传统dao接口具有一样的功能了。 下一步是实现类了,个自领域对象去实现各自的接口,还要集成上面的抽象类,这样就实现了代码复用的最大化,实现类中只需要写出额外的查询操作就可以了。当然还要获得域对象的Class实例,这就要在构造方法中传入Class实例。用spring提供的HibernateTemplate注入到GenericHibernateDao中,这样在各个实现类就可以直接调用HibernateTemplate来实现额外的查询操作了。 如果在实现类中不想调用某个方法(例如:update()),就可以覆盖它,方法中抛出UnsupportedOperationException()异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值