基于spring jdbc的通用存取层

本文介绍了如何基于Spring JDBC封装一层通用的数据库存取层,简化单表操作并支持数据库分页。通过注解实体描述数据库结构,避免手动编写SQL和填充结果集。示例展示了从通用DAO接口、实现、实体定义到具体服务调用的完整流程,并提供了分页查询的实现方式。

博主在spring jdbc的基础上封装了层数据库存取层,好处在于大部分的数据存取已经可以使用,单表编码几乎不用编码,并且支持数据库分页。

使用注解在实体描述数据库的情况,进而从程序员角度只看到对象而不需要写sql语句,也无需从结果集填充属性值到实体。

先介绍api:

限定符和类型 方法和说明
Long count(String sql, Object... values)
计算结果个数的辅助方法
void create(T t)
创建对象
void delete(String sql, Object... values)
批量删除对象
void delete(T t)
删除对象
T load(T t)
读取对象
PageDto<T> page(PageDto<T> pageDto, String sql, Object... values)
根据分页对象 PageDto中的ranges的数值来读取数据库数据
List<T> query(String sql, Object... values)
查询对象列表
List<T> queryAll()
获取所有对象
T queryById(Object key)
适用于单主键的对象获取
void setInjectDataSource(DataSource dataSource)
子类调用本方法注入数据源
Subclass call this method to inject  DataSource.
void update(String sql, Object... values)
批量更新对象
void update(T t)
更新单个对象
以下介绍使用范例:

1 通用dao接口

import ifunsu.at.gmail.base.dao.BaseDao;
public interface InjectDataSourceDao<T> extends BaseDao<T>{
}

2 通用dao实现

import ifunsu.at.gmail.base.dao.BaseDaoImpl;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;

public class InjectDataSourceDaoImpl<T> extends BaseDaoImpl<T>{
@Autowired
private DataSource dataSource;

@PostConstruct
public void buildDataSource() {
this.setInjectDataSource(dataSource);
}
}

=================================================

以上是为了引入dao所写的代码,每个项目都有这样两个文件。

=================================================

3 实体

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

@AllArgsConstructor
@NoArgsConstructor
@ToString
@EqualsAndHashCode
@Entity
@Table(name="users")
public class PortalUser implements Serializable {

private static final long serialVersionUID = 192903603246880174L;
@Id
@Column(name = "username", length = 128, nullable = false)
private @Setter @Getter String username;
@Column(name = "password", length = 128, nullable = true)
private @Setter @Getter String password;
@Column(name = "enabled")
private @Setter @Getter boolean enabled;
}

上面的实体代码重点在于有@Table注解和@Id、@Column。

有table注解则知道表的名称,有column则知道表的字段名,有id则知道主键(支持多主键)。

4 实体dao接口

public interface PortalUserDao extends InjectDataSourceDao<PortalUser> {
}

可以看到无需写方法。

5 实体dao实现

import org.springframework.stereotype.Repository;
import com.highjet.portal.dao.entity.PortalUser;
import com.highjet.portal.dao.jdbc.PortalUserDao;
@Repository
public class PortalUserDaoImpl extends InjectDataSourceDaoImpl<PortalUser>
implements PortalUserDao {
}

可以看到实现也无需写方法。

6 service调用

public class PortalServiceImpl implements PortalService {
@Autowired
private @Setter PortalUserDao portalUserDao;

@Override
public PortalUser productPortalToken(String username, String token){
PortalUser portalUser = new PortalUser(username, token, true);
this.portalUserDao.update(portalUser);
return portalUser;
}

}

虽然PortalUserDao没写update方法,但是其父接口有,所以可以直接调用。

============================================================

以上即是使用方法,以下是分页代码。

============================================================

public class PageDto<T>
extends Object
implements Serializable

分页对象(page object)

缓存pageSize * pageSize个数的结果集

典型用法:(Typical usage:)

PageDto page = new PageDto();
page.changePageSize(size);
page = this.service.search(page);
request.setAttribute("page", page, WebRequest.SCOPE_SESSION);

以上是读取一次放在session中。下面在分页时获取。(Above read and put into session. Below used when pageing.)


PageDto page = (PageDto) request.getAttribute("page", WebRequest.SCOPE_SESSION); 
List list = page.getList(pageNumber);
if(list == null){
  page = this.service.search(page);//读取的范围超过缓存需要向数据库重新读取。(Access database when read beyond ranges.) 
}
request.setAttribute("page", page, WebRequest.SCOPE_SESSION);// 再放进session中保存。(Result into session again.)

后台数据库读取代码,通常与BaseDaoImpl配合使用。(Codes at Dao. Use with BaseDaoImpl.)
PageDto page(PageDto pageDto, final String sql, final Object... objects); 


限定符和类型 方法和说明
void alignList()
对齐结果集
void changePageSize(int pageSize)
改变页尺寸同时会影响缓存的长度
Change page size will affect cache size.
List<T> getList()
默认读取当前页
Load data from current page.
List<T> getList(int currentPage)
读取指定页并改变当前页
Change current page and load data.
int[] nextRanges()
获取下一个数据库读取区间
Get next ResultSet ranges.
void setResultSetList(int totalRecord, List<T> list, int[] ranges)
设置结果集
Set result after read data from database.
================================================================================

如果为自定义查询,则需要做些改变。

================================================================================

实体:

@Table(name="fakeTable")
public class Complex implements Serializable {

@Id

@Column(name = "fakeColumn", nullable = false)

private @Setter @Getter String id;

}

重点在于fakeTable和fakeColumn,系统检测到这两个关键字时则知道这是组合表的查询。

dao实现:

@Repository
public class ComplexDaoImpl extends InjectGreenPlumDataSourceDaoImpl<Complex>
implements ComplexDao {

     @Override
public
PageDto queryForList(PageDtopageDto) {

                pageDto = this.page(pageDto, "select 语句", 可变条件参数);

condition.setPageDto(pageDto);
return condition;

}

}

重点在于select语句中的结果列名需要和实体名字一致,结果列数可以比实体个数多。

==============================================================================

以上为所有用法,附件是jar包,不开源但可以免费使用。

jar包下载 

api下载 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值