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

SpringBoot系列——Spring-Data-JPA(升级版)

2018-11-20 12:03 736 查看

  前言

  在上篇博客中:SpringBoot系列——Spring-Data-JPA:https://www.cnblogs.com/huanzi-qch/p/9970545.html,我们实现了单表的基础get、save(插入/更新)、list、page、delete接口,但是这样每个单表都要写着一套代码,重复而繁杂,那能不能写成一套通用common代码,每个单表去继承从而实现这套基础接口呢?同时,我们应该用Vo去接收、传输数据,实体负责与数据库表映射。

 

  common代码

  Vo与实体转换

/**
* 实体转换工具
*/
public class FastCopy {

/**
* 类型转换:实体Vo <->实体  例如:UserVo <-> User
* 支持一级复杂对象复制
*/
public static <T> T copy(Object src, Class<T> targetType) {
T target = null;
try {
target = targetType.newInstance();
BeanWrapper targetBean = new BeanWrapperImpl(target);
BeanMap srcBean = new BeanMap(src);
for (Object key : srcBean.keySet()) {
try {
String srcPropertyName = key + "";
Object srcPropertyVal = srcBean.get(key);
//&& StringUtils.isEmpty(targetBean.getPropertyValue(srcPropertyName))
if (!StringUtils.isEmpty(srcPropertyVal) && !"class".equals(srcPropertyName)) {
Class srcPropertyType = srcBean.getType(srcPropertyName);
Class targetPropertyType = targetBean.getPropertyType(srcPropertyName);
if (targetPropertyType != null) {
if (srcPropertyType == targetPropertyType) {
targetBean.setPropertyValue(srcPropertyName, srcPropertyVal);
} else {
Object targetPropertyVal = targetPropertyType.newInstance();
BeanUtils.copyProperties(srcPropertyVal, targetPropertyVal);
targetBean.setPropertyValue(srcPropertyName, targetPropertyVal);

BeanWrapper targetBean2 = new BeanWrapperImpl(targetPropertyVal);
BeanMap srcBean2 = new BeanMap(srcPropertyVal);
srcBean2.keySet().forEach((srcPropertyName2) -> {
Class srcPropertyType2 = srcBean2.getType((String) srcPropertyName2);
Class targetPropertyType2 = targetBean2.getPropertyType((String) srcPropertyName2);
if (targetPropertyType2 != null && srcPropertyType2 != targetPropertyType2
&& srcBean2.get(srcPropertyName2) != null && !"class".equals(srcPropertyName2)) {
Object targetPropertyVal2 = null;
try {
targetPropertyVal2 = targetPropertyType2.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
BeanUtils.copyProperties(srcBean2.get(srcPropertyName2), targetPropertyVal2);
targetBean2.setPropertyValue((String) srcPropertyName2, targetPropertyVal2);
}
});

}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return target;
}

/**
* 类型转换:实体Vo <->实体  例如:List<UserVo> <-> List<User>
*/
public static <T> List<T> copyList(List srcList, Class<T> targetType) {
List<T> newList = new ArrayList<>();
for (Object entity : srcList) {
newList.add(copy(entity, targetType));
}
return newList;
}

/**
* 获取/过滤对象的空属性
*/
public static String[] getNullProperties(Object src) {
BeanWrapper srcBean = new BeanWrapperImpl(src); //1.获取Bean
Set<String> properties = new HashSet<>(); //3.获取Bean的空属性
for (PropertyDescriptor p : srcBean.getPropertyDescriptors()) {
String propertyName = p.getName();
Object srcValue = srcBean.getPropertyValue(propertyName);
if (StringUtils.isEmpty(srcValue)) {
srcBean.setPropertyValue(propertyName, null);
properties.add(propertyName);
}
}
String[] result = new String[properties.size()];
return properties.toArray(result);
}

/**
* 获取对象的非空属性
*/
public static Map<String, Object> getNotNullProperties(Object src) {
BeanWrapper srcBean = new BeanWrapperImpl(src); //1.获取Bean
PropertyDescriptor[] pds = srcBean.getPropertyDescriptors(); //2.获取Bean的属性描述
Map<String, Object> properties = new LinkedHashMap<>();  //3.获取Bean的非空属性
for (PropertyDescriptor p : pds) {
String key = p.getName();
Object value = srcBean.getPropertyValue(key);
if (!StringUtils.isEmpty(value) && !"class".equals(key)) {
properties.put(key, value);
}
}

return properties;
}

/**
* 将Object数组转为实体类VO
*/
public static <V> List<V> getEntityVo(List<Object[]> propertyArrayList, Class<V> voClass) {
List<V> list = new ArrayList<>();
try {
if (propertyArrayList != null) {
for (Object[] propertyArray : propertyArrayList) {
V vo = voClass.newInstance();
Field[] fields = vo.getClass().getDeclaredFields();
for (int i = 0; i < propertyArray.length; i++) {
Field voField = fields[i];
Object queryVal = propertyArray[i];
if (voField.getType() == String.class && queryVal instanceof BigDecimal) {
queryVal = String.valueOf(queryVal);
}
voField.setAccessible(true);//获取授权
voField.set(vo, queryVal);
}
list.add(vo);
}

}
} catch (Exception e) {
throw new RuntimeException(e);
}
return list;
}

}

  

  通用service、repository

/**
* 通用Service
*
* @param <V> 实体类Vo
* @param <E> 实体类
* @param <T> id主键类型
*/
public interface CommonService<V, E,T> {

Result<PageInfo<V>> page(V entityVo);

Result<List<V>> list(V entityVo);

Result<V> get(T id);

Result<V> save(V entityVo);

Result<T> delete(T id);
}
/**
* 通用Service实现类
*
* @param <V> 实体类Vo
* @param <E> 实体类
* @param <T> id主键类型
*/
public class CommonServiceImpl<V, E, T> implements CommonService<V, E, T> {

private Class<V> entityVoClass;//实体类Vo

private Class<E> entityClass;//实体类

@Autowired
private CommonRepository<E, T> commonRepository;//注入实体类仓库

CommonServiceImpl() {
Type[] types = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments();
this.entityVoClass = (Class<V>) types[0];
this.entityClass = (Class<E>) types[1];
}

@Override
public Result<PageInfo<V>> page(V entityVo) {
//实体类缺失分页信息
if (!(entityVo instanceof PageCondition)) {
throw new RuntimeException("实体类" + entityClass.getName() + "未继承PageCondition。");
}
PageCondition pageCondition = (PageCondition) entityVo;
Page<E> page = commonRepository.findAll(Example.of(FastCopy.copy(entityVo, entityClass)), pageCondition.getPageable());
return Result.of(PageInfo.of(page, entityVoClass));
}

@Override
public Result<List<V>> list(V entityVo) {
List<E> entityList = commonRepository.findAll(Example.of(FastCopy.copy(entityVo, entityClass)));
List<V> entityModelList = FastCopy.copyList(entityList, entityVoClass);
return Result.of(entityModelList);
}

@Override
public Result<V> get(T id) {
Optional<E> optionalE = commonRepository.findById(id);
if (!optionalE.isPresent()) {
throw new RuntimeException("ID不存在!");
}
return Result.of(FastCopy.copy(optionalE.get(), entityVoClass));
}

@Override
public Result<V> save(V entityVo) {
E e = commonRepository.save(FastCopy.copy(entityVo, entityClass));
return Result.of(FastCopy.copy(e, entityVoClass));
}

@Override
public Result<T> delete(T id) {
commonRepository.deleteById(id);
return Result.of(id);
}
}
/**
* 通用Repository
*
* @param <E> 实体类
* @param <T> id主键类型
*/
@NoRepositoryBean
public interface CommonRepository<E,T> extends JpaRepository<E,T>, JpaSpecificationExecutor<E> {
}

 

  单表使用

  单表继承通用代码,实现get、save(插入/更新)、list、page、delete接口

  Vo

/**
* 用户类Vo
*/
@Data
public class UserVo extends PageCondition implements Serializable {

private Integer id;

private String username;

private String password;

private Date created;

private String descriptionId;

//机架类型信息
private DescriptionVo description;
}
/**
* 用户描述类Vo
*/
@Data
public class DescriptionVo implements Serializable {
private Integer id;

private String userId;

private String description;
}

 

  controller、service、repository

@RestController
@RequestMapping("/user")
public class UserController {

@Autowired
private UserService userService;

@RequestMapping("/getAllUser")
public ModelAndView getAllUser(){
Result result=userService.getAllUser();
ModelAndView mv=new ModelAndView();
mv.addObject("userList",result.getData());
mv.setViewName("index.html");
return mv;
}

/*
CRUD、分页、排序
*/

@RequestMapping("page")
public Result<PageInfo<UserVo>> page(UserVo entityVo) {
return userService.page(entityVo);
}

@RequestMapping("list")
public Result<List<UserVo>> list(UserVo entityVo) {
return userService.list(entityVo);
}

@RequestMapping("get/{id}")
public Result<UserVo> get(@PathVariable("id") Integer id) {
return userService.get(id);
}

@RequestMapping("save")
public Result<UserVo> save(UserVo entityVo) {
return userService.save(entityVo);
}

@RequestMapping("delete/{id}")
public Result<Integer> delete(@PathVariable("id") Integer id) {
return userService.delete(id);
}
}
public interface UserService extends CommonService<UserVo, User,Integer>{

Result getAllUser();
}
@Service
@Transactional public class UserServiceImpl extends CommonServiceImpl<UserVo, User,Integer> implements UserService { @Autowired private UserRepository userRepository; @Override public Result getAllUser() { List<User> userList = userRepository.getAllUser(); if(userList != null && userList.size()>0){ ArrayList<UserVo> userVos = new ArrayList<>(); for(User user : userList){ userVos.add(FastCopy.copy(user, UserVo.class)); } return Result.of(userVos); }else { return Result.of(userList,false,"获取失败!"); } } }
@Repository
public interface UserRepository extends CommonRepository<User, Integer> {

@Query(value = "from User") //HQL
//    @Query(value = "select * from tb_user",nativeQuery = true)//原生SQL
List<User> getAllUser();

}

 

  经测试,所有的接口都可以使用,数据传输正常,因为传输的Vo,分页信息跟杂七杂八的字段、数据都在Vo,所有看起来会比较杂。更新接口依旧跟上一篇的一样,接收到的是什么就保存什么。

 

  后记

  单表的增删改查接口,直接继承这一套通用代码即可实现,无需再重复编写,大大提升开发效率。

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