springData使用QueryDsl的示例代码

经过多年,spring data jpa越来越完善,在版本迭代的过程中,会不断增加功能,今天看新的reference发现有Querydsl.然后搜索到上面的参考资料2

无论是JpaSpecificationExecutor,还是QueryDslPredicateExecutor,它俩都提供了使用Predicate(意义相同,都是构建where子句;类不同,javax.persistence.criteria.Predicate,com.querydsl.core.types.Predicate)去构建查询,使用比较方便.

关于两者的简单使用,上面的参考资料2有介绍.文末也有总结,从概括来看,我个人认为应倾向使用QueryDslPredicateExecutor,QueryDsl不仅适用于JPA repositories,还支持MongoDB.

下面是个例子

1.pom.xml


  4.0.0
  org.exam
  testjava
  1.0.0
  ${project.artifactId}
  
    UTF-8
    UTF-8
    1.8
    4.2.5.RELEASE
    Hopper-SR1
    4.1.1
    5.1.0.Final
    8.0.32
    1.1.7
    5.1.33
    4.12
  
  
    
      
        org.springframework
        spring-framework-bom
        ${spring.version}
        import
        pom
      
      
        org.springframework.data
        spring-data-releasetrain
        ${spring-data.version}
        import
        pom
      
    
  
  
    
      
        org.apache.maven.plugins
        maven-compiler-plugin
        3.1
        
          ${java.version}
          ${java.version}
        
      
      
        com.mysema.maven
        maven-apt-plugin
        1.0.4
        
          
            generate-sources
            
              process
            
            
              target/generated-sources
              com.querydsl.apt.jpa.JPAAnnotationProcessor
            
          
        
      
    
  
  
    
      org.springframework.data
      spring-data-jpa
    
    
      org.springframework.data
      spring-data-mongodb
    
    
      com.querydsl
      querydsl-apt
      ${querydsl.version}
      provided
    
    
      com.querydsl
      querydsl-jpa
      ${querydsl.version}
    
    
      com.querydsl
      querydsl-mongodb
      ${querydsl.version}
    
    
      org.hibernate
      hibernate-entitymanager
      ${hibernate.version}
    
    
      org.apache.tomcat
      tomcat-jdbc
      ${tomcat.version}
    
    
      org.springframework
      spring-test
    
    
      ch.qos.logback
      logback-classic
      ${logback.version}
    
    
      mysql
      mysql-connector-java
      ${mysql.version}
    
    
      junit
      junit
      ${junit.version}
    
  

  
    
      central
      Central Repository
      http://repo1.maven.org/maven2
      default
      
        false
      
    
  

2.Domain类

package org.exam.domain;

import org.springframework.data.mongodb.core.mapping.Document;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.io.Serializable;

@Entity
@Document
public class Employee implements Serializable {
  @Id
  @Column(length = 38)
  private String id;
  @Column(length = 32)
  private String name;
  private long salary;
  private long departmentId;
  //setter和getter略
}

3.Repository类

package org.exam.repository.jpa;
import org.exam.domain.Employee;
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.Collection;
public interface JpaEmployeeRepository extends PagingAndSortingRepository,QueryDslPredicateExecutor{
  Collection findByIdIn(Collection ids);
}
package org.exam.repository.mongo;

import org.exam.domain.Employee;
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.Collection;
public interface MongoEmployeeRepository extends PagingAndSortingRepository, QueryDslPredicateExecutor {
  Collection findByIdIn(Collection ids);
}

JPA有JpaRepository,MongoDB有MongoRepository,它俩都继承PagingAndSortingRepository

3.配置类

package org.exam.config;

import com.mongodb.MongoClient;
import com.mongodb.WriteConcern;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.data.mongodb.core.WriteResultChecking;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.annotation.Resource;
import java.net.UnknownHostException;
import java.util.Properties;

@Configuration
@PropertySource("classpath:config.properties")
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "org.exam.repository.jpa")
@EnableMongoRepositories(basePackages = "org.exam.repository.mongo")
public class AppConfig {
  @Resource
  private Environment env;

  @Bean(destroyMethod = "close")
  public DataSource dataSource() {
    DataSource dataSource = new DataSource();
    dataSource.setDriverClassName(env.getProperty("ds.driverClassName"));
    dataSource.setUrl(env.getProperty("ds.url"));
    dataSource.setUsername(env.getProperty("ds.username"));
    dataSource.setPassword(env.getProperty("ds.password"));
    dataSource.setInitialSize(env.getProperty("ds.initialSize", Integer.class));
    dataSource.setMinIdle(env.getProperty("ds.minIdle", Integer.class));
    dataSource.setMaxIdle(env.getProperty("ds.maxIdle", Integer.class));
    dataSource.setMaxActive(env.getProperty("ds.maxActive", Integer.class));
    return dataSource;
  }

