LAPTOP-KB9HII50\70708 2 лет назад
Родитель
Сommit
690fba030b

+ 50 - 0
starter/mysql-starter/pom.xml

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>wlyy-starter</artifactId>
        <groupId>com.yihu.jw</groupId>
        <version>2.4.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>mysql-starter</artifactId>
    <dependencies>
        <!-- JdbcTemplate-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-dbcp2</artifactId>
        </dependency>
        <!-- JdbcTemplate-->
        <!-- Jpa -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!-- Jpa -->
        <!-- Hibernate -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>${version.hibernate-validator}</version>
        </dependency>
        <!-- Hibernate -->
        <dependency>
            <groupId>com.yihu</groupId>
            <artifactId>utils</artifactId>
            <version>2.0.0</version>
        </dependency>
    </dependencies>
</project>

+ 219 - 0
starter/mysql-starter/src/main/java/com/yihu/mysql/parm/PageModel.java

@ -0,0 +1,219 @@
package com.yihu.mysql.parm;
import com.yihu.mysql.query.FieldCondition;
import org.springframework.util.StringUtils;
import javax.persistence.Column;
import java.lang.reflect.Method;
import java.util.*;
/**
 * 实体查询模型。将前端的查询转换为实体查询。
 *
 * @author lincl
 * @version 1.0
 * @created 2016.2.1
 */
public class PageModel {
    private int page;                               // 页码
    private int rows;                               // 页大小
    private String[] order;                         // 排序,格式为 +f1,-f2
    private Map<String, FieldCondition> filters;    // 记录过滤器
    private String[] result;                        // 实际返回的字段
    private Class modelClass;                       // JPA实体类
    public PageModel() {
    }
    public PageModel(int page, int rows) {
        this.page = page;
        this.rows = rows;
    }
    public String format(String modelName, boolean isSql) {
        if (modelClass == null) {
            System.err.print("NullPoint: modelClass");
            return "";
        }
        Map<String, FieldCondition> filters = getFilters();
        if (filters.size() == 0)
            return "";
        Map<String, String> whMap = new HashMap<>();
        FieldCondition fieldCondition;
        String wh = "";
        for (String k : filters.keySet()) {
            fieldCondition = filters.get(k);
            if (!fieldCondition.isValid())
                continue;
            if (fieldCondition.isGroup()) {
                String str = whMap.get(fieldCondition.getGroup());
                if (str == null)
                    str = "(" + fieldCondition.format(modelName, isSql);
                else
                    str += " or " + fieldCondition.format(modelName, isSql);
                whMap.put(fieldCondition.getGroup(), str);
            } else {
                if (wh.equals(""))
                    wh = fieldCondition.format(modelName, isSql);
                else
                    wh += " and " + fieldCondition.format(modelName, isSql);
            }
        }
        for (String k : whMap.keySet()) {
            wh += " and " + whMap.get(k) + ") ";
        }
        return wh;
    }
    private String getTableCol(String field) {
        try {
            Method method = modelClass.getMethod("get" + firstLetterToUpper(field));
            Column column = method.getDeclaredAnnotation(Column.class);
            if (column != null) {
                return column.name();
            }
            return null;
        } catch (Exception e) {
            return null;
        }
    }
    public String formatSqlOrder(String modelName) {
        return formatOrder(modelName, true);
    }
    public String formatSqlOrder() {
        return formatSqlOrder("");
    }
    public String formatOrder() {
        return formatOrder("", false);
    }
    public String formatOrder(String modelName, boolean isSql) {
        if (modelClass == null) {
            System.err.print("NullPoint: modelClass");
            return "";
        }
        if (order == null || order.length == 0)
            return "";
        List<String> ls = new ArrayList<>();
        String tmp = "";
        if (isSql) {
            for (String item : order) {
                tmp = getTableCol(item);
                if (!StringUtils.isEmpty(tmp))
                    ls.add(tmp);
            }
        } else
            for (String item : order) {
                tmp = getTableCol(item);
                if (!StringUtils.isEmpty(tmp))
                    ls.add(item);
            }
        return arrayJoin(ls, StringUtils.isEmpty(modelName) ? "," : "," + modelName + ".", 1);
    }
    public String arrayJoin(Collection<String> ls, String joinStr, int offer) {
        if (ls == null || ls.size() == 0)
            return "";
        String tmp = "";
        for (String str : ls) {
            tmp += joinStr + str;
        }
        return tmp.substring(offer);
    }
    public String formatWithOrder(String modelName) {
        return format(modelName, false) + " order by " + formatOrder(modelName, false);
    }
    public String formatSqlWithOrder(String modelName) {
        return formatSql(modelName) + " order by " + formatSqlOrder(modelName);
    }
    public String format() {
        return format("", false);
    }
    public String formatSql(String modelName) {
        return format(modelName, true);
    }
    public String formatSql() {
        return formatSql("");
    }
    public Object getFieldVal(String field) {
        return filters.get(field).getVal();
    }
    public void setFieldVal(String field, List val) {
        filters.get(field).setVal(val);
    }
    public int getPage() {
        return page;
    }
    public void setPage(int page) {
        this.page = page;
    }
    public int getRows() {
        return rows;
    }
    public void setRows(int rows) {
        this.rows = rows;
    }
    public Map<String, FieldCondition> getFilters() {
        return filters == null ? new HashMap<>() : filters;
    }
    public void setFilters(Map<String, FieldCondition> filters) {
        this.filters = filters;
    }
    public void addFieldCondition(FieldCondition fieldCondition) {
        if (filters == null)
            filters = new HashMap<>();
        filters.put(fieldCondition.getCol(), fieldCondition);
    }
    public String[] getOrder() {
        return order;
    }
    public void setOrder(String[] order) {
        this.order = order;
    }
    public String[] getResult() {
        return result;
    }
    public void setResult(String[] result) {
        this.result = result;
    }
    public Class getModelClass() {
        return modelClass;
    }
    public void setModelClass(Class modelClass) {
        this.modelClass = modelClass;
        Map<String, FieldCondition> map = getFilters();
        for (String key : map.keySet()) {
            map.get(key).setTableCol(getTableCol(key));
        }
    }
    public static String firstLetterToUpper(String str) {
        if (str == null || "".equals(str.trim())) {
            return "";
        }
        return str.replaceFirst(("" + str.charAt(0)), ("" + str.charAt(0)).toUpperCase());
    }
}

