jpa 封装

package com.chehaha.common.data.service;

import java.io.Serializable;
import java.util.List;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

import com.chehaha.common.data.pojo.Criterion;
import com.chehaha.common.data.pojo.DataMode;

public interface ICrudService {

 <T> T get(Serializable id,Class<T> clazz);
 <T> T findOne(List<Criterion> criteria, Class<T> clazz);
 <T> T save(T entity,Class<T> clazz);
 <T> T save(T entity);
 <T> T saveGeneric(T entity,Class<?> clazz);

 <T> void delete(T entity, Class<T> clazz);
 <T> void delete(T entity);
 <T> List<T> getAll(Class<T> clazz);
 <T> List<T> getAll(Class<T> clazz, Sort sort);
 <T> List<T> getAll(Class<T> clazz,DataMode mode);
 <T> List<T> getAll(Class<T> clazz,DataMode mode, Sort sort);
 <T> List<T> getGenericAll(Class<?> clazz);
 <T> List<T> getGenericAll(Class<?> clazz,DataMode mode);
 
 <T> List<T> find(Class<T> clazz, List<Criterion> criteria);
 <T> List<T> find(Class<T> clazz, List<Criterion> criteria, DataMode mode);
 <T> List<T> find(Class<T> clazz, List<Criterion> criteria, Sort sort);
 <T> List<T> find(Class<T> clazz, List<Criterion> criteria, Sort sort,DataMode mode);
 <T> List<T> findGeneric(Class<?> clazz, List<Criterion> criteria);
 <T> List<T> findGeneric(Class<?> clazz, List<Criterion> criteria,DataMode mode); 
 
 <T> Page<T> getAllByPage(Class<T> clazz,Pageable page);
 <T> Page<T> getGenericAllByPage(Class<?> clazz,Pageable page);
 
 <T> Page<T> findByPage(Class<T> clazz, List<Criterion> criteria,Pageable page);
 <T> Page<T> findByPage(Class<T> clazz, List<Criterion> criteria,Pageable page,DataMode mode);
 <T> Page<T> findGenericByPage(Class<?> clazz, List<Criterion> criteria,Pageable page);
 <T> Page<T> findGenericByPage(Class<?> clazz, List<Criterion> criteria,Pageable page,DataMode mode);
 
// <T> List<T> search(Class<T> clazz,Predicate predicate);
}

-----------------------------------------------------------------------------

1.参数设定2.值设定3.builder匹配方法选择。这里用表达式来区分

package com.chehaha.common.data.pojo;


import java.io.Serializable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.List;
import java.util.Map;


public class Criterion implements Serializable {

 private static final long serialVersionUID = 815285616955434414L;
 private final static String regex = "\\|";
 private String property;
 private Expression expression;
 private Object value;

 public static Criterion instance(String key,Object value){
  Criterion c = new Criterion();
  String[] keys = key.split(regex);
  
  c.setExpression(keys.length == 1 ? Expression.Equal : Expression.set(keys[1]));
  c.setProperty(keys[0]);
  
  switch(c.getExpression()){
  case Between:
   Map<String,Object> data = (Map<String,Object>)value;
   String type = data.get("type").toString();
   if("date".equals(type)){
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 
    DateRangeCriterion o = new DateRangeCriterion();
    try {
     o.setBegin(sdf.parse(data.get("begin").toString()));
     o.setEnd(sdf.parse(data.get("end").toString()));
    } catch (ParseException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }   
    c.setValue(o);
   }else if("int".equals(type)){
    IntegerRangeCriterion o = new IntegerRangeCriterion();
    o.setBegin(Integer.parseInt(data.get("begin").toString()) );
    o.setEnd(Integer.parseInt(data.get("end").toString()));
    c.setValue(o);
   }else if("long".equals(type)){
    LongRangeCriterion o = new LongRangeCriterion();
    o.setBegin(Long.parseLong(data.get("begin").toString()) );
    o.setEnd(Long.parseLong(data.get("end").toString()));
    c.setValue(o);
   }else if("float".equals(type)){
    FloatRangeCriterion o = new FloatRangeCriterion();
    o.setBegin(Float.parseFloat(data.get("begin").toString()) );
    o.setEnd(Float.parseFloat(data.get("end").toString()));
    c.setValue(o);
   }else{
    DoubleRangeCriterion o = new DoubleRangeCriterion();
    o.setBegin(Double.parseDouble(data.get("begin").toString()) );
    o.setEnd(Double.parseDouble(data.get("end").toString()));
    c.setValue(o);
   }
   break;
  case In:
   if(value instanceof String){
    c.setValue(Arrays.asList(value.toString().split(",")));
   }else if(value instanceof List){
    c.setValue(value);
   }
   break;
  default:
   c.setValue(value);
   break;
  }
  
  return c;
 }
 
