项目架构: 项目采取前后分离开发模式,前端:antd pro 2.0,后端:spring cloud + spring boot + JPA。数据交换:json
最近在项目组开发中使用到JPA,初次使用JPA感觉很强大,解放了repository层的实现,提高了开发效率。
在git上评审项目组成员代码时,发现各应用模块在Service层都对其下业务创建了CRUD操作,查看完项目代码,感觉80%都类似,只是调用的业务类型和参数不同而已。因此跳出一个将Service层CRUD操作进行封装的想法。思考过后,开始搬砖...
1. 创建service层公共接口BaseService
package com.****.common;
import java.util.List;
import java.util.Map;
/**
* 封装公共基础操作接口,定义基本CRUD操作,避免代码冗余
* @param <V> VO类
* @param <E> Entity实体类
* @author Abin
* @Date 2018/11/07
*/
public interface BaseService<V, E> {
/**
* 根据ID,检测Entity是否存在
* @param id Entity实体类主键
* @return boolean 是否存在
*/
boolean checkExists(Long id);
/**
* 根据名称,检测Entity是否存在
* @param name Entity实体类名称属性
* @return boolean 是否存在
*/
boolean checkExists(String name);
/**
* 根据ID,获取单一Entity实体类,并转为VO对象返回
* @param id Entity实体类ID
* @return V 返回Entity实体类对应的VO对象
*/
V findOne(Long id);
/**
* 获取所有Entity实体,并转为VO集合返回
* @return List<VO>
*/
List<V> findAll();
/**
* 根据map<属性名,属性值>多条件模糊查询获取所有Entity实体,并转为VO集合返回
* @param map 条件集合
* @return List<VO> VO对象集合
*/
List<V> findByLike(Map<String, String> map);
/**
* 根据map<属性名,属性值>多条件查询、排序、分页获取所有Entity实体,并转为VO集合返回
* @param condMap 条件集合
* @param sortProperties 排序属性集合
* @param currentPage 当前页面
* @param pageSize 每页显示条数
* @return Map<String, Object> VO对象集合
*/
Map<String, Object> getPageByConditional(Map<String, Object> condMap, List<String> sortProperties, Integer currentPage, Integer pageSize);
/**
* 添加Entity实体
* @param v VO对象
* @return boolean 是否添加成功
*/
boolean save(V v);
/**
* 修改Entity实体
* @param v VO对象
* @return boolean 是否修改成功
*/
boolean update(V v);
/**
* 根据ID,Map<属性名,值>,更新Entity实体
* @param id Entity实体ID
* @param map 需要更新的字段名、值集合
* @return boolean 是否更新成功
*/
boolean updateValuesByMap(Long id, Map<String, Object> map);
/**
* 根据ID, 逻辑删除Entity实体
* @param id Entity对象ID
* @return boolean 是否删除成功
*/
boolean updateValid(Long id);
/**
* 根据ID, 删除Entity实体,非逻辑删除
* @param id Entity对象ID
* @return boolean 是否删除成功
*/
void delete(Long id);
}
2. 创建BaseService接口实现类BaseServiceImpl,实现类中根据传入的业务模块实体E,创建SimpleJpaRepository
package com.******.common.impl;
import com.******.common.util.BaseConverter;
import com.******.constant.Constants;
import com.******.common.BaseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.*;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
/**
* 封装公共基础实现类,实现基本CRUD操作,避免代码冗余
* @param <V> VO类
* @param <E> Entity实体类
* @author Abin
* @date 2018/10/14
*/
@Service
@Slf4j
public class BaseServiceImpl<V, E> implements BaseService<V, E> {
@Autowired
private BaseConverter baseConverter;
@PersistenceContext
EntityManager em;
private Class<V> voClass;
private Class<E> eClass;
/**
* 根据domain class创建JPA repository 实现类SimpleJpaRepository
* @return SimpleJpaRepository对象
*/
private S