经过多年,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
<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"> <modelVersion>4.0.0</modelVersion> <groupId>org.exam</groupId> <artifactId>testjava</artifactId> <version>1.0.0</version> <name>${project.artifactId}</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring.version>4.2.5.RELEASE</spring.version> <spring-data.version>Hopper-SR1</spring-data.version> <querydsl.version>4.1.1</querydsl.version> <hibernate.version>5.1.0.Final</hibernate.version> <tomcat.version>8.0.32</tomcat.version> <logback.version>1.1.7</logback.version> <mysql.version>5.1.33</mysql.version> <junit.version>4.12</junit.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-framework-bom</artifactId> <version>${spring.version}</version> <scope>import</scope> <type>pom</type> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-releasetrain</artifactId> <version>${spring-data.version}</version> <scope>import</scope> <type>pom</type> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>${java.version}</source> <target>${java.version}</target> </configuration> </plugin> <plugin> <groupId>com.mysema.maven</groupId> <artifactId>maven-apt-plugin</artifactId> <version>1.0.4</version> <executions> <execution> <phase>generate-sources</phase> <goals> <goal>process</goal> </goals> <configuration> <outputDirectory>target/generated-sources</outputDirectory> <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor> </configuration> </execution> </executions> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> </dependency> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-apt</artifactId> <version>${querydsl.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-jpa</artifactId> <version>${querydsl.version}</version> </dependency> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-mongodb</artifactId> <version>${querydsl.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-jdbc</artifactId> <version>${tomcat.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> </dependency> </dependencies> <repositories> <repository> <id>central</id> <name>Central Repository</name> <url>http://repo1.maven.org/maven2</url> <layout>default</layout> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> </project>
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<Employee,String>,QueryDslPredicateExecutor<Employee>{ Collection<Employee> findByIdIn(Collection<String> 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<Employee, String>, QueryDslPredicateExecutor<Employee> { Collection<Employee> findByIdIn(Collection<String> 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<Employee> 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<Employee> 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<UserDTO> findAll(String empName,Pageable pageable) { QEmployee qEmp = QEmployee.employee; QDepartment qDep = QDepartment.department; List<Predicate> 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<UserDTO> content; if (pageable == null || total > pageable.getOffset()) { Map<String, SimpleExpression<?>> 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<UserDTO> 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/
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
我得到了以下数据结构 我正在寻找一个查询dsl谓词,它给我的所有出版物,其中任何Author.name包含某个字符串,例如“汉斯” 我试过了: 但是,如果有多个作者在名称中包含“Hans”,则这是抱怨。有没有像出版一样就像一个集合?
我正在尝试在我的Spring数据服务中使用查询DSL来实现类似于SQL的查询 成员可以是项目或黑客马拉松的成员。项目是黑客马拉松的一部分。我试图找到哈查顿和子项目的所有成员。 因为谓词产生了交叉连接,所以QueryDslPredicateExecutor接口对我不起作用: 我尝试过使用JPAQuery来手动管理连接策略,但是也遇到了同样的问题: Hibernate:选择memberenti0_.i
在任何情况下,我不想重复计数的每一个页面我需要,这个信息是需要的只是第一次调用。
本例子以https://github.com/weiboad/kafka-php作为客户端。使用composer安装时请先看EasySwoole文档中自动加载的章节, 为EasySwoole引入composer。 如何在EasySwoole中添加自定义阻塞进程 EasySwoole支持在beforeWorker事件中添加自定义进程参与swoole底层的事件循环,具体实例代码为: $serv
本文向大家介绍SpringBoot使用Jsp的示例代码,包括了SpringBoot使用Jsp的示例代码的使用技巧和注意事项,需要的朋友参考一下 本文是简单总结一下SpringBoot使用Jsp的Demo。 前言 在早期做项目的时候,JSP是我们经常使用的java服务器页面,其实就是一个简化servlet的设计,在本文开始之前,回顾一下jsp的几大对象,如图。 而在现在SpringBoot框架流行的
我有实体: 和存储库接口: 执行查询时: