springboot+jpa+jqueryeasyui重新封装


重新对springboot进行了封装,主要有以下内容:

1、对JpaRepository进行了自定义扩展,业务类的所有数据库访问接口继承BaseDaoIF

BaseBaoFactoryBean.java

package com.mm.happy.dao;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;

import javax.persistence.EntityManager;
import java.io.Serializable;

@SuppressWarnings({ "rawtypes", "unchecked" })
public class BaseBaoFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable> extends JpaRepositoryFactoryBean<R, T, I> {

	public BaseBaoFactoryBean(Class<? extends R> repositoryInterface) {
		super(repositoryInterface);
	}

	@Override
	protected RepositoryFactorySupport createRepositoryFactory(EntityManager em) {
		return new BaseRepositoryFactory(em);
	}

	// 创建一个内部类,该类不用在外部访问
	private static class BaseRepositoryFactory<T, I extends Serializable> extends JpaRepositoryFactory {

		private final EntityManager em;

		public BaseRepositoryFactory(EntityManager em) {
			super(em);
			this.em = em;
		}

		// 设置具体的实现类是BaseRepositoryImple
		@Override
		protected Object getTargetRepository(RepositoryInformation information) {
			return new BaseBaoImpl<T, I>((Class<T>) information.getDomainType(), em);
		}

		// 设置具体的实现类的class
		@Override
		protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
			return BaseBaoImpl.class;
		}
	}
}


BaseBaoImpl.java

package com.mm.happy.dao;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;

import com.mm.happy.utils.StringUtil;

/**
 *自定义扩展dao基类
 */
public class BaseBaoImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements BaseDaoIF<T, ID> {

	private final EntityManager entityManager;

	// 父类没有不带参数的构造方法,这里手动构造父类
	public BaseBaoImpl(Class<T> domainClass, EntityManager entityManager) {
		super(domainClass, entityManager);
		this.entityManager = entityManager;
	}

	// 通过EntityManager来完成查询
	@SuppressWarnings("unchecked")
	@Override
	public List<Object[]> listBySQL(String sql) {
		return entityManager.createNativeQuery(sql).getResultList();
	}

	// 通过EntityManager来完成查询
	@SuppressWarnings("unchecked")
	@Override
	public List listBySQL(String sql, Class<T> domainClass) {
		return entityManager.createNativeQuery(sql, domainClass).getResultList();
	}

	@Override
	public void updateBySql(String sql, Object... args) {
		Query query = entityManager.createNativeQuery(sql);
		int i = 0;
		for (Object arg : args) {
			query.setParameter(++i, arg);
		}
		query.executeUpdate();
	}

	@Override
	public void updateByHql(String hql, Object... args) {
		Query query = entityManager.createQuery(hql);
		int i = 0;
		for (Object arg : args) {
			System.out.println(arg);
			query.setParameter(++i, arg);
		}
		query.executeUpdate();
	}

