如何利用泛型封装通用的service层
身为一名开发人员,大家都知道,我们经常会在项目中大量的编写许多重复的代码,比如说
public Entity find(String id);
像这种代码,简单,但是写多了,可能也会容易出错,那么我们能不能直接编写一套完整的,通用的方法呢,这样既不用重复编写,还不用出错,说道通用的方法,泛型是个不错的选择.
基础架构:spring-boot+spring mvc+spring jpa.
jpa是个好东西,个人感觉它最大的好处是不需要自己手动建表.还能在修改了表字段以后,自动给你添加上上去,它不像mybatis,业务改了之后,还需要调整sql语句,
好了,废话不多说,上代码:
一、首先建立一个实体类WebVisitRecordEntity
继承BaseEntity.BaseEntity在项目里面,是所有实体类的最顶层.里面是封装了一些通用的属性.
1.BaseEntity
package cn.yxw.function;
import cn.yxw.function.Enum.status.StatusEnum;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import java.io.Serializable;
import java.util.Date;
@MappedSuperclass
public abstract class BaseEntity implements Serializable{
@Id
@Column(length = 32 )
private String id;
private Date createTime;
@Column(length = 32 )
private String createUser;
private Date updateTime;
@Column(length = 32 )
private String updateUser;
@Column(length = 8 )
private String delStatus = StatusEnum.FALSE.getStatus();
@Column(length = 8 )
private String enAbleStatus = StatusEnum.TRUE.getStatus();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public String getCreateUser() {
return createUser;
}
public void setCreateUser(String createUser) {
this.createUser = createUser;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public String getUpdateUser() {
return updateUser;
}
public void setUpdateUser(String updateUser) {
this.updateUser = updateUser;
}
public String getDelStatus() {
return delStatus;
}
public void setDelStatus(String delStatus) {
this.delStatus = delStatus;
}
public String getEnAbleStatus() {
return enAbleStatus;
}
public void setEnAbleStatus(String enAbleStatus) {
this.enAbleStatus = enAbleStatus;
}
}
2.WebVisitRecordEntity
package cn.yxw.function.domain.plugins;
import cn.yxw.function.BaseEntity;
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
@Entity()
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Table(name = "web_visit_Record")
public class WebVisitRecordEntity extends BaseEntity {
private static final long serialVersionUID = 341666498307329777L;
private int count = 0;
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
二、有了实体类之后
首先建立一个顶层的api接口。所有通用的api方法,可以放在这里(ResultBean是一个封装了一个结果的数据类,里面包含了定义执行是否成功,执行返回的数据,执行错误提示的消息)
package cn.yxw.function;
import cn.yxw.function.result.ResultBean;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
public interface BaseApi<T extends BaseEntity> {
T get(String id);
T find(String id);
ResultBean<T> delete(String id);
ResultBean<T> delete(T entity);
ResultBean<T> create(T entity);
ResultBean<T> update(T entity);
Page<T> page(Pageable pageable);
boolean exists(String id);
}
三、实现BaseApi
既然是要定义通用的api,那么不仅仅只是一套接口,我们需要在定义一个可以实现BaseApi的BaseServiceImpl,之后的所有实现类,都可以继承这个BaseServiceImpl.java的泛型,给了我们的项目很好的扩展性,而顶层BaseEntity也给了我很好的实现方案,将BaseEntity作为泛型的入口
1.基本时限BaseApi
package cn.yxw.function.service.impl.domain.userCenter;
import cn.yxw.function.BaseApi;
import cn.yxw.function.BaseEntity;
import cn.yxw.function.result.ResultBean;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
public class BaseServiceImpl<T extends BaseEntity> implements BaseApi<T> {
@Override
public T get(String id) {
return null;
}
@Override
public T find(String id) {
return null;
}
@Override
public ResultBean<T> delete(String id) {
return null;
}
@Override
public ResultBean<T> delete(T entity) {
return null;
}
@Override
public ResultBean<T> create(T entity) {
return null;
}
@Override
public ResultBean<T> update(T entity) {
return null;
}
@Override
public Page<T> page(Pageable pageable) {
return null;
}
@Override
public boolean exists(String id) {
return false;
}
}
2.使用jpa作为BaseServiceImpl的属性.
package cn.yxw.function.service.impl.domain.userCenter;
import cn.yxw.function.BaseApi;
import cn.yxw.function.BaseEntity;
import cn.yxw.function.Enum.code.ServiceCodeEnum;
import cn.yxw.function.result.ResultBean;
import cn.yxw.function.util.ObjectUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
public class BaseServiceImpl<T extends BaseEntity> implements BaseApi<T> {
@Autowired
private JpaRepository<T, String> baseRepository;
@Override
public T get(String id) {
T entity = this.baseRepository.getOne(id);
return entity;
}
@Override
public T find(String id) {
return this.baseRepository.findById(id).get();
}
@Override
public ResultBean<T> delete(String id) {
this.baseRepository.deleteById(id);
return ResultBean.success("");
}
@Override
public ResultBean<T> delete(T entity) {
this.baseRepository.delete(entity);
return ResultBean.success(entity);
}
@Override
public ResultBean<T> create(T entity) {
if(ObjectUtil.isNull(entity)){
return ResultBean.failfure("数据为空,无法创建!");
}
if(this.exists(entity.getId())){
return ResultBean.failfure("实体id相同,无法重复创建!");
}
entity = this.baseRepository.saveAndFlush(entity);
if(ObjectUtil.isNull(entity)){
return ResultBean.failfure(ServiceCodeEnum.CORE_SYSTEM_FAILURE);
}
return ResultBean.success(entity);
}
@Override
public ResultBean<T> update(T entity) {
if(ObjectUtil.isNull(entity)){
return ResultBean.failfure("数据为空,无法创建!");
}
if(!this.exists(entity.getId())){
return ResultBean.failfure("数据库不存在该数据,无法执行更新");
}
entity = this.baseRepository.saveAndFlush(entity);
if(ObjectUtil.isNull(entity)){
return ResultBean.failfure(ServiceCodeEnum.CORE_SYSTEM_FAILURE);
}
return ResultBean.success(entity);
}
@Override
public Page<T> page(Pageable pageable) {
return null;
}
@Override
public boolean exists(String id) {
return this.baseRepository.existsById(id);
}
}
四、定义类自己的api
继承BaseApi,定义实现类,继承BaseServiceImpl.并实现自己的api
package cn.yxw.function.domain.userCenter;
import cn.yxw.function.BaseApi;
import cn.yxw.function.domain.plugins.WebVisitRecordEntity;
public interface WebVisitRecordApi extends BaseApi<WebVisitRecordEntity> {
}
package cn.yxw.function.service.impl.domain.userCenter;
import cn.yxw.function.domain.plugins.WebVisitRecordEntity;
import cn.yxw.function.domain.userCenter.WebVisitRecordApi;
import org.springframework.stereotype.Service;
@Service
public class WebVisitRecordServiceImpl extends BaseServiceImpl<WebVisitRecordEntity> implements WebVisitRecordApi {
}
五、测试
到这里,代码已经结束. 测试一下,构建下controller层. 并进行测试
package cn.yxw.function.controller.System.admin;
import cn.yxw.function.controller.BaseController;
import cn.yxw.function.domain.plugins.WebVisitRecordEntity;
import cn.yxw.function.result.ResultBean;
import cn.yxw.function.service.impl.domain.userCenter.WebVisitRecordServiceImpl;
import cn.yxw.function.util.ObjectUtil;
import com.alibaba.druid.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.Map;
@RestController()
@RequestMapping(value = "web/record")
public class WebVisitRecordsController extends BaseController {
@Autowired
private WebVisitRecordServiceImpl webVisitRecordService;
@GetMapping(value = "/get")
public Map get(String id){
if(StringUtils.isEmpty(id)){
return this.errorWithMsg("参数不得为空");
}
WebVisitRecordEntity entity = this.webVisitRecordService.find(id);
return this.result(entity,"");
}
@PostMapping(value = "/create")
public Map create(int num){
WebVisitRecordEntity entity = new WebVisitRecordEntity();
entity.setId(System.currentTimeMillis()+"");
entity.setCreateTime(new Date());
entity.setCount(num);
ResultBean<WebVisitRecordEntity> result = this.webVisitRecordService.create(entity);
return this.result(result.getDate(),result.getMsg());
}
@PostMapping(value = "/update")
public Map update(String id, int num){
if(StringUtils.isEmpty(id)){
return this.errorWithMsg("参数不得为空");
}
WebVisitRecordEntity entity = this.webVisitRecordService.find(id);
if(ObjectUtil.isNull(entity)){
return this.errorWithMsg("不存在该数据");
}
entity.setUpdateTime(new Date());
entity.setCount(entity.getCount()+num);
ResultBean<WebVisitRecordEntity> result = this.webVisitRecordService.update(entity);
return this.result(result.getDate(),result.getMsg());
}
}
三次测试都已经成功,但是我们真实的项目不可能这么简单.所以我们再次测试下扩展性
等等,不知道你们发现没有,上面的代码有一段是错误的.
我在controller层的属性不是api,而是实现类.......
虽然不影响,但是就无法扩展了...此处做修正
六、扩展性
1. WebVisitRecordApi
package cn.yxw.function.domain.userCenter;
import cn.yxw.function.BaseApi;
import cn.yxw.function.domain.plugins.WebVisitRecordEntity;
public interface WebVisitRecordApi extends BaseApi<WebVisitRecordEntity> {
int countAll();
}
2. WebVisitRecordServiceImpl
package cn.yxw.function.service.impl.domain.userCenter;
import cn.yxw.function.domain.plugins.WebVisitRecordEntity;
import cn.yxw.function.domain.userCenter.WebVisitRecordApi;
import cn.yxw.function.util.ObjectUtil;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class WebVisitRecordServiceImpl extends BaseServiceImpl<WebVisitRecordEntity> implements WebVisitRecordApi {
@Override
public int countAll() {
List<WebVisitRecordEntity> list = super.baseRepository.findAll();
int count = 0;
if(ObjectUtil.isNull(list) || list.size() <= 0){
return count;
}
for (WebVisitRecordEntity entity : list){
count += entity.getCount();
}
return count;
}
}
3. WebVisitRecordController
@GetMapping(value = "count")
public Map count(){
return this.result(this.webVisitRecordService.countAll(),"执行成功");
}
4.测试
七、总结
emmmm.....其实我上面还有个小错误,就留给你们寻找吧
其实,封装的这个service层,也有很大的局限性,比如说,如果我需要自定义dao层的方法,怎么办?需要执行sql语句怎么办,仔细想想,我们能不能再封装一个BaseRepository呢?然后作为BaseServiceImpl中的属性传入??????
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。
相关文章