+ 362 - 0
starter/mysql-starter/src/main/java/com/yihu/mysql/query/BaseJpaService.java

@ -0,0 +1,362 @@
package com.yihu.mysql.query;
import com.yihu.utils.context.SpringContextUtils;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.EntityType;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.text.ParseException;
import java.util.*;
/**
 * Service基础类。此类基于Spring Data JPA进行封装(Spring Data JPA又是基于JPA封装,EHR平台使用Hibernate作为JPA实现者)。
 * 需要注意的是,部分功能会跳过JPA接口而直接使用Hibernate接口,比如访问Hibernate的Session接口,因为它把JPA的EntityManager功能强大。
 *
 * @author lincl
 * @author Sand
 * @version 1.0
 * @created 2016.2.3。
 */
@Transactional(propagation = Propagation.SUPPORTS)
public abstract class BaseJpaService<T, R extends CrudRepository> {
    protected final int defaultPage = 1;
    protected final int defaultSize = 15;
    protected Class<T> tClass;
    protected Class<R> repoClass;
    @PersistenceContext
    protected EntityManager entityManager;
    @Autowired
    protected JdbcTemplate jdbcTemplate;
    public BaseJpaService() {
        Type genType = getClass().getGenericSuperclass();
        if (genType instanceof ParameterizedType) {
            Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
            if (params.length == 2) {
                tClass = (Class<T>) params[0];
                repoClass = (Class<R>) params[1];
            }
        }
    }
    public T save (T entity) {
        return (T) getRepository().save(entity);
    }
    public void batchInsert (List list) {
        for (int i = 0; i < list.size(); i++) {
            entityManager.persist(list.get(i));
            if (i % 30 == 0) {
                entityManager.flush();
                entityManager.clear();
            }
        }
    }
    public void delete(Serializable id) {
        getRepository().delete(id);
    }
    public void delete(T entity) {
        getRepository().delete(entity);
    }
    public void delete(Iterable ids) {
        getRepository().delete(ids);
    }
    public int delete(Object[] ids){
        if (Integer.class.getName().equals(getEntityIdType())) {
            Integer [] _ids = new Integer[ids.length];
            for (int i = 0; i < ids.length; i ++) {
                _ids[i] = new Integer(ids[i].toString());
            }
            ids = _ids;
        }
        String hql = "DELETE FROM " + getEntityClass().getName() + " WHERE " + getEntityIdFiled() + " in(:ids)";
        Query query = currentSession().createQuery(hql);
        query.setParameterList("ids", ids);
        return query.executeUpdate();
    }
    public T retrieve(Serializable id) {
        return (T) getRepository().findById(id);
    }
    public List<T> search(String filters) throws ParseException {
        URLQueryParser queryParser = createQueryParser("", filters, "");
        CriteriaQuery query = queryParser.makeCriteriaQuery();
        return entityManager
                .createQuery(query)
                .getResultList();
    }
    public List<T> search(String filters, String sorts) throws ParseException {
        URLQueryParser queryParser = createQueryParser("", filters, sorts);
        CriteriaQuery query = queryParser.makeCriteriaQuery();
        return entityManager
                .createQuery(query)
                .getResultList();
    }
    public List<T> search(String fields, String filters, String sorts) throws ParseException {
        URLQueryParser queryParser = createQueryParser(fields, filters, sorts);
        CriteriaQuery query = queryParser.makeCriteriaQuery();
        return entityManager
                .createQuery(query)
                .getResultList();
    }
    public List<T> search(String fields, String filters, String sorts, Integer page, Integer size) throws ParseException {
        URLQueryParser queryParser = createQueryParser(fields, filters, sorts);
        CriteriaQuery query = queryParser.makeCriteriaQuery();
        if (page == null || page <= 0) {
            page = defaultPage;
        }
        if (size == null || size <= 0 || size > 10000) {
            size = defaultSize;
        }
        return entityManager
                .createQuery(query)
                .setFirstResult((page - 1) * size)
                .setMaxResults(size)
                .getResultList();
    }
    public List<T> findByField(String field, Object value){
        return findByFields(
                new String[]{field},
                new Object[]{value}
        );
    }
    public List<T> findByFields(String[] fields, Object[] values){
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery query = criteriaBuilder.createQuery(getEntityClass());
        Root<T> root = query.from(getEntityClass());
        List<Predicate> ls = new ArrayList<>();
        for(int i=0; i< fields.length; i++){
            if (values[i].getClass().isArray()) {
                ls.add(criteriaBuilder.in(root.get(fields[i]).in((Object[]) values[i])));
            } else {
                ls.add(criteriaBuilder.equal(root.get(fields[i]), values[i]));
            }
        }
        query.where(ls.toArray(new Predicate[ls.size()]));
        return entityManager
                .createQuery(query)
                .getResultList() ;
    }
    public long getCount(String filters) throws ParseException {
        URLQueryParser queryParser = createQueryParser(filters);
        CriteriaQuery query = queryParser.makeCriteriaCountQuery();
        return (long) entityManager.createQuery(query).getSingleResult();
    }
    public Class<T> getEntityClass() {
        return tClass;
    }
    public <T> URLQueryParser createQueryParser(String fields, String filters, String orders) {
        URLQueryParser queryParser = new URLQueryParser<T>(fields, filters, orders)
                .setEntityManager(entityManager)
                .setEntityClass(getEntityClass());
        return queryParser;
    }
    public <T> URLQueryParser createQueryParser(String filters) {
        URLQueryParser queryParser = new URLQueryParser<T>(filters)
                .setEntityManager(entityManager)
                .setEntityClass(getEntityClass());
        return queryParser;
    }
    public Sort parseSorts(String sorter){
        if (!StringUtils.isEmpty(sorter)) {
            String[] orderArray = sorter.split(",");
            List<Sort.Order> orderList = new ArrayList<>(orderArray.length);
            Arrays.stream(orderArray).forEach(
                    elem -> orderList.add(
                            elem.startsWith("+") ? new Sort.Order(Sort.Direction.ASC, elem.substring(1)):
                                    new Sort.Order(Sort.Direction.DESC, elem.substring(1))));
            return Sort.by(orderList);
        }
        return null;
    }
    public JpaRepository getJpaRepository(){
        return (JpaRepository) SpringContextUtils.getService(repoClass);
    }
    public R getRepository() {
        return SpringContextUtils.getService(repoClass);
    }
    public Session currentSession() {
        return entityManager.unwrap(Session.class);
    }
    public String getEntityName(){
        return getEntityClass().getName();
    }
    public String getEntityIdFiled(){
        EntityType entityType = entityManager.getMetamodel().entity(getEntityClass());
        javax.persistence.metamodel.Type type = entityType.getIdType();
        return entityType.getId(type.getJavaType()).getName();
    }
    public String getEntityIdType(){
        EntityType entityType = entityManager.getMetamodel().entity(getEntityClass());
        javax.persistence.metamodel.Type type = entityType.getIdType();
        return type.getJavaType().getName();
    }
    /**
     * 将实体转换为模型。
     *
     * @param source
     * @param target
     * @param <T>
     * @return
     */
    public <T> T convertToModel(Object source, Class<T> target) {
        if (source == null) {
            return null;
        }
        T _target = BeanUtils.instantiate(target);
        BeanUtils.copyProperties(source, _target);
        return _target;
    }
    /**
     * 将实体集合转换为模型集合。
     * @param sources
     * @param targets
     * @param target
     * @param <T>
     * @return
     */
    public <T> List<T> convertToModels(Collection sources, List<T> targets, Class<T> target){
        if (null == sources) {
            return null;
        }
        sources.forEach(item -> {
            T _target = BeanUtils.instantiate(target);
            BeanUtils.copyProperties(item, _target);
            targets.add(_target);
        });
        return targets;
    }
    public String getCode() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }
    /**
     * 获取指定长度的随机数字字符串
     * @param length
     * @return
     */
    public String randomInt(int length) {
        String str = "0123456789";
        StringBuffer buffer = new StringBuffer();
        Random random = new Random();
        for(int i = 0; i < length; ++i) {
            int pos = random.nextInt(str.length());
            buffer.append(str.charAt(pos));
        }
        return buffer.toString();
    }
    /**
     * 获取指定长度的随机字符串
     * @param length
     * @return
     */
    public String randomString(int length) {
        String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        StringBuffer buffer = new StringBuffer();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            int pos = random.nextInt(str.length());
            buffer.append(str.charAt(pos));
        }
        return buffer.toString();
    }
    /**
     * 排序条件 第一个字符为 + 表示升序,第一个字符为 - 表示减序,不包含 + 或者 - 默认升序
     * @param sorts
     * @return
     */
    public Sort createSort(String sorts){
        Sort sort = null;
        if (!org.springframework.util.StringUtils.isEmpty(sorts)) {
            // 默认升序
            if(sorts.contains("-")){
                sort = Sort.by(Sort.Direction.DESC,sorts.substring(1,sorts.length()).split(","));
            }else if(sorts.contains("+")){
                sort = Sort.by(Sort.Direction.ASC,sorts.substring(1,sorts.length()).split(","));
            }else{
                sort = Sort.by(Sort.Direction.ASC,sorts.split(","));
            }
        }
        return sort;
    }
    /**
     * 创建分页对象
     * @param page
     * @param size
     * @param sorts
     * @return
     */
    public Pageable createPage(Integer page, Integer size, String sorts){
        PageRequest pageRequest = null;
        if(null == page || page <= 0){
            page = defaultPage;
        }
        if(null == size || size <= 0){
            size = defaultSize;
        }
        if(!org.apache.commons.lang3.StringUtils.isEmpty(sorts)){
            pageRequest = PageRequest.of(page,size,createSort(sorts));
        }else{
            pageRequest = PageRequest.of(page,size);
        }
        return pageRequest;
    }
}

