1. 程式人生 > >SpringBoot中使用JPA進行復雜查詢

SpringBoot中使用JPA進行復雜查詢

一、使用EntityManager進行復雜查詢

自己寫SQL語句的方式。

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.hibernate.SQLQuery;
import org.hibernate.transform.Transformers;
import org.hibernate.type.IntegerType;
import org.hibernate.type.StringType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; @Component public class EchartsCustomImpl { @Autowired private EntityManager entityManager; /** 查詢省份訪問量資料 **/
private final static String SELECT_CHINA_MAP_SQL = "" + "select " + " taa.num as num, map.province_name as provinceName " + "from ( " + " select " + " sum(pv_count+visitor_count) as num, province_id " + " from area " + " where " + " create_time BETWEEN :startTime and :endTime "
+ " group by province_id " + ") as taa left join province as map on taa.province_id=map.province_id "; public Map<String, Integer> selectChinaMapData(String startTime, String endTime) { Query query = entityManager.createNativeQuery(SELECT_CHINA_MAP_SQL) .setParameter("startTime", startTime) .setParameter("endTime", endTime); query.unwrap(SQLQuery.class) .addScalar("num", IntegerType.INSTANCE) .addScalar("provinceName", StringType.INSTANCE) .setResultTransformer(Transformers.aliasToBean(ChinaMapDto.class)); List<ChinaMapDto> chinaMapDtoList = query.getResultList(); Map<String, Integer> map = new HashMap<>(); if(!CollectionUtils.isEmpty(chinaMapDtoList)) { for (ChinaMapDto chinaMapDto : chinaMapDtoList) { map.put(chinaMapDto.getProvinceName(), chinaMapDto.getNum()); } } return map; } }

二、使用JpaSpecificationExecutor進行復雜查詢

  1. 繼承JpaSpecificationExecutor介面

    @Repository
    public interface ResumeRepository extends JpaRepository<Resume, Integer>, JpaSpecificationExecutor<Resume> {
    }
    
  2. 使用

    import java.util.ArrayList;
    import java.util.List;
    
    import javax.persistence.criteria.CriteriaBuilder;
    import javax.persistence.criteria.CriteriaQuery;
    import javax.persistence.criteria.Predicate;
    import javax.persistence.criteria.Root;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.jpa.domain.Specification;
    import org.springframework.test.context.junit4.SpringRunner;
    import org.springframework.util.StringUtils;
    
    import com.intecwh.hp.domain.entity.Resume;
    import com.intecwh.hp.domain.repository.base.ResumeRepository;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class ApplicationTest {
    	
    	@Autowired
    	private ResumeRepository resumeRepository;
    	
    	@Test
    	public void testJpaSpecificationExecutor() {
    		
    		String empName = "zhangsan";
    		String school = "清華大學";
    		String specName = "計算機";
    		
    		Specification<Resume> specification = new Specification<Resume>() {
    
    			@Override
    			public Predicate toPredicate(Root<Resume> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
    				List<Predicate> list = new ArrayList<Predicate>(); 
    				if(!StringUtils.isEmpty(empName)) {
    					list.add(cb.like(root.get("empName").as(String.class), "%"+empName+"%"));
    				}
    				if(!StringUtils.isEmpty(school)) {
    					list.add(cb.like(root.get("school").as(String.class), school));
    				}
    				if(!StringUtils.isEmpty(specName)) {
    					list.add(cb.like(root.get("specName").as(String.class), specName));
    				}
    				
    				Predicate[] p = new Predicate[list.size()];
    				return cb.or(list.toArray(p));
    			}
    			
    		};
    		
    		List<Resume> resumes = resumeRepository.findAll(specification);
    		System.out.println(resumes);
    	}
    }
    

    參考文章:http://blog.didispace.com/spring-boot-data-jpa-specification/