mysql查询的手写工具类
注:来源于@tianlihu讲师
在jpa分页查询时需要使用在自定义方法或者给定方法在参数中加入Pageable即可分页,但是如果参数为空则会报错。为避免这种问题·····
此篇文章涉及到,StringBuilder 、LinkedHashMap、instanceof、Sort、PageImpl、对象转map、获取泛型等java重点知识。含金量四颗星。
import ch.qos.logback.core.net.SyslogOutputStream;
import com.zhangzhi.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
/*
* StringBuilder 线程虽不安全但是快,不需要重新赋值在线程中改变值
* LinkedHashMap 使用LinkedHashMap传入的顺序不会发生变化
* */
public class BasesService<T> {
@Autowired
private EntityManager entityManager;
public Page<T> findPage(Object params, Pageable pageable, Integer page, Integer pageSize) {
page = page == null ? 0 : page;
pageSize = pageSize == null ? 10 : pageSize;
return findPage(params, PageRequest.of(page, pageSize));
}
// 这个是带分页的 还可携对象的参数
public Page<T> findPage(LinkedHashMap<String, Object> params, Integer page, Integer pageSize) {
page = page == null ? 0 : page;
pageSize = pageSize == null ? 10 : pageSize;
return findPage(params, PageRequest.of(page, pageSize));
}
// 使用时需要放到 Map 参数只需传pageNum和size
// 第二原生 条件可使用对象转入:使用的专对象的工具方法
public Page<T> findPage(Object params, Pageable pageable) {
LinkedHashMap<String, Object> paramMap = entityToMap(params);
// 先调用产生数据
List<T> list = findList(paramMap, pageable);
// 计算总数
Long count = findCount(paramMap);
return new PageImpl<>(list, pageable, count);
}
//原生! 需传入LinkedHashMap和Pageable
public Page<T> findPage(LinkedHashMap<String, Object> params, Pageable pageable) {
List<T> list = findList(params, pageable);
Long count = findCount(params);
return new PageImpl<>(list, pageable, count);
}
// 使用时需要放到 Map 参数需要传pageable
// 产生数据的方法 参数传入查询条件、传入分页的条件
private List<T> findList(LinkedHashMap<String, Object> params, Pageable pageable) {
StringBuilder hql = new StringBuilder("select t from " + getEntityType().getSimpleName() + " t where 1=1");
// 拼接条件
makeupWhereHql(params, hql);
// 拼接排序
makupOrderBy(pageable, hql);
Query query = entityManager.createQuery(hql.toString());
// 拼接参数
setParameters(params, query);
query.setFirstResult((int) pageable.getOffset());
query.setMaxResults(pageable.getPageSize());
return query.getResultList();
}
// 计算总条数的方法
private Long findCount(LinkedHashMap<String, Object> params) {
StringBuilder hql = new StringBuilder("select count(*) from " + getEntityType().getSimpleName() + " t where 1=1");
// 拼接条件
makeupWhereHql(params, hql);
Query query = entityManager.createQuery(hql.toString());
// 拼接参数
setParameters(params, query);
return (Long) query.getSingleResult();
}
// 拼接排序的方法
private void makupOrderBy(Pageable pageable, StringBuilder hql) {
Sort sort = pageable.getSort();
Iterator<Sort.Order> orders = sort.iterator();
StringBuilder orderBy = new StringBuilder();
if (orders.hasNext()) {
Sort.Order order = orders.next();
String property = order.getProperty();//获取他的值
Sort.Direction direction = order.getDirection();//获取 Desc&Asc
orderBy.append("order by " + property + " " + direction.name());
}
while (orders.hasNext()) {
Sort.Order order = orders.next();
String property = order.getProperty();
Sort.Direction direction = order.getDirection();
orderBy.append("," + property + " " + direction.name());
}
hql.append(orderBy);
}
// 拼接条件的方法
private void makeupWhereHql(LinkedHashMap<String, Object> params, StringBuilder hql) {
Set<Map.Entry<String, Object>> parameters = params.entrySet();
for (Map.Entry<String, Object> parameter : parameters) {
Object value = parameter.getValue();
if (value != null) {
if (value instanceof String) {
hql.append(" and t." + parameter.getKey() + " like concat('%', :" + parameter.getKey() + ", '%')");
} else {
hql.append(" and t." + parameter.getKey() + "=:" + parameter.getKey());
}
}
}
}
// 拼接参数的方法
private void setParameters(LinkedHashMap<String, Object> params, Query query) {
Set<Map.Entry<String, Object>> parameters = params.entrySet();
for (Map.Entry<String, Object> parameter : parameters) {
Object value = parameter.getValue();
if (value != null) {
query.setParameter(parameter.getKey(), value);
}
}
}
// 将对象转为Map 的方法
private static LinkedHashMap<String, Object> entityToMap(Object object) {
LinkedHashMap<String, Object> map = new LinkedHashMap();
for (Field field : object.getClass().getDeclaredFields()) {
try {
boolean flag = field.isAccessible();
field.setAccessible(true);
Object o = field.get(object);
map.put(field.getName(), o);
field.setAccessible(flag);
} catch (Exception e) {
e.printStackTrace();
}
}
return map;
}
//这个是返回泛型的方法
private Class<?> getEntityType() {
Class<?> clazz = getClass();
ParameterizedType genericSuperclass = (ParameterizedType) clazz.getGenericSuperclass();
Type actualClassType = genericSuperclass.getActualTypeArguments()[0];
return (Class<?>) actualClassType;
}
}
调用
public Page<User> findOrders(String summary, Date createTime, Integer page, Integer pageSize) {
LinkedHashMap<String, Object> params = new LinkedHashMap<>();
params.put("summary", summary);
params.put("createTime", createTime);
PageRequest request = PageRequest.of(page, pageSize);
return findPage(params, request);//调用父类的即可
}
合理创造工具类中的重载,可以大幅度的提升效率.