+ 198 - 0
starter/mysql-starter/src/main/java/com/yihu/mysql/query/FieldCondition.java

@ -0,0 +1,198 @@
package com.yihu.mysql.query;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
/**
 * @author lincl
 * @version 1.0
 * @created 2016.2.1
 */
public class FieldCondition {
    private String col;       //过滤字段 ,不可为空
    private String logic;    //过滤方式,默认为=;   =, sw, ew, like, >, <, between, >=, <=
    private List<Object> val;//过滤值, 值为空则不过滤
    private String group;   //分组,  多个过滤器中的group相同时  用or连接
    private String tableCol;//数据库字段, 初始化根据实体自动设置, user设置无效
    public FieldCondition() {
    }
    public FieldCondition(String col, Object val) {
        this.col = col;
        this.addVal(val);
    }
    public FieldCondition(String col, String logic, Object ... vals) {
        this.col = col;
        this.logic = logic;
        this.addVal(vals);
    }
    public FieldCondition(String col, String logic, List<Object> val, String group) {
        this.col = col;
        this.logic = logic;
        this.val = val;
        this.group = group;
    }
    /**
     * 格式化过滤条件
     * @param modelName 视图名
     * @param isSql true:返回sql形式, false:返回jpa形式
     * @return
     */
    public String format(String modelName, boolean isSql){
        if(getCol()==null || getCol().equals("") || getVal()==null || getVal().size()==0)
            return "";
        String val = getValMapping();
        if(val==null)
            return "";
        String rs = (isSql ? getTableCol() : getCol()) + " " + getLogic() + " " + val;
        if(modelName.trim().equals(""))
            return " " + rs;
        return " " +modelName + "." + rs;
    }
    /**
     * 格式化过滤条件
     * @return 返回jpa形式
     */
    public String format(){
        return format("", false);
    }
    /**
     * 格式化过滤条件
     * @return 返回sql形式
     */
    public String formatSql(){
        return format("", true);
    }
    /**
     * 判断是否存在分组信息
     * @return
     */
    public boolean isGroup(){
        return !(getGroup()==null || "".equals(getGroup()));
    }
    /**
     * 添加值
     * @param vals
     */
    public void addVal(Object ... vals){
        if(this.val==null)
            this.val = new ArrayList<>();
        for(Object val:vals){
            this.val.add(val);
        }
    }
    /**
     * 判断数据表是否包含有该过滤字段
     * @return
     */
    public boolean isValid() {
        return !StringUtils.isEmpty(getTableCol()) && !(getVal()==null || getVal().size()==0)
                 && !(getCol()==null || getCol().equals("")) && isLogicValid();
    }
    /**
     * 判断查询方式是否符合规范
     * @return
     */
    public boolean isLogicValid(){
        String logic = getLogic();
        if(logic.equals("=") || logic.equals("like") || logic.equals("sw") || logic.equals("ew") ||
                logic.equals("<") || logic.equals(">") || logic.equals(">=") || logic.equals("<=") ||
                    logic.equals("in") || logic.equals("not in") || logic.equals("between"))
            return true;
        return false;
    }
    /**
     * 获取占位符
     * @return
     */
    private String getValMapping(){
        String logic = getLogic();
        String val = ":" + getCol();
        if(logic.equals("in") || logic.equals("not in"))
            return  "("+val+") ";
        if(logic.equals("between"))
            return val + "1 and " +val+"2 ";
        if(logic.equals("=") || logic.equals("like") || logic.equals("sw") || logic.equals("ew") ||
                logic.equals("<") || logic.equals(">") || logic.equals(">=") || logic.equals("<=")){
            return val;
        }
        return null;
    }
    /**
     * 格式化 值, 不支持between
     * between形式: 调用getVal(), 获取值,  占位符为 between col + "1" and  col + "2"
     * @return
     */
    public Object formatVal(){
        if(getLogic().equals("sw"))
            return "%"+getVal().get(0);
        if (getLogic().equals("ew"))
            return getVal().get(0)+"%";
        if (getLogic().equals("like"))
            return "%"+getVal().get(0)+"%";
        if(getLogic().equals("in") || getLogic().equals("not in"))
            return getVal();
        return getVal().get(0);
    }
    /************************************************************************************/
    /***************            getter  &  setter                            ************/
    /***************                                                         ************/
    /************************************************************************************/
    public String getCol() {
        return col;
    }
    public void setCol(String col) {
        this.col = col;
    }
    public String getLogic() {
        if(logic==null || "".equals(logic))
            return "=";
        return logic;
    }
    public void setLogic(String logic) {
        this.logic = logic;
    }
    public List<Object> getVal() {
        return val;
    }
    public void setVal(List<Object> val) {
        this.val = val;
    }
    public String getGroup() {
        return group;
    }
    public void setGroup(String group) {
        this.group = group;
    }
    public String getTableCol() {
        return tableCol;
    }
    public void setTableCol(String tableCol) {
        this.tableCol = tableCol;
    }
}