 public String getProperty() {
  return property;
 }

 public void setProperty(String property) {
  this.property = property;
 }

 public Expression getExpression() {
  return expression;
 }

 public void setExpression(Expression expression) {
  this.expression = expression;
 }

 public Object getValue() {
  return value;
 }

 public void setValue(Object value) {
  this.value = value;
 }

}

--------------------------------

package com.chehaha.common.data.pojo;

public enum Expression {
 Equal,NotEqual,Less,LessThan,Great,GreatThan,Between,In,Like,StartLike,EndLike;
 public static Expression set(String val){
  if("less".equals(val)){
   return Less;
  }else if("less-than".equals(val)){
   return LessThan;
  }else if("great".equals(val)){
   return Great;
  }else if("great-than".equals(val)){
   return GreatThan;
  }else if("between".equals(val)){
   return Between;
  }else if("in".equals(val)){
   return In;
  }else if("like".equals(val)){
   return Like;
  }else if("like-start".equals(val)){
   return StartLike;
  }else if("like-end".equals(val)){
   return EndLike;
  }else if("not".equals(val)){
   return NotEqual;
  }else{
   return Equal;
  }
 }
}

--------------------------------------------------------------

具体创建两个对象SimpleJpaRepository  操作实体对象,具体操作参数对象Specification

package com.chehaha.common.data.service.impl;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import com.chehaha.common.exception.FrameworkException;
import com.chehaha.common.exception.code.F1;
import com.chehaha.common.exception.code.F3;
import com.chehaha.common.util.json.impl.FastjsonUtil;
import com.chehaha.shop.entity.ShopDiscountInfo;
import com.chehaha.shop.pojo.ActiveStatus;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

//import com.querydsl.core.types.Predicate;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
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.JpaContext;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.JpaEntityInformationSupport;
import org.springframework.data.jpa.repository.support.QueryDslJpaRepository;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.chehaha.common.data.pojo.*;
import com.chehaha.common.data.service.ICrudService;
import com.chehaha.common.util.string.StringUtil;

@Service
@Transactional(readOnly = true)
public class CrudServiceImpl implements ICrudService {

 private static final Logger log = LoggerFactory.getLogger(CrudServiceImpl.class);

 @Autowired
 private JpaContext context;

 private <T> SimpleJpaRepository<T, Serializable> getGenericRepository(Class<?> clazz) {
  // ((java.lang.reflect.ParameterizedType)clazz.getGenericSuperclass()).getActualTypeArguments()[0];
  Class<T> entityClass = (Class<T>) clazz;
  return getRepository(entityClass);
 }

 private <T> SimpleJpaRepository<T, Serializable> getRepository(Class<T> clazz) {
  EntityManager em = context.getEntityManagerByManagedType(clazz);
  JpaEntityInformation<T, ?> jei = JpaEntityInformationSupport.getEntityInformation(clazz, em);
  return new SimpleJpaRepository<T, Serializable>(jei, em);
 }

 private <T> QueryDslJpaRepository<T, Serializable> getDslRepository(Class<T> clazz) {
  EntityManager em = context.getEntityManagerByManagedType(clazz);
  JpaEntityInformation<T, Serializable> jei = (JpaEntityInformation<T, Serializable>) JpaEntityInformationSupport
    .getEntityInformation(clazz, em);
  return new QueryDslJpaRepository<T, Serializable>(jei, em);
 }

 private <T> Expression<? extends T> castToType(Class<T> clazz, Object o) {
  return (Expression<? extends T>) o;
 }

