> 文章列表 > SpringDataJPA

SpringDataJPA

SpringDataJPA

介绍:

spirng data jpa是spring提供的一套简化JPA开发的框架,按照约定好的规则进行【方法命名】去写dao层接口,就可以在不写接口实现的情况下,实现对数据库的访问和操作。同时提供了很多除了CRUD之外的功能,如分页、排序、复杂查询等等。

Spring Data JPA 让我们解脱了DAO层的操作,基本上所有CRUD都可以依赖于它来实现,在实际的工作工程中,推荐使用Spring Data JPA + ORM(如:hibernate)完成操作,这样在切换不同的ORM框架时提供了极大的方便,同时也使数据库层操作更加简单,方便解耦。

SpringData Jpa 极大简化了数据库访问层代码。 如何简化的呢? 使用了SpringDataJpa,我们的dao层中只需要写接口,就自动具有了增删改查、分页查询等方法。

示例:

pom依赖:

依赖1:

最好在父maven项目中设置spring data统一版本管理依赖: 因为不同的spring data子项目发布时间版本不一样,你自己维护很麻烦, 这样不同的spring data子项目能保证是统一版本

<dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-bom</artifactId><version>2021.1.0</version><scope>import</scope><type>pom</type>
</dependency>

 子项目依赖:

<dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-jpa</artifactId>
</dependency><!-- junit4 -->
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13</version><scope>test</scope>
</dependency>
<!-- hibernate对jpa的支持包 -->
<dependency><groupId>org.hibernate</groupId><artifactId>hibernate-entitymanager</artifactId><version>5.4.32.Final</version>
</dependency><!-- Mysql and MariaDB -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.22</version>
</dependency><!--连接池-->
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.8</version>
</dependency><!--spring-test -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.3.10</version><scope>test</scope>
</dependency>

javaconfig:

@Configuration          // 标记当前类为配置类   =xml配文件
//@EnableJpaRepositories(basePackages="com.tuling.repositories")  // 启动jpa    <jpa:repositories
@EnableTransactionManagement    // 开启事务
public class SpringDataJPAConfig {/**  <!--数据源--><bean class="com.alibaba.druid.pool.DruidDataSource" name="dataSource"><property name="username" value="root"/><property name="password" value="123456"/><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/springdata_jpa?characterEncoding=UTF-8"/></bean>* */@Beanpublic DataSource dataSource() {DruidDataSource dataSource = new DruidDataSource();dataSource.setUsername("root");dataSource.setPassword("123456");dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/springdata_jpa?characterEncoding=UTF-8");return  dataSource;}/**  <!--EntityManagerFactory--><bean name="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"><property name="jpaVendorAdapter"><!--Hibernate实现--><bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"><!--生成数据库表--><property name="generateDdl" value="true"></property><property name="showSql" value="true"></property></bean></property><!--设置实体类的包--><property name="packagesToScan" value="com.tuling.pojo"></property><property name="dataSource" ref="dataSource" ></property></bean>* */@Beanpublic LocalContainerEntityManagerFactoryBean entityManagerFactory() {HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();vendorAdapter.setGenerateDdl(true);vendorAdapter.setShowSql(true);LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();factory.setJpaVendorAdapter(vendorAdapter);factory.setPackagesToScan("com.tuling.pojo");factory.setDataSource(dataSource());return factory;}/** <bean class="org.springframework.orm.jpa.JpaTransactionManager" name="transactionManager"><property name="entityManagerFactory" ref="entityManagerFactory"></property></bean>* */@Beanpublic PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {JpaTransactionManager txManager = new JpaTransactionManager();txManager.setEntityManagerFactory(entityManagerFactory);return txManager;}}

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/data/jpahttps://www.springframework.org/schema/data/jpa/spring-jpa.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"><!--用于整合jpa  @EnableJpaRepositories --><jpa:repositories base-package="com.tuling.repositories"entity-manager-factory-ref="entityManagerFactory"transaction-manager-ref="transactionManager"/><!--EntityManagerFactory--><bean name="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"><property name="jpaVendorAdapter"><!--Hibernate实现--><bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"><!--生成数据库表--><property name="generateDdl" value="true"></property><property name="showSql" value="true"></property></bean></property><!--设置实体类的包--><property name="packagesToScan" value="com.tuling.pojo"></property><property name="dataSource" ref="dataSource" ></property></bean><!--数据源--><bean class="com.alibaba.druid.pool.DruidDataSource" name="dataSource"><property name="username" value="root"/><property name="password" value="123456"/><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/springdata_jpa?characterEncoding=UTF-8"/></bean><!--声明式事务--><bean class="org.springframework.orm.jpa.JpaTransactionManager" name="transactionManager"><property name="entityManagerFactory" ref="entityManagerFactory"></property></bean><!--启动注解方式的声明式事务--><tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven><context:component-scan base-package="com.tuling"></context:component-scan></beans>

pojo实体类:

@Entity     // 作为hibernate 实体类
@Table(name = "tb_customer")       // 映射的表明
public class Customer {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(name = "id")private Long custId; //客户的主键@Column(name = "cust_name")private String custName;//客户名称@Column(name="cust_address")private String custAddress;//客户地址public Long getCustId() {return custId;}public void setCustId(Long custId) {this.custId = custId;}public String getCustName() {return custName;}public void setCustName(String custName) {this.custName = custName;}public String getCustAddress() {return custAddress;}public void setCustAddress(String custAddress) {this.custAddress = custAddress;}@Overridepublic String toString() {return "Customer{" +"custId=" + custId +", custName='" + custName + '\\'' +", custAddress='" + custAddress + '\\'' +"}\\n";}
}

customerRepository:

public interface CustomerRepository extends CrudRepository<Customer,Long>{
// public interface CustomerRepository extends PagingAndSortingRepository<Customer,Long>{}

测试:

//@ContextConfiguration("/spring.xml")
@ContextConfiguration(classes = SpringDataJPAConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringdataJpaTest {// jdk动态代理的实例@AutowiredCustomerRepository repository;@Testpublic  void testR(){Optional<Customer> byId = repository.findById(20L);System.out.println(byId.orElse(null));}@Testpublic  void testC(){Customer customer = new Customer();customer.setCustName("李四");System.out.println(repository.save(customer));}@Testpublic  void testD(){Customer customer = new Customer();customer.setCustId(3L);customer.setCustName("李四");repository.delete(customer);}@Testpublic  void testFindAll(){Iterable<Customer> allById = repository.findAllById(Arrays.asList(1L, 7L, 8L));System.out.println(allById);}
}

CrudRepository与PagingAndSortingRepository区别:

PagingAndSortingRepository更全,除了CrudRepository的东西,里面包含分页。

 

 PagingAndSortingRepository的实例测试:

@ContextConfiguration(classes = SpringDataJPAConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringDataJpaPagingAndSortTest
{// jdk动态代理的实例@AutowiredCustomerRepository repository;@Testpublic  void testPaging(){Page<Customer> all = repository.findAll(PageRequest.of(0, 2));System.out.println(all.getTotalPages());System.out.println(all.getTotalElements());System.out.println(all.getContent());}@Testpublic  void testSort(){Sort sort = Sort.by("custId").descending();Iterable<Customer> all = repository.findAll(sort);System.out.println(all);}@Testpublic  void testSortTypeSafe(){Sort.TypedSort<Customer> sortType = Sort.sort(Customer.class);Sort sort = sortType.by(Customer::getCustId).descending();Iterable<Customer> all = repository.findAll(sort);System.out.println(all);}
}

自定义操作

jpql(原生sql):

a. @Query

i. 查询如果返回单个实体 就用pojo接收 , 如果是多个需要通过集合

ii. 参数设置方式1. 索引 : ?数字2. 具名: :参数名 结合@Param注解指定参数名字

iii. 增删改:1. 要加上事务的支持:2. 如果是插入方法:一定只能在hibernate下才支持 (Insert into..select )

@Transactional

@Modifying // 通知springdatajpa 是增删改的操作

CustomerRepository:

public interface CustomerRepository extends PagingAndSortingRepository<Customer,Long>{
//public interface CustomerRepository extends CrudRepository<Customer,Long>{// 增删查改// 查询@Query("FROM Customer where custName=:custName ")List<Customer> findCustomerByCustName(@Param("custName") String custName);// 修改@Transactional@Modifying   // 通知springdatajpa 是增删改的操作@Query("UPDATE Customer c set c.custName=:custName where c.custId=:id")int updateCustomer(@Param("custName") String custName,@Param("id")Long id);@Transactional@Modifying   // 通知springdatajpa 是增删改的操作@Query("DELETE FROM Customer c where c.custId=?1")int deleteCustomer(Long id);// 新增  JPQL@Transactional@Modifying   // 通知springdatajpa 是增删改的操作@Query("INSERT INTO Customer (custName) SELECT c.custName FROM Customer c where c.custId=?1")int insertCustomerBySelect(Long id);@Query(value="select * FROM tb_customer where cust_name=:custName ",nativeQuery = true)List<Customer> findCustomerByCustNameBySql(@Param("custName") String custName);
}

 测试:

@ContextConfiguration(classes = SpringDataJPAConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class JpqlTest {// jdk动态代理的实例@AutowiredCustomerRepository repository;@Testpublic  void testR(){List<Customer> customer = repository.findCustomerByCustName("李四");System.out.println(customer);}@Testpublic  void testU(){int result = repository.updateCustomer("王五", 7L);System.out.println(result);}@Testpublic  void testD(){int result = repository.deleteCustomer(10L);System.out.println(result);}@Testpublic  void testC(){int result = repository.insertCustomerBySelect(7L);System.out.println(result);}@Testpublic  void testR_sql(){List<Customer> customer = repository.findCustomerByCustNameBySql("徐庶");System.out.println(customer);}
}

规定方法名:

支持的查询方法主题关键字(前缀)

决定当前方法作用

只支持查询 和删除

支持的查询方法谓词关键字和修饰符

决定查询条件

 

 CustomerMethodNameRepository::

public interface CustomerMethodNameRepository extends PagingAndSortingRepository<Customer,Long> {List<Customer> findByCustName(String custName);boolean existsByCustName(String custName);@Transactional@Modifyingint deleteByCustId(Long custName);List<Customer> findByCustNameLike(String custName);}

测试:

@ContextConfiguration(classes = SpringDataJPAConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class MethodNameTest {// jdk动态代理的实例@AutowiredCustomerMethodNameRepository repository;@Testpublic  void test01() {List<Customer> list = repository.findByCustName("李四");System.out.println(list);}@Testpublic  void test02() {boolean exists = repository.existsByCustName("xxx");System.out.println(exists);}@Testpublic  void test03() {int exists = repository.deleteByCustId(12L);System.out.println(exists);}@Testpublic  void test04() {List<Customer> list = repository.findByCustNameLike("徐%");System.out.println(list);}
}

Query by Example:

只支持查询:

i. 不支持嵌套或分组的属性约束,如 firstname = ?0 or (firstname = ?1and lastname = ?2).

ii. 只支持字符串 start/contains/ends/regex 匹配和其他属性类型的精确匹配。

实现:将Repository继承QueryByExampleExecutor

实例:

CustomerQBERepository:

public interface CustomerQBERepositoryextends PagingAndSortingRepository<Customer,Long>, QueryByExampleExecutor<Customer> {
}

测试:

@ContextConfiguration(classes = SpringDataJPAConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class QBETest {// jdk动态代理的实例@AutowiredCustomerQBERepository repository;/*** 简单实例  客户名称  客户地址动态查询*/@Testpublic  void test01(){// 查询条件Customer customer=new Customer();customer.setCustName("徐庶");customer.setCustAddress("BEIJING");// 通过Example构建查询条件Example<Customer> example = Example.of(customer);List<Customer> list = (List<Customer>) repository.findAll(example);System.out.println(list);}/***  通过匹配器 进行条件的限制* 简单实例  客户名称  客户地址动态查询*/@Testpublic  void test02(){// 查询条件Customer customer=new Customer();customer.setCustName("庶");customer.setCustAddress("JING");// 通过匹配器 对条件行为进行设置ExampleMatcher matcher = ExampleMatcher.matching()//.withIgnorePaths("custName")       // 设置忽略的属性//.withIgnoreCase("custAddress")      // 设置忽略大小写//.withStringMatcher(ExampleMatcher.StringMatcher.ENDING);    // 对所有条件字符串进行了结尾匹配.withMatcher("custAddress",m -> m.endsWith().ignoreCase());      // 针对单个条件进行限制, 会使withIgnoreCase失效,需要单独设置//.withMatcher("custAddress", ExampleMatcher.GenericPropertyMatchers.endsWith().ignoreCase());// 通过Example构建查询条件Example<Customer> example = Example.of(customer,matcher);List<Customer> list = (List<Customer>) repository.findAll(example);System.out.println(list);}
}

Specifications:

在之前使用Query by Example只能针对字符串进行条件设置,那如果希望对所有类型支持,可以使用Specifications

实例:

实现:将Repository继承JpaSpecificationExecutor

CustomerSpecificationsRepository:

public interface CustomerSpecificationsRepositoryextends PagingAndSortingRepository<Customer,Long>,JpaSpecificationExecutor<Customer> {}

Root:查询哪个表(关联查询) = from

CriteriaQuery:查询哪些字段,排序是什么 =组合(order by . where )

CriteriaBuilder:条件之间是什么关系,如何生成一个查询条件,每一个查询条件都是什么类型(>between in...) = where

Predicate(Expression): 每一条查询条件的详细描述

@ContextConfiguration(classes = SpringDataJPAConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class SpecificationTest {// jdk动态代理的实例@AutowiredCustomerSpecificationsRepository repository;@Testpublic  void testR(){List<Customer> customer = repository.findAll(new Specification<Customer>() {@Overridepublic Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {// root from Customer  , 获取列// CriteriaBuilder where 设置各种条件  (> < in ..)// query  组合(order by , where)return null;}});System.out.println(customer);}/*** 查询客户范围 (in)* id  >大于* 地址  精确*/@Testpublic  void testR2(){List<Customer> customer = repository.findAll(new Specification<Customer>() {@Overridepublic Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {// root from Customer  , 获取列// CriteriaBuilder where 设置各种条件  (> < in ..)// query  组合(order by , where)Path<Object> custId = root.get("custId");Path<Object> custName = root.get("custName");Path<Object> custAddress = root.get("custAddress");// 参数1 :为哪个字段设置条件   参数2:值Predicate predicate = cb.equal(custAddress, "BEIJING");return predicate;}});System.out.println(customer);}/*** 查询客户范围 (in)* id  >大于* 地址  精确*/@Testpublic  void testR3(){List<Customer> customer = repository.findAll(new Specification<Customer>() {@Overridepublic Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {// root from Customer  , 获取列// CriteriaBuilder where 设置各种条件  (> < in ..)// query  组合(order by , where)Path<Long> custId = root.get("custId");Path<String> custName = root.get("custName");Path<String> custAddress = root.get("custAddress");// 参数1 :为哪个字段设置条件   参数2:值Predicate custAddressP = cb.equal(custAddress, "BEIJING");Predicate custIdP = cb.greaterThan(custId, 0L);CriteriaBuilder.In<String> in = cb.in(custName);in.value("徐庶").value("王五");Predicate and = cb.and(custAddressP, custIdP,in);return and;}});System.out.println(customer);}/*** 查询客户范围 (in)* id  >大于* 地址  精确*/@Testpublic  void testR4(){Customer params=new Customer();//params.setCustAddress("BEIJING");params.setCustId(0L);params.setCustName("徐庶,王五");List<Customer> customer = repository.findAll(new Specification<Customer>() {@Overridepublic Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {// root from Customer  , 获取列// CriteriaBuilder where 设置各种条件  (> < in ..)// query  组合(order by , where)// 1. 通过root拿到需要设置条件的字段Path<Long> custId = root.get("custId");Path<String> custName = root.get("custName");Path<String> custAddress = root.get("custAddress");// 2. 通过CriteriaBuilder设置不同类型条件List<Predicate> list=new ArrayList<>();if(!StringUtils.isEmpty(params.getCustAddress())) {// 参数1 :为哪个字段设置条件   参数2:值list.add(cb.equal(custAddress, "BEIJING")) ;}if(params.getCustId()>-1){list.add(cb.greaterThan(custId, 0L));}if(!StringUtils.isEmpty(params.getCustName())) {CriteriaBuilder.In<String> in = cb.in(custName);in.value("徐庶").value("王五");list.add(in);}// 组合条件Predicate and = cb.and(list.toArray(new Predicate[list.size()]));return and;}});System.out.println(customer);}@Testpublic  void testR5(){Customer params=new Customer();//params.setCustAddress("BEIJING");params.setCustId(0L);params.setCustName("徐庶,王五");List<Customer> customer = repository.findAll(new Specification<Customer>() {@Overridepublic Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {// root from Customer  , 获取列// CriteriaBuilder where 设置各种条件  (> < in ..)// query  组合(order by , where)Path<Long> custId = root.get("custId");Path<String> custName = root.get("custName");Path<String> custAddress = root.get("custAddress");// 参数1 :为哪个字段设置条件   参数2:值List<Predicate> list=new ArrayList<>();if(!StringUtils.isEmpty(params.getCustAddress())) {list.add(cb.equal(custAddress, "BEIJING")) ;}if(params.getCustId()>-1){list.add(cb.greaterThan(custId, 0L));}if(!StringUtils.isEmpty(params.getCustName())) {CriteriaBuilder.In<String> in = cb.in(custName);in.value("徐庶").value("王五");list.add(in);}Predicate and = cb.and(list.toArray(new Predicate[list.size()]));Order desc = cb.desc(custId);return query.where(and).orderBy(desc).getRestriction();}});System.out.println(customer);}
}

限制:不能分组、聚合函数, 需要自己通过entityManager玩

Querydsl:

QueryDSL是基于ORM框架或SQL平台上的一个通用查询框架。借助QueryDSL可以在任何支持的ORM框架或SQL平台上以通用API方式构建查询。

JPA是QueryDSL的主要集成技术,是JPQL和Criteria查询的代替方法。目前QueryDSL支持的平台包括JPA,JDO,SQL,Mongodb 等等。。。

Querydsl扩展能让我们以链式方式代码编写查询方法。该扩展需要一个接口QueryDslPredicateExecutor,它定义了很多查询方法。

实例:

引入依赖:

<properties><querydsl.version>4.4.0</querydsl.version><apt.version>1.1.3</apt.version>
</properties><!-- querydsl -->
<dependency><groupId>com.querydsl</groupId><artifactId>querydsl-jpa</artifactId><version>${querydsl.version}</version>
</dependency>

添加 maven 插件:

这个插件是为了让程序自动生成query type(查询实体,命名方式为:"Q"+对应实体名)。

<build><plugins><plugin><groupId>com.mysema.maven</groupId><artifactId>apt-maven-plugin</artifactId><version>${apt.version}</version><dependencies><dependency><groupId>com.querydsl</groupId><artifactId>querydsl-apt</artifactId><version>${querydsl.version}</version></dependency></dependencies><executions><execution><phase>generate-sources</phase><goals><goal>process</goal></goals><configuration><outputDirectory>target/generated-sources/queries</outputDirectory><processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor><logOnlyOnError>true</logOnlyOnError></configuration></execution></executions></plugin></plugins>
</build>

执行mvn compile之后,可以找到该target/generated-sources/java,然后IDEA标示为源代码目录即可.

 CustomerQueryDSLRepository:

public interface CustomerQueryDSLRepository extendsPagingAndSortingRepository<Customer,Long>, QuerydslPredicateExecutor<Customer> {}

测试类:

@ContextConfiguration(classes = SpringDataJPAConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class QueryDSLTest {// jdk动态代理的实例@AutowiredCustomerQueryDSLRepository repository;@Testpublic  void test01() {QCustomer customer = QCustomer.customer;// 通过Id查找BooleanExpression eq = customer.custId.eq(1L);System.out.println(repository.findOne(eq));}/*** 查询客户名称范围 (in)* id  >大于* 地址  精确*/@Testpublic  void test02() {QCustomer customer = QCustomer.customer;// 通过Id查找BooleanExpression and = customer.custName.in("徐庶", "王五").and(customer.custId.gt(0L))  //大于.and(customer.custAddress.eq("BEIJING"));System.out.println(repository.findOne(and));}/*** 查询客户名称范围 (in)* id  >大于* 地址  精确*/@Testpublic  void test03() {Customer params=new Customer();params.setCustAddress("BEIJING");params.setCustId(0L);params.setCustName("徐庶,王五");QCustomer customer = QCustomer.customer;// 初始条件 类似于1=1 永远都成立的条件BooleanExpression expression = customer.isNotNull().or(customer.isNull());expression=params.getCustId()>-1?expression.and(customer.custId.gt(params.getCustId())):expression;expression=!StringUtils.isEmpty( params.getCustName())?expression.and(customer.custName.in(params.getCustName().split(","))):expression;expression=!StringUtils.isEmpty( params.getCustAddress())?expression.and(customer.custAddress.eq(params.getCustAddress())):expression;System.out.println(repository.findAll(expression));}// 解决线程安全问题   autowire装配会有 线程安全问题@PersistenceContextEntityManager em;/*** 自定义列查询、分组* 需要使用原生态的方式(Specification)* 通过Repository进行查询, 列、表都是固定*/@Testpublic  void test04() {JPAQueryFactory factory = new JPAQueryFactory(em);QCustomer customer = QCustomer.customer;// 构建基于QueryDSL的查询JPAQuery<Tuple> tupleJPAQuery = factory.select(customer.custId, customer.custName).from(customer).where(customer.custId.eq(1L)).orderBy(customer.custId.desc());// 执行查询List<Tuple> fetch = tupleJPAQuery.fetch();// 处理返回数据for (Tuple tuple : fetch) {System.out.println(tuple.get(customer.custId));System.out.println(tuple.get(customer.custName));}}@Testpublic  void test05() {JPAQueryFactory factory = new JPAQueryFactory(em);QCustomer customer = QCustomer.customer;// 构建基于QueryDSL的查询JPAQuery<Long> longJPAQuery = factory.select(customer.custId.sum()).from(customer)//.where(customer.custId.eq(1L)).orderBy(customer.custId.desc());// 执行查询List<Long> fetch = longJPAQuery.fetch();// 处理返回数据for (Long sum : fetch) {System.out.println(sum);}}
}