+ 28 - 0
starter/mysql-starter/src/main/java/com/yihu/mysql/query/ReturnIdPstCreator.java

@ -0,0 +1,28 @@
package com.yihu.mysql.query;
import org.springframework.jdbc.core.PreparedStatementCreator;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
/**
 * @author lincl
 * @version 1.0
 * @created 2016/5/6
 */
public class ReturnIdPstCreator implements PreparedStatementCreator {
    String sql;
    public ReturnIdPstCreator(String sql){
        this.sql = sql;
    }
    @Override
    public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
        return connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
    }
}

+ 303 - 0
starter/mysql-starter/src/main/java/com/yihu/mysql/query/URLHqlQueryParser.java

@ -0,0 +1,303 @@
package com.yihu.mysql.query;
import javafx.util.Pair;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.*;
import org.hibernate.metadata.ClassMetadata;
import org.springframework.util.StringUtils;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * URL 查询串解析器。
 *
 * @author lincl
 * @author Sand
 * @version 1.0
 * @created 2016.02.05 10:17
 */
public class URLHqlQueryParser<T> {
    private String fields;
    private String filters;
    private String orders;
    Session session;
    Class<T> entityCls;
    public URLHqlQueryParser(String fields, String filters, String orders) {
        this.fields = fields;
        this.filters = filters;
        this.orders = orders;
    }
    public URLHqlQueryParser(String filters){
        this.filters = filters;
    }
    public URLHqlQueryParser setSession(Session session) {
        this.session = session;
        return this;
    }
    public URLHqlQueryParser setEntityClass(Class<T> cls) {
        this.entityCls = cls;
        return this;
    }
    /**
     * 生成搜索语句.
     *
     * @return
     */
    public Criteria makeCriteriaQuery() {
        Criteria criteria = session.createCriteria(entityCls);
        ClassMetadata classMetadata = session.getSessionFactory().getClassMetadata(entityCls);
//        makeSelection(criteria, classMetadata);
        makeOrderBy(criteria, classMetadata);
        makeWhere(criteria, classMetadata);
        return criteria;
    }
    /**
     * 生成count语句。
     *
     * @return
     */
    public Criteria makeCriteriaCountQuery() {
        Criteria criteria = session.createCriteria(entityCls);
        ClassMetadata classMetadata = session.getSessionFactory().getClassMetadata(entityCls);
        criteria.setProjection(Projections.rowCount());
        makeWhere(criteria, classMetadata);
        return criteria;
    }
    /**
     * 生成返回值字段。
     *
     * @param criteria
     * @param classMetadata
     */
    private void makeSelection(Criteria criteria, ClassMetadata classMetadata) {
    }
    /**
     * +code 以code字段进行升序排序
     * -code 以code字段进行降序排序
     * 生成排序字段。
     *
     * @param criteria
     * @param classMetadata
     */
    private void makeOrderBy(Criteria criteria, ClassMetadata classMetadata) {
        if (!StringUtils.isEmpty(orders)) {
            String[] orderArray = orders.split(",");
            for(String elem : orderArray){
//                try {
//                    classMetadata.getPropertyType(elem);
//                }catch (Exception e){
//                    throw new IllegalArgumentException("the property not found!");
//                }
                criteria = elem.startsWith("+") ?
                        criteria.addOrder(Order.asc(elem.substring(1)))
                        : criteria.addOrder(Order.desc(elem.substring(1)));
            }
        }
    }
    /**
     * like:使用"?"来表示,如:name?'%医'
     * not in:使用"<>"来表示并用","逗号对值进行分隔,如:status=2,3,4,5
     * in:使用"="来表示并用","逗号对值进行分隔,如:status=2,3,4,5
     * =:使用"="来表示,如:status=2
     * >=:使用大于号和大于等于语法,如:createDate>2012
     * <=:使用小于号和小于等于语法,如:createDate<=2015
     * 分组:在条件后面加上空格,并设置分组号,如:createDate>2012 g1,具有相同组名的条件将使用or连接
     * 多条件组合:使用";"来分隔
     * <p>
     * 生成 where 条件。
     *
     * @param criteria
     * @param classMetadata
     */
    private void makeWhere(Criteria criteria, ClassMetadata classMetadata) {
        if (StringUtils.isEmpty(filters)) return;
        Map<String, List<Criterion>> criterionMap = new HashMap<>();
        String[] filterArray = filters.split(";");
        List<Criterion> groupCriterion = new ArrayList<>();
        for (int i = 0; i < filterArray.length; ++i) {
            String[] tokens = filterArray[i].split(" ");
            if (tokens.length > 2){
                for(int j=1; j<tokens.length; j++){
                    if(j==tokens.length-1)
                        tokens[1] = tokens[j];
                    else
                        tokens[0] += " " + tokens[j] ;
                }
            }
//            if (tokens.length > 2) throw new IllegalArgumentException("无效过滤参数");
            String group = null;
            if (tokens.length >= 2) group = tokens[1];
            Criterion criterion = splitFilter(tokens[0], classMetadata);
            if (group == null)
                group = Integer.toString(i);
            criterionMap.put(group,
                    makeGroupCriterion(criterionMap.get(group), criterion));
        }
        addWhere(criteria, criterionMap);
    }
    private void addWhere(Criteria criteria, Map<String, List<Criterion>> criterionMap) {
        List<Criterion> ls;
        for (String group : criterionMap.keySet()){
            ls = criterionMap.get(group);
            if(ls.size()>1)
                criteria.add(
                        Restrictions.or(ls.toArray(new Criterion[ls.size()]))
                );
            else
                criteria.add(
                        Restrictions.and(ls.toArray(new Criterion[ls.size()]))
                );
        }
    }
    protected List<Criterion> makeGroupCriterion(List<Criterion> ls, Criterion criterion){
        (ls = ls == null ? new ArrayList<>() : ls)
                .add(criterion);
        return ls;
    }
    protected Criterion splitFilter(String filter, ClassMetadata classMetadata) {
        Criterion criterion = null;
        if (filter.contains("?")) {
            Pair<Property, Object> pair = getPair(filter, "[?]", classMetadata);
            criterion = pair.getKey().like("%"+pair.getValue()+"%");
        } else if (filter.contains("<>")) {
            Pair<Property, Object> pair = getPair(filter, "<>", classMetadata);
            if (pair.getValue().getClass().isArray()) {
                criterion = pair.getKey().in((Object[])pair.getValue());
            } else {
                criterion = pair.getKey().eq(pair.getValue());
            }
            criterion = Restrictions.not(criterion);
        }  else if (filter.contains(">=")) {
            Pair<Property, Object> pair = getPair(filter, ">=", classMetadata);
            criterion = pair.getKey().ge(pair.getValue());
        } else if (filter.contains(">")) {
            Pair<Property, Object> pair = getPair(filter, ">", classMetadata);
            //todo:  转成对应类型
            criterion = pair.getKey().gt(pair.getValue());
        } else if (filter.contains("<=")) {
            Pair<Property, Object> pair = getPair(filter, "<=", classMetadata);
            criterion = pair.getKey().le(pair.getValue());
        } else if (filter.contains("<")) {
            Pair<Property, Object> pair = getPair(filter, "<", classMetadata);
            criterion = pair.getKey().lt(pair.getValue());
        } else if (filter.contains("=")) {
            Pair<Property, Object> pair = getPair(filter, "=", classMetadata);
            if (pair.getValue().getClass().isArray()) {
                criterion = pair.getKey().in((Object[])pair.getValue());
            } else {
                criterion = pair.getKey().eq(pair.getValue());
            }
        }
        return criterion;
    }
    protected Pair<Property, Object> getPair(String filter, String splitter, ClassMetadata classMetadata) throws IllegalArgumentException {
        String[] tokens = filter.split(splitter);
        String valStr = tokens[1];
        Object val = tokens[1];
        try {
            if((splitter.equals("=") || splitter.equals("<>")) && valStr.contains(",")){
                val = formatVal(tokens[0], valStr, true);
            }
            else if(!splitter.equals("[?]")){
                val = formatVal(tokens[0], valStr, false);
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return new Pair(Property.forName(tokens[0]), val);
    }
    private Object formatVal(String fileName, String valStr, boolean isArr) throws NoSuchFieldException {
        Object val = "";
        if(isLong(fileName)){
            if(isArr){
                val = strToLongArr(valStr);
            }else
                val = Long.parseLong(valStr);
        }else if(isInteger(fileName)){
            if(isArr){
                val = strToIntArr(valStr);
            }else
                val = Integer.parseInt(valStr);
        }else {
            if(isArr)
                val = valStr.split(",");
            else
                val = valStr;
        }
        return val;
    }
    private Long[] strToLongArr(String valStr){
        String[] strArr = valStr.split(",");
        Long[] longArr = new Long[strArr.length];
        for(int i=0; i<strArr.length; i++){
            longArr[i] = Long.parseLong(strArr[i]);
        }
        return longArr;
    }
    private Integer[] strToIntArr(String valStr){
        String[] strArr = valStr.split(",");
        Integer[] intArr = new Integer[strArr.length];
        for(int i=0; i<strArr.length; i++){
            intArr[i] = Integer.parseInt(strArr[i]);
        }
        return intArr;
    }
    private boolean isInteger(String fieldName) throws NoSuchFieldException {
        Field field = getField(fieldName);
        return field.getType().equals(Integer.class) || field.getType().equals(Integer.TYPE);
    }
    private boolean isLong(String fieldName) throws NoSuchFieldException {
        Field field = getField(fieldName);
        return field.getType().equals(Long.class) || field.getType().equals(Long.TYPE);
    }
    private Field getField(String fieldName) throws NoSuchFieldException {
        Field f;
        try {
            f = entityCls.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            f = entityCls.getSuperclass().getDeclaredField(fieldName);
        }
        return f;
    }
}

+ 275 - 0
starter/mysql-starter/src/main/java/com/yihu/mysql/query/URLQueryParser.java

@ -0,0 +1,275 @@
package com.yihu.mysql.query;
import com.yihu.utils.date.DateUtil;
import javafx.util.Pair;
import org.springframework.util.StringUtils;
import javax.persistence.EntityManager;
import javax.persistence.criteria.*;
import java.text.ParseException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * URL 查询串解析器
 *
 * @author Sand
 * @version 1.0
 * @created 2016.02.05 10:17
 */
public class URLQueryParser<T> {
    private static final Pattern PATTERN = Pattern.compile("[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}");
    private String fields;
    private String filters;
    private String orders;
    private EntityManager entityManager;
    private CriteriaBuilder builder;
    private Class<T> entityCls;
    public URLQueryParser(String fields, String filters, String orders) {
        this.fields = fields;
        this.filters = filters;
        this.orders = orders;
    }
    public URLQueryParser(String filters) {
        this.filters = filters;
    }
    public URLQueryParser setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
        builder = entityManager.getCriteriaBuilder();
        return this;
    }
    public URLQueryParser setEntityClass(Class<T> cls) {
        this.entityCls = cls;
        return this;
    }
    /**
     * 生成搜索语句.
     *
     * @return
     */
    public CriteriaQuery makeCriteriaQuery() throws ParseException {
        CriteriaQuery query = builder.createQuery();
        Root<T> root = query.from(entityCls);
        makeSelection(builder, query, root);
        makeOrderBy(builder, query, root);
        makeWhere(builder, query, root);
        return query;
    }
    /**
     * 生成count语句。
     *
     * @return
     */
    public CriteriaQuery makeCriteriaCountQuery() throws ParseException {
        CriteriaQuery<Long> query = builder.createQuery(Long.class);
        Root<T> root = query.from(entityCls);
        query.select(builder.count(root));
        makeWhere(builder, query, root);
        return query;
    }
    /**
     * 生成返回值字段。
     *
     * @param criteriaBuilder
     * @param query
     * @param root
     */
    private void makeSelection(CriteriaBuilder criteriaBuilder, CriteriaQuery query, Root<T> root) {
        query.select(root);
        /*if (!StringUtils.isEmpty(fields)) {
            String[] fieldArray = fields.split(",");
            List<Selection<T>> selections = new ArrayList<>(fieldArray.length);
            Arrays.stream(fieldArray).forEach(elem -> selections.add(root.get(elem)));
            query.select(criteriaBuilder.tuple(selections.toArray(new Selection[selections.size()])));
        } else {
            query.select(root);
        }*/
    }
    /**
     * +code 以code字段进行升序排序
     * -code 以code字段进行降序排序
     * 生成排序字段。
     *
     * @param criteriaBuilder
     * @param query
     * @param root
     */
    private void makeOrderBy(CriteriaBuilder criteriaBuilder, CriteriaQuery query, Root<T> root) {
        if (!StringUtils.isEmpty(orders)) {
            String[] orderArray = orders.split(",");
            List<Order> orderList = new ArrayList<>(orderArray.length);
            Arrays.stream(orderArray).forEach(
                    elem -> orderList.add(
                            elem.startsWith("+") ?
                                    criteriaBuilder.asc(root.get(elem.substring(1))) : criteriaBuilder.desc(root.get(elem.substring(1)))));
            query.orderBy(orderList);
        }
    }
    /**
     * like:使用"?"来表示,如:name?'%医'
     * in:使用"="来表示并用","逗号对值进行分隔,如:status=2,3,4,5
     * not in:使用"<>"来表示并用","逗号对值进行分隔,如:status=2,3,4,5
     * =:使用"="来表示,如:status=2
     * >=:使用大于号和大于等于语法,如:createDate>2012.01.01 23:59:59
     * <=:使用小于号和小于等于语法,如:createDate<=2015.01.01 23:59:59
     * 分组:在条件后面加上空格,并设置分组号,如:createDate>2012.01.01 23:59:59 g1,具有相同组名的条件将使用or连接 GB/T 2261.2-2003
     * 多条件组合:使用";"来分隔
     * <p/>
     * 生成 where 条件。
     *
     * @param criteriaBuilder
     * @param query
     * @param root
     */
    private void makeWhere(CriteriaBuilder criteriaBuilder, CriteriaQuery query, Root<T> root) throws ParseException {
         if (StringUtils.isEmpty(filters)) {
             return;
         }
        Map<String, Predicate> predicateMap = new HashMap<>();
        String[] filterArray = filters.split(";");
        for (int i = 0; i < filterArray.length; ++i) {
            String filter = filterArray[i];
            //查看是否是时间格式 yyyy-MM-dd hh:mm:ss
            String[] tokens;
            String[] filters = filter.split("[?]|<>|>=|>|<=|<|=");
            Matcher m = PATTERN.matcher(filters[1]);
            if (m.matches()) {
                tokens = new String[]{filter};
            } else {
                tokens = filter.split(" ");
            }
            if (tokens.length > 2){
                for (int j = 1; j < tokens.length; j++){
                    if (j == tokens.length - 1) {
                        tokens[1] = tokens[j];
                    } else {
                        tokens[0] += " " + tokens[j] ;
                    }
                }
            }
            String group = null;
            if (tokens.length >= 2) {
                group = tokens[1];
            }
            Predicate predicate = splitFilter(tokens[0], criteriaBuilder, root);
            if (group != null) {
                if (null == predicateMap.get(group)) {
                    predicateMap.put(group, predicate);
                } else {
                    predicateMap.put(group, criteriaBuilder.or(predicateMap.get(group), predicate));
                }
            } else {
                predicateMap.put(Integer.toString(i), predicate);
            }
        }
        query.where(predicateMap.values().toArray(new Predicate[predicateMap.size()]));
    }
    protected Predicate splitFilter(String filter, CriteriaBuilder cb, Root<T> root) throws ParseException {
        Predicate predicate = null;
        if (filter.contains("?")) {
            Pair<Path, String> pair = getPair(filter, "[?]", root);
            predicate = cb.like(pair.getKey(), "%" + pair.getValue() + "%");
        } else if (filter.contains("<>")) {
            Pair<Path, String> pair = getPair(filter, "<>", root);
            if (pair.getValue().contains(",")) {
                predicate = cb.not(pair.getKey().in(pair.getValue().split(",")));
            } else {
                predicate = cb.notEqual(pair.getKey(), pair.getValue());
            }
        } else if (filter.contains(">=")) {
            Pair<Path, String> pair = getPair(filter, ">=", root);
            String value = pair.getValue();
            if(pair.getKey().getJavaType() == Date.class){
                Date date = DateUtil.strToDate(pair.getValue());
                predicate = cb.greaterThanOrEqualTo(pair.getKey(), date);
            }else {
                predicate = cb.greaterThanOrEqualTo(pair.getKey(),value);
            }
        } else if (filter.contains(">")) {
            Pair<Path, String> pair = getPair(filter, ">", root);
            String value = pair.getValue();
            if(pair.getKey().getJavaType() == Date.class){
                Date date = DateUtil.strToDate(pair.getValue());
                predicate = cb.greaterThan(pair.getKey(), date);
            }else {
                predicate = cb.greaterThan(pair.getKey(),value);
            }
        } else if (filter.contains("<=")) {
            Pair<Path, String> pair = getPair(filter, "<=", root);
            String value = pair.getValue();
            if(pair.getKey().getJavaType() == Date.class){
                Date date = DateUtil.strToDate(pair.getValue());
                predicate = cb.lessThanOrEqualTo(pair.getKey(), date);
            }else {
                predicate = cb.lessThanOrEqualTo(pair.getKey(),value);
            }
        } else if (filter.contains("<")) {
            Pair<Path, String> pair = getPair(filter, "<", root);
            String value = pair.getValue();
            if(pair.getKey().getJavaType() == Date.class){
                Date date = DateUtil.strToDate(pair.getValue());
                predicate = cb.lessThan(pair.getKey(), date);
            }else {
                predicate = cb.lessThan(pair.getKey(),value);
            }
        } else if (filter.contains("=")) {
            Pair<Path, String> pair = getPair(filter, "=", root);
            Set<Object> values = new HashSet<>();
            for (String value : pair.getValue().split(",")) {
                if (pair.getKey().getJavaType().isEnum()) {
                    values.add(Enum.valueOf(pair.getKey().getJavaType(), value));
                } else if (pair.getKey().getJavaType().equals(Boolean.class) ||
                        pair.getKey().getJavaType().equals(Boolean.TYPE)) {
                    values.add(Boolean.valueOf(value));
                } else if(pair.getKey().getJavaType() == Date.class){
                    Date date = DateUtil.strToDate(pair.getValue());
                    values.add(date);
                }else {
                    values.add(value);
                }
            }
            predicate = pair.getKey().in(values);
        }
        return predicate;
    }
    protected Pair<Path, String> getPair(String filter, String splitter, Root<T> root) {
        String[] tokens = filter.split(splitter);
        return new Pair<>(root.get(tokens[0]), tokens[1]);
    }
}

+ 63 - 0
starter/mysql-starter/src/main/java/com/yihu/mysql/query/UpdatePstCallback.java

@ -0,0 +1,63 @@
package com.yihu.mysql.query;
import javafx.util.Pair;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.PreparedStatementCallback;
import java.lang.reflect.Type;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
/**
 * @author lincl
 * @version 1.0
 * @created 2016/5/6
 */
public class UpdatePstCallback implements PreparedStatementCallback<Integer> {
    List<Pair<Type, Object>> values;
    public UpdatePstCallback(List<Pair<Type, Object>> values){
        this.values = values;
    }
    @Override
    public Integer doInPreparedStatement(PreparedStatement preparedStatement) throws SQLException, DataAccessException {
        //设参
        setParams(preparedStatement);
        //执行语句
        preparedStatement.executeUpdate();
        //获取id
        int key = getKey(preparedStatement);
        //关闭
        preparedStatement.close();
        return key;
    }
    private int getKey(PreparedStatement preparedStatement) throws SQLException {
        int autoIncKeyFromApi = -1;
        ResultSet rs = preparedStatement.getGeneratedKeys();
        if (rs.next()) {
            autoIncKeyFromApi = rs.getInt(1);
        }
        rs.close();
        rs = null;
        return autoIncKeyFromApi;
    }
    public PreparedStatement setParams(PreparedStatement pst) throws SQLException {
        int i=1;
        for(Pair<Type, Object> pair : values){
            pst.setObject(i, pair.getValue());
            i++;
        }
        return pst;
    }
}