	/**
	 * 组装查询条件
	 */
	@Override
	public Specification<T> buildSpecification(Map<String, String[]> searchMap, Class<T> domainClass) {
		Specification<T> specification = new Specification<T>() {
			@Override
			public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				// path转化
				List<Predicate> predicates = new ArrayList<>();
				try {
					// 循环取出searchMap的值
					Iterator<Entry<String, String[]>> it = searchMap.entrySet().iterator();
					while (it.hasNext()) {
						Entry<String, String[]> entry = it.next();
						// 值
						String value = entry.getValue()[0];
						// 名称
						String searchfiledName = entry.getKey();
						// search.xxx转换成xxx, // 获取属性的名字
						String name = null;
						String values[] = null;
						// 有区间的时候用"search.s."起始b,"search.e."结束标识
						if (searchfiledName.startsWith("search.s.")) {
							values = new String[2];
							name = searchfiledName.substring(9);
							values[0] = value;
							if (searchMap.get("search.e." + name) != null) {
								values[1] = searchMap.get("search.e." + name)[0];
							}

						} else if (searchfiledName.startsWith("search.e.")) {
							continue;// 上面已经处理,这里直接跳过
						} else {
							if (!StringUtil.isNotBlank(value)) {
								continue;// 不是区间范围的查询,值为空直接跳过
							}
							name = searchfiledName.substring(7);
						}
						Field field = domainClass.getDeclaredField(name);
						// 获取属性类型
						String type = field.getGenericType().toString();
						// 获取查询字段的值,
						if (type.equals("class java.lang.String")) {
							if (values != null && values.length > 1) {
								if (StringUtil.isNotBlank(values[0])) {
									// 大于或等于传入值
									predicates.add(cb.greaterThanOrEqualTo(root.get(name), values[0]));
								}
								if (values.length > 1 && StringUtil.isNotBlank(values[1])) {
									// 小于或等于传入值
									predicates.add(cb.lessThanOrEqualTo(root.get(name), values[1]));
								}
							} else {// 不是区间的情况
								if (searchMap.get("search.equal." + name) != null) {// 配置了精确查询的情况
									predicates.add(cb.equal(root.get(name), value));
								} else {// 默认为模糊查询
									predicates.add(cb.like(root.get(name), "%" + value + "%"));
								}
							}

						} else if (type.equals("class java.util.Date")) {
							if (values != null && values.length > 1) {
								if (StringUtil.isNotBlank(values[0])) {
									// 大于或等于传入时间
									predicates.add(cb.greaterThanOrEqualTo(root.get(name).as(String.class), values[0]));
								}
								if (values.length > 1 && StringUtil.isNotBlank(values[1])) {
									// 小于或等于传入时间
									predicates.add(cb.lessThanOrEqualTo(root.get(name).as(String.class), values[1]));
								}

							} else {// 不是区间的情况
								predicates.add(cb.equal(root.get(name).as(String.class), value));
							}
						} else {
							if (values != null && values.length > 1) {
								if (StringUtil.isNotBlank(values[0])) {
									// 大于或等于传入值
									predicates.add(cb.greaterThanOrEqualTo(root.get(name), values[0]));
								}
								if (values.length > 1 && StringUtil.isNotBlank(values[1])) {
									// 小于或等于传入值
									predicates.add(cb.lessThanOrEqualTo(root.get(name), values[1]));
								}

							} else {// 不是区间的情况
								predicates.add(cb.equal(root.get(name).as(String.class), value));
							}
						}
					}

				} catch (Exception e) {
					e.printStackTrace();
				}
				Predicate[] pre = new Predicate[predicates.size()];
				return query.where(predicates.toArray(pre)).getRestriction();
			}

		};
		return specification;

	}

}

BaseDaoIF.java

package com.mm.happy.dao;

import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.transaction.annotation.Transactional;

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


/**
 * dao扩展接口,子类接口需继承
 * @author zbj
 *
 * @param <T>
 * @param <ID>
 */
@NoRepositoryBean
@Transactional(readOnly=true)
public interface BaseDaoIF<T,ID extends Serializable> extends JpaRepository<T,ID>,JpaSpecificationExecutor<T> {
    //sql语句查询
	public List<Object[]> listBySQL(String sql);
	
	 //sql语句查询
	public List<Object[]> listBySQL(String sql,Class<T> domainClass);
    
	//sql语句更新
    @Transactional
    public void updateBySql(String sql,Object...args);
    
    //sql语句更新
    @Transactional
    public void updateByHql(String hql,Object...args);
   
    //组装查询条件
	public Specification<T> buildSpecification(Map <String, String[]> searchMap,Class<T> domainClass);

    

}

2、查询条件动态组装封装,即页面上增加查询条件,后台代码无需修改

1)前端配置,页面控件的名称以"search."打头,若是区间以"search.s."和“search.e.”打头

<form id="searchForm">
				<table>
					<tr>
						<th>姓:</th>
						<td><input name="search.firstname"  placeholder="精确查询"/><input type="hidden" name="search.equal.firstname" /></td>
						<th>名:</th>
						<td><input name="search.lastname" placeholder="默认模糊查询"/></td>
						<th>id<a></a>:</th>
						<td><input name="search.s.id" /></td>
						<th>-</th>
						<td><input name="search.e.id" /></td>
					</tr>
					
				
					<tr>
						<th>创建时间</th>
						<td><input class="easyui-datetimebox" editable="false" name="search.s.createTime" /></td>
						<!--由于datebox框架上面的数据必须是时间格式的,所以我们用editable="false"来禁止用户手动输入,以免报错-->
						<th>-</th>
						<td><input class="easyui-datetimebox" editable="true" name="search.e.createTime" /></td>
						<td><a class="easyui-linkbutton" href="javascript:void(0);" οnclick="searchFunc();" iconCls="icon-search">查找</a></td>
						<td><a class="easyui-linkbutton" href="javascript:void(0);" οnclick="clearSearch();" iconCls="icon-clear">清空</a></td>
					</tr>
				</table>
			</form>