  @Bean
  public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
    jpaVendorAdapter.setDatabase(Database.valueOf(env.getProperty("jpa.database")));
    jpaVendorAdapter.setGenerateDdl(env.getProperty("jpa.generateDdl",Boolean.class));
    jpaVendorAdapter.setShowSql(env.getProperty("jpa.showSql",Boolean.class));
    LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
    emf.setDataSource(dataSource());
    emf.setPackagesToScan("org.exam.domain");
    emf.setJpaVendorAdapter(jpaVendorAdapter);
    Properties properties = new Properties();
    properties.setProperty("hibernate.default_schema", env.getProperty("jpa.defaultSchema"));
    emf.setJpaProperties(properties);
    return emf;
  }

  @Bean
  public PlatformTransactionManager transactionManager() {
    return new JpaTransactionManager(entityManagerFactory().getObject());
  }

  @Bean
  public MongoDbFactory mongoDbFactory() throws UnknownHostException {
    return new SimpleMongoDbFactory(new MongoClient(env.getProperty("mongo.host"), env.getProperty("mongo.port", Integer.class)), env.getProperty("mongo.db"));
  }

  @Bean
  public MongoTemplate mongoTemplate() throws UnknownHostException {
    MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory());
    mongoTemplate.setWriteResultChecking(WriteResultChecking.EXCEPTION);
    mongoTemplate.setWriteConcern(WriteConcern.NORMAL);
    return mongoTemplate;
  }
}

4.测试类

package org.exam.repository.jpa;

import org.exam.config.AppConfig;
import org.exam.domain.Employee;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import org.springframework.transaction.annotation.Transactional;

import java.util.UUID;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = {AppConfig.class})
@Transactional(transactionManager = "transactionManager")//Rollback默认为true
public class JpaEmployeeRepositoryTest {
  @Autowired
  private JpaEmployeeRepository jpaEmployeeRepository;

  @Test
  @Rollback(false)
  public void testSave() {
    for (int i = 0; i < 5; i++) {
      Employee employee = new Employee();
      employee.setId(UUID.randomUUID().toString());
      employee.setName("name");
      employee.setDepartmentId(1 + i);
      employee.setSalary(6800 + i);
      jpaEmployeeRepository.save(employee);
    }
  }

  @Test
  public void testFindAll() {
    Page all = jpaEmployeeRepository.findAll(null, new PageRequest(0, 8));
    for (Employee employee : all) {
      System.out.println("employee = " + employee);
    }
  }
}
package org.exam.repository.mongo;
import com.mongodb.MongoClient;
import org.exam.config.AppConfig;
import org.exam.domain.Employee;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.geo.Circle;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import java.net.UnknownHostException;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = {AppConfig.class})
public class MongoEmployeeRepositoryTest {
  @Autowired
  private MongoEmployeeRepository mongoEmployeeRepository;

  public static void main(String[] args) throws UnknownHostException {
    MongoTemplate template = new MongoTemplate(new MongoClient("127.0.0.1", 27017), "test");
    Circle circle = new Circle(-73.99171, 40.738868, 0.01);

    System.out.println();
  }

  @Test
  public void testFindAll() {
    Page all = mongoEmployeeRepository.findAll(null, new PageRequest(0, 8));
    for (Employee employee : all) {
      System.out.println("employee = " + employee);
    }
  }
}

5.其它config.properties,logback.xml文件不太重要,篇幅关系就省略.

源码下载

再了解一下比较大的需求,从几张表来取几个字段的数据,返回分页排序数据.

1.在AppConfig注册JPAQueryFactory Bean

@Bean
public JPAQueryFactory jpaQueryFactory(EntityManager entityManager) {
  return new JPAQueryFactory(new HQLTemplates(), entityManager);
}

2.建一个DTO(数据传输对象)

public class UserDTO {
  private String empName;
  private String deptName;
  private long salary;
  //setter,getter略
}

3.查询例子测试

private Page findAll(String empName,Pageable pageable) {
  QEmployee qEmp = QEmployee.employee;
  QDepartment qDep = QDepartment.department;
  List criteria = new ArrayList<>();
  if (StringUtils.hasText(empName)){
    criteria.add(qEmp.name.eq(empName.trim()));
  }

  JPAQuery query = jpaQueryFactory.from(qEmp).innerJoin(qDep).on(qEmp.deptId.eq(qDep.id)).where(criteria.toArray(new Predicate[criteria.size()]));
  long total = query.fetchCount();
  List content;
  if (pageable == null || total > pageable.getOffset()) {
    Map> map = new HashMap<>();
    map.put("deptName", qDep.name);
    map.put("empName", qEmp.name);
    map.put("salary", qEmp.salary);
    content = QuerydslUtils.applyPagination(pageable, query).select(Projections.bean(UserDTO.class, map)).fetch();
  } else {
    content = Collections.emptyList();
  }
  return new PageImpl<>(content, pageable, total);
}

@Test
public void test() {
  Pageable pageable = new PageRequest(0, 10, new QSort(new OrderSpecifier<>(Order.DESC, QEmployee.employee.salary), new OrderSpecifier<>(Order.ASC, QDepartment.department.name)));
  Page page = findAll("name", pageable);
  for (UserDTO userDTO : page) {
    System.out.println("userDTO = " + userDTO);
  }
}

参考资料

1:http://docs.spring.io/spring-data/jpa/docs/1.10.x/reference/pdf/spring-data-jpa-reference.pdf

2:https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

你可能感兴趣的:(springData使用QueryDsl的示例代码)