 private <T> List<T> clearPropertyCollection(Class<T> clazz, List<T> list) throws IllegalAccessException,
   IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
  List<Field> listFields = new ArrayList<Field>();
  Field[] allFields = clazz.getDeclaredFields();
  for (Field f : allFields) {
   if (Collection.class.isAssignableFrom(f.getType())) {
    listFields.add(f);
   }
  }
  for (T item : list) {
   for (Field field : listFields) {
    clazz.getMethod(StringUtil.getSetterName(field.getName()), field.getType()).invoke(item, (Object) null);
    // field.setAccessible(true);
    // field.set(item, null);
   }
  }
  return list;
 }

 private <T> Specification<T> getSpec(List<Criterion> criteria, boolean isNone) {// ,Class<?> clazz) {
  // Class<T> entityClass = (Class<T>)clazz;
  return new Specification<T>() {
   @Override
   public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
    if (isNone) {
     return builder.disjunction();
    }
    Predicate pred = builder.conjunction();
    Path<?> exp = null;
    String[] attr;
    boolean isSingle = true;
    for (Criterion cr : criteria) {
     attr = cr.getProperty().split("\\.");
     isSingle = attr[0].indexOf(",") < 0;
     if (isSingle) {
      exp = root.get(attr[0]);
     }
     if (attr.length > 1) {
      exp = root.join(attr[0]).get(attr[1]);
     }

     switch (cr.getExpression()) {
     case Equal:
      pred = builder.and(pred, builder.equal(exp, cr.getValue()));
      break;
     case NotEqual:
      pred = builder.and(pred, builder.notEqual(exp, cr.getValue()));
      break;
     case Like:
      String key1 = cr.getValue().toString();
      if (isSingle) {
       pred = builder.and(pred, builder.like((Expression<String>) exp, "%" + key1 + "%"));
      } else {
       String[] attrs = attr[0].split(",");
       List<Predicate> muti = new ArrayList<Predicate>();
       for (String a : attrs) {
        muti.add(builder.like((Expression<String>) root.<String>get(a), "%" + key1 + "%"));
       }
       pred = builder.and(pred, builder.or(muti.toArray(new Predicate[muti.size() - 1])));
      }
      break;
     case StartLike:
      String key2 = cr.getValue().toString();
      if (isSingle) {
       pred = builder.and(pred, builder.like((Expression<String>) exp, "%" + key2));
      } else {
       String[] attrs = attr[0].split(",");
       List<Predicate> muti = new ArrayList<Predicate>();
       for (String a : attrs) {
        muti.add(builder.like((Expression<String>) root.<String>get(a), "%" + key2));
       }
       pred = builder.and(pred, builder.or(muti.toArray(new Predicate[muti.size() - 1])));
      }
      break;
     case EndLike:
      String key3 = cr.getValue().toString();
      if (isSingle) {
       pred = builder.and(pred, builder.like((Expression<String>) exp, key3 + "%"));
      } else {
       String[] attrs = attr[0].split(",");
       List<Predicate> muti = new ArrayList<Predicate>();
       for (String a : attrs) {
        muti.add(builder.like((Expression<String>) root.<String>get(a), key3 + "%"));
       }
       pred = builder.and(pred, builder.or(muti.toArray(new Predicate[muti.size() - 1])));
      }
      break;
     case Great:
      if (cr.getValue() instanceof Number) {
       pred = builder.and(pred, builder.gt((Expression<Number>) exp, (Number) cr.getValue()));
      } else if (cr.getValue() instanceof Date) {
       pred = builder.and(pred, builder.greaterThan((Expression<Date>) exp, (Date) cr.getValue()));
      } else {
       SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
       try {
        pred = builder.and(pred, builder.greaterThan((Expression<Date>) exp,
          sdf.parse(cr.getValue().toString())));
       } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
       }
      }
      break;
     case GreatThan:
      if (cr.getValue() instanceof Number) {
       pred = builder.and(pred, builder.ge((Expression<Number>) exp, (Number) cr.getValue()));
      } else if (cr.getValue() instanceof Date) {
       pred = builder.and(pred,
         builder.greaterThanOrEqualTo((Expression<Date>) exp, (Date) cr.getValue()));
      } else {
       SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
       try {
        pred = builder.and(pred, builder.greaterThanOrEqualTo((Expression<Date>) exp,
          sdf.parse(cr.getValue().toString())));
       } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
       }
      }
      break;
     case Less:
      if (cr.getValue() instanceof Number) {
       pred = builder.and(pred, builder.lt((Expression<Number>) exp, (Number) cr.getValue()));
      } else if (cr.getValue() instanceof Date) {
       pred = builder.and(pred, builder.lessThan((Expression<Date>) exp, (Date) cr.getValue()));
      } else {
       SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
       try {
        pred = builder.and(pred,
          builder.lessThan((Expression<Date>) exp, sdf.parse(cr.getValue().toString())));
       } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
       }
      }
      break;
     case LessThan:
      if (cr.getValue() instanceof Number) {
       pred = builder.and(pred, builder.le((Expression<Number>) exp, (Number) cr.getValue()));
      } else if (cr.getValue() instanceof Date) {
       pred = builder.and(pred,
         builder.lessThanOrEqualTo((Expression<Date>) exp, (Date) cr.getValue()));
      } else {
       SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
       try {
        pred = builder.and(pred, builder.lessThanOrEqualTo((Expression<Date>) exp,
          sdf.parse(cr.getValue().toString())));
       } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
       }
      }
      break;
     case Between:
      Class<?> cls = (Class<?>) ((ParameterizedType) cr.getValue().getClass().getGenericSuperclass())
        .getActualTypeArguments()[0];
      if (Date.class.equals(cls)) {
       DateRangeCriterion range = (DateRangeCriterion) cr.getValue();
       pred = builder.and(pred, builder.between((Expression<? extends Date>) exp, range.getBegin(),
         range.getEnd()));
      } else if (Integer.class.equals(cls)) {
       IntegerRangeCriterion range = (IntegerRangeCriterion) cr.getValue();
       pred = builder.and(pred,
         builder.between((Expression<Integer>) exp, range.getBegin(), range.getEnd()));
      } else if (Long.class.equals(cls)) {
       LongRangeCriterion range = (LongRangeCriterion) cr.getValue();
       pred = builder.and(pred,
         builder.between((Expression<Long>) exp, range.getBegin(), range.getEnd()));
      } else if (Float.class.equals(cls)) {
       FloatRangeCriterion range = (FloatRangeCriterion) cr.getValue();
       pred = builder.and(pred,
         builder.between(exp.as(Float.class), range.getBegin(), range.getEnd()));
      } else {
       DoubleRangeCriterion range = (DoubleRangeCriterion) cr.getValue();
       pred = builder.and(pred,
         builder.between(exp.as(Double.class), range.getBegin(), range.getEnd()));
      }
      break;
     case In:
      List<String> list = (List<String>) cr.getValue();
      pred = builder.and(pred, exp.in(list));
      break;
     default:
      break;
     }
    }
    return pred;
   }
  };
 }

 @Override
 public <T> T get(Serializable id, Class<T> clazz) {
  // TODO Auto-generated method stub
  return getRepository(clazz).findOne(id);
 }

 @Override
 public <T> T findOne(List<Criterion> criteria, Class<T> clazz) {
  Specification<T> spec = getSpec(criteria, false);
  // TODO Auto-generated method stub
  return getRepository(clazz).findOne(spec);
 }

 @Override
 @Transactional
 public <T> T save(T entity, Class<T> clazz) {
  // TODO Auto-generated method stub
  return getRepository(clazz).save(entity);

 }

 @Override
 @Transactional
 public <T> T save(T entity) {
  // TODO Auto-generated method stub
  return save(entity, (Class<T>) entity.getClass());
 }

 @Override
 @Transactional
 public <T> void delete(T entity, Class<T> clazz) {
  // TODO Auto-generated method stub
  getRepository(clazz).delete(entity);
 }

 @Override
 @Transactional
 public <T> void delete(T entity) {
  delete(entity, (Class<T>) entity.getClass());
 }

 @Override
 @Transactional
 public <T> T saveGeneric(T entity, Class<?> clazz) {
  // TODO Auto-generated method stub
  return getGenericRepository(clazz).save(entity);

 }

 public <T> List<T> getAll(Class<T> clazz, DataMode mode) {
  return getAll(clazz, mode, null);
 }

 public <T> List<T> getAll(Class<T> clazz, DataMode mode, Sort sort) {
  List<Criterion> criteria = new ArrayList<Criterion>();
  return find(clazz, criteria, sort, mode);
 }

 public <T> List<T> getAll(Class<T> clazz, Sort sort) {
  return getAll(clazz, DataMode.All, sort);
 }

 public <T> List<T> getAll(Class<T> clazz) {
  return getAll(clazz, DataMode.All);
 }

 public <T> List<T> getGenericAll(Class<?> clazz, DataMode mode) {
  List<Criterion> criteria = new ArrayList<Criterion>();
  return findGeneric(clazz, criteria, mode);
 }

 public <T> List<T> getGenericAll(Class<?> clazz) {
  return getGenericAll(clazz, DataMode.All);
 }

 public <T> List<T> find(Class<T> clazz, List<Criterion> criteria) {
  return find(clazz, criteria, DataMode.NoDetail);
 }

 public <T> List<T> find(Class<T> clazz, List<Criterion> criteria, Sort sort) {
  return find(clazz, criteria, sort, DataMode.NoDetail);
 }
 
 public <T> List<T> find(Class<T> clazz, List<Criterion> criteria, DataMode mode) {
  return find(clazz, criteria, null, mode);
 }

 public <T> List<T> find(Class<T> clazz, List<Criterion> criteria, Sort sort, DataMode mode) {
  boolean isNone = (mode == DataMode.None);
  Specification<T> spec = getSpec(criteria, isNone);
  List<T> list = getRepository(clazz).findAll(spec, sort);
  if (mode == DataMode.NoDetail) {
   try {
    // StatefulPersistenceContext.initializeNonLazyCollections()
    // 看如何阻止该方法运行
    list = clearPropertyCollection(clazz, list);
   } catch (Exception e) {
    log.error("can't remove entity's collection properties....");
   }
  }
  return list;
 }

 public <T> List<T> findGeneric(Class<?> clazz, List<Criterion> criteria) {
  return findGeneric(clazz, criteria, DataMode.NoDetail);
 }

 public <T> List<T> findGeneric(Class<?> clazz, List<Criterion> criteria, DataMode mode) {
  boolean isNone = (mode == DataMode.None);
  Specification<Object> spec = getSpec(criteria, isNone);
  List<T> list = (List<T>) getGenericRepository(clazz).findAll(spec);
  if (mode == DataMode.NoDetail) {
   try {
    // StatefulPersistenceContext.initializeNonLazyCollections()
    // 看如何阻止该方法运行
    list = clearPropertyCollection((Class<T>) clazz, (List<T>) list);
   } catch (Exception e) {
    log.error("can't remove entity's collection properties....");
   }
  }
  return list;
 }

 public <T> Page<T> getAllByPage(Class<T> clazz, Pageable page) {
  List<Criterion> criteria = new ArrayList<Criterion>();
  return findByPage(clazz, criteria, page);
 }

 public <T> Page<T> getGenericAllByPage(Class<?> clazz, Pageable page) {
  List<Criterion> criteria = new ArrayList<Criterion>();
  return findGenericByPage(clazz, criteria, page);
 }

 public <T> Page<T> findByPage(Class<T> clazz, List<Criterion> criteria, Pageable page) {
  return findByPage(clazz, criteria, page, DataMode.NoDetail);
 }

 public <T> Page<T> findByPage(Class<T> clazz, List<Criterion> criteria, Pageable page, DataMode mode) {
  boolean isNone = (mode == DataMode.None);
  Specification<T> spec = getSpec(criteria, isNone);
  Page<T> pagenation = getRepository(clazz).findAll(spec, page);
  if (mode == DataMode.NoDetail) {
   try {
    clearPropertyCollection(clazz, pagenation.getContent());
   } catch (Exception e) {
    log.error("can't remove entity's collection properties....");
   }
  }
  return pagenation;
 }

 public <T> Page<T> findGenericByPage(Class<?> clazz, List<Criterion> criteria, Pageable page) {
  return findGenericByPage(clazz, criteria, page, DataMode.NoDetail);
 }

 public <T> Page<T> findGenericByPage(Class<?> clazz, List<Criterion> criteria, Pageable page, DataMode mode) {
  boolean isNone = (mode == DataMode.None);
  Specification<T> spec = getSpec(criteria, isNone);
  Page<T> pagenation = (Page<T>) getGenericRepository(clazz).findAll((Specification<Object>) spec, page);
  if (mode == DataMode.NoDetail) {
   try {
    // clearPropertyCollection(clazz, pagenation.getContent());
   } catch (Exception e) {
    log.error("can't remove entity's collection properties....");
   }
  }
  return pagenation;
 }

 // public <T> List<T> search(Class<T> clazz, com.querydsl.core.types.Predicate
 // predicate) {
 // return getDslRepository(clazz).findAll(predicate);
 // }

}

jpa 理解

1. spirngboot jpa 默认使用的是spring.datasource下的数据源。如果使用多数据源则重新配置@bean @Qualify Datasource

2. 配置数据库原地址后 可以配置jpa的核心 EntityManageFactory管理器 ,然后可以配置管理核心操作EntityManage 接口

3. 使用方式可以有 3.1. 用entitymanage直接操作 ,增删改查都写入自己定义的工具类中(非接口形式,简单)

  3.2 可以继续配置封装到自定jpa接口中进行使用,此接口继承jpaRepository 后使用此接口了。(接口形式,一般)

  3.3  使用系统自带的封装了entitymanage 的类 simpleJpaRepository 进行使用 (接口形式,难)

3种方法都是围绕核心entitymanage进行封装,可以继承接口 后使用,可以直接封装到类里头直接使用 。

猜你喜欢

转载自blog.csdn.net/qq_27988103/article/details/80433979
JPA
今日推荐