2)java后台,动态查询条件,放在自定义扩展的BaseDaoIF接口实现中

	/**
	 * 组装查询条件
	 */
	@Override
	public Specification<T> buildSpecification(Map<String, String[]> searchMap, Class<T> domainClass) {
		Specification<T> specification = new Specification<T>() {
			@Override
			public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				// path转化
				List<Predicate> predicates = new ArrayList<>();
				try {
					// 循环取出searchMap的值
					Iterator<Entry<String, String[]>> it = searchMap.entrySet().iterator();
					while (it.hasNext()) {
						Entry<String, String[]> entry = it.next();
						// 值
						String value = entry.getValue()[0];
						// 名称
						String searchfiledName = entry.getKey();
						// search.xxx转换成xxx, // 获取属性的名字
						String name = null;
						String values[] = null;
						// 有区间的时候用"search.s."起始b,"search.e."结束标识
						if (searchfiledName.startsWith("search.s.")) {
							values = new String[2];
							name = searchfiledName.substring(9);
							values[0] = value;
							if (searchMap.get("search.e." + name) != null) {
								values[1] = searchMap.get("search.e." + name)[0];
							}

						} else if (searchfiledName.startsWith("search.e.")) {
							continue;// 上面已经处理,这里直接跳过
						} else {
							if (!StringUtil.isNotBlank(value)) {
								continue;// 不是区间范围的查询,值为空直接跳过
							}
							name = searchfiledName.substring(7);
						}
						Field field = domainClass.getDeclaredField(name);
						// 获取属性类型
						String type = field.getGenericType().toString();
						// 获取查询字段的值,
						if (type.equals("class java.lang.String")) {
							if (values != null && values.length > 1) {
								if (StringUtil.isNotBlank(values[0])) {
									// 大于或等于传入值
									predicates.add(cb.greaterThanOrEqualTo(root.get(name), values[0]));
								}
								if (values.length > 1 && StringUtil.isNotBlank(values[1])) {
									// 小于或等于传入值
									predicates.add(cb.lessThanOrEqualTo(root.get(name), values[1]));
								}
							} else {// 不是区间的情况
								if (searchMap.get("search.equal." + name) != null) {// 配置了精确查询的情况
									predicates.add(cb.equal(root.get(name), value));
								} else {// 默认为模糊查询
									predicates.add(cb.like(root.get(name), "%" + value + "%"));
								}
							}

						} else if (type.equals("class java.util.Date")) {
							if (values != null && values.length > 1) {
								if (StringUtil.isNotBlank(values[0])) {
									// 大于或等于传入时间
									predicates.add(cb.greaterThanOrEqualTo(root.get(name).as(String.class), values[0]));
								}
								if (values.length > 1 && StringUtil.isNotBlank(values[1])) {
									// 小于或等于传入时间
									predicates.add(cb.lessThanOrEqualTo(root.get(name).as(String.class), values[1]));
								}

							} else {// 不是区间的情况
								predicates.add(cb.equal(root.get(name).as(String.class), value));
							}
						} else {
							if (values != null && values.length > 1) {
								if (StringUtil.isNotBlank(values[0])) {
									// 大于或等于传入值
									predicates.add(cb.greaterThanOrEqualTo(root.get(name), values[0]));
								}
								if (values.length > 1 && StringUtil.isNotBlank(values[1])) {
									// 小于或等于传入值
									predicates.add(cb.lessThanOrEqualTo(root.get(name), values[1]));
								}

							} else {// 不是区间的情况
								predicates.add(cb.equal(root.get(name).as(String.class), value));
							}
						}
					}

				} catch (Exception e) {
					e.printStackTrace();
				}
				Predicate[] pre = new Predicate[predicates.size()];
				return query.where(predicates.toArray(pre)).getRestriction();
			}

		};
		return specification;

	}

3)在controller类中调用

/**
	 * 分页获取列表用户数据
	 * @param request
	 * @param response
	 * @param searchCondition
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "get_users", method = RequestMethod.POST)
	public ResponsePage findAll(HttpServletRequest req, HttpServletResponse res) {
		// 初始化设置分页对象
		ResponsePage userResp = initResponsePage(req, res);
		// 查询条件设置
		Specification<ExampleUser> specification = userDao.buildSpecification(getSearchFields(req), ExampleUser.class);
		Page<ExampleUser> userPage = userDao.findAll(specification, new PageRequest(userResp.getPageNo() - 1, userResp.getPageSize(), userResp.getSort()));

		// 查询后再补充设置分页对象
		userResp = setResponsePage(userResp, userPage);
		return userResp;
	}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值