java map排序 分页_springboot学习笔记5(JPA 实现分页、排序、返回map集合)

本文介绍了SpringBoot集成JPA在数据访问层的简化,展示了如何使用JPA的CurdRepository、PagingAndSortingRepository、JpaRepository等接口进行分页、排序和实例查询。通过自定义查询方法,包括按条件、分页、排序、SQL查询和实例查询。同时,文章还展示了如何自定义基类BaseRepository,实现SQL查询并返回Map集合,以及如何在Controller层调用这些方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在相当长的一段时间里,实现应用程序的数据访问层非常麻烦。必须编写太多的模板代码来执行简单的查询,以及执行分页。Spring  JPA旨在通过减少实际需要的工作量来显著改进数据访问层的实现。作为开发人员,您可以编写存储库接口,包括自定义查找程序方法。下面介绍  springboot集成JPA的使用:

JPA核心接口是Repository,其它所有接口都在此类的基础上进行了扩展。 下面是JPA关系图解图:

33c7e0f63f0f430a488e47423d1944ea.png

熟悉JPA的几个API

CurdRepository提供了增删改产方法,PagingAndSortingRepositroy增加了分页查询方法,JpaRepositroy又增加了实例查询方法。实际应用中可以有选择的继承上面接口即可。上面说过,jpa提供了封装查询数据库模板方法。下面就来一一介绍JPA给我们提供的模板方法:

CurdRepository

接口,提供增删改查基本的功能

@NoRepositoryBean

public interface CrudRepository extends Repository {

S save(S entity);

Iterable save(Iterable entities);

T findOne(ID id);

boolean exists(ID id);

Iterable findAll();

Iterable findAll(Iterable ids);

long count();

void delete(ID id);

void delete(T entity);

void delete(Iterable extends T> entities);

void deleteAll();

}

PagingAndSortingRepositroy

接口 ,分页查询,和排序

@NoRepositoryBean

public interface PagingAndSortingRepository extends CrudRepository {

//分类查询

Iterable findAll(Sort sort);

//分页查询

Page findAll(Pageable pageable);

}

JpaRepositroy

接口,提供实例查询方法

@NoRepositoryBean

public interface JpaRepository

extends PagingAndSortingRepository, QueryByExampleExecutor {

List findAll();

List findAll(Sort sort);

List findAll(Iterable ids);

List save(Iterable entities);

void flush();

S saveAndFlush(S entity);

void deleteInBatch(Iterable entities);

void deleteAllInBatch();

T getOne(ID id);

//实例查询

@Override

List findAll(Example example);

//实例查询,分类排序

@Override

List findAll(Example example, Sort sort);

}

SimpleRepository

实现类,增加了事务注解,进行事务管理,这就不介绍了,讲到自定义封装基类的时候会用到,一般都不会继承使用这个类.

二、使用

自定义一个PersonRepository接口继承上述任何一个接口都可以。不需要在接口上加@Repository注解,也不需要写实现类,即可在service,controller层注入使用,是不是很简洁。对于一般的修改保存操作,只要直接调用JPA接口提供的方法就可以用了,这里就不在介绍了。

entity层

Person实体类:

@Entity

public class Person {

private Integer id;

private String name;

private String password;

.....省略get set方法

}

PersonName接口

如果只需要查询person 中的name ,可以先定义一个接口,这种方式还是比较常用的:

public interface PersonName {

String getName();

}

持久层

PersonRepository 接口

下面介绍了JPA查询方法,条件查询,list集合查询,分页查询,排序查询,sql语句查询,指定字段查询,实例查询,基本上包含了实际开发中所需要的查询方法。

//省略了注释。

public interface PersonRepository extends JpaRepository {

//自定义查询,AND为jpa 关键字,相当于(where x.lastname = ?1 and x.firstname = ?2)

jpa关键字应该都要熟悉

Person findByNameAndPassword(String name ,String password);

//指定字段查询,只返回name

PersonName findById(Integer id);

//排序查询,返回list集合

List findByNameAndPassword(String name ,String password,Sort sort);

//分页查询 查询计算元素总个数总页数,数据多的情况下,代价是昂贵的

Page findByNameAndPassword(String name ,String password,Pageable pageable);

//分页查询,返回的是一个片段,它只知道下一片段或者上一片段是否可用。

Slice findByNameAndPassword(String name,Pageable pageable);

//sql查询。?后面数字,对应方法中参数位置。使用原生sql语句

@Query("select p from person as p where p.name = ?1 and p.password = ?2 ",nativeQuery = true)

Person myfind(String name ,String password);

//实例查询

Person findByExample(Example example)

}

说明: JPA 提供两种查询方式,一种就是直接从方法名中派生中查询(需要遵循它的规范,见下文 JPA 查询语句关键字)上面的例子就是这种方式;另一种就是手动定义查询了(使用JPA 核心类 EntityManager,下文自定义查询会介绍)。

Controller 层

@RestController public class TestController {

@Resource

private PersonRepository personRepository;

@GetMapping(value = "/test")

public String test(Integer personId){

Person p = personRepository.findByNameAndPassword("张三","123");

//排序

List p1 = personRepository.findByNameAndPassword("张三","123",

new Sort(Sort.Direction.ASC,"id"));

//分页

Page p2 = personRepository.findByNameAndPassword("张三",

"123", new PageRequest(1,10,new Sort("id")));

Person tempPerson=new Person();

tempPerson.setId(personId));

//通过实例查询

Person p3= personRepository.findByExample(Example.of(tempPerson))

return p+"+"+ p1 "+"+p2.getTotalElements()+"+"+p3;

}

JPA 查询语句关键字

Keyword

Sample

JPQL snippet

And

findByLastnameAndFirstname

… where x.lastname = ?1 and x.firstname = ?2

Or

findByLastnameOrFirstname

… where x.lastname = ?1 or x.firstname = ?2

Is,Equals

findByFirstname,findByFirstnameIs,findByFirstnameEquals

… where x.firstname = 1?

Between

findByStartDateBetween

… where x.startDate between 1? and ?2

LessThan

findByAgeLessThan

… where x.age < ?1

LessThanEqual

findByAgeLessThanEqual

… where x.age <= ?1

GreaterThan

findByAgeGreaterThan

… where x.age > ?1

GreaterThanEqual

findByAgeGreaterThanEqual

… where x.age >= ?1

After

findByStartDateAfter

… where x.startDate > ?1

Before

findByStartDateBefore

… where x.startDate < ?1

IsNull

findByAgeIsNull

… where x.age is null

IsNotNull,NotNull

findByAge(Is)NotNull

… where x.age not null

Like

findByFirstnameLike

… where x.firstname like ?1

NotLike

findByFirstnameNotLike

… where x.firstname not like ?1

StartingWith

findByFirstnameStartingWith

… where x.firstname like ?1 (parameter bound with appended %)

EndingWith

findByFirstnameEndingWith

… where x.firstname like ?1 (parameter bound with prepended %)

Containing

findByFirstnameContaining

… where x.firstname like ?1 (parameter bound wrapped in %)

OrderBy

findByAgeOrderByLastnameDesc

… where x.age = ?1 order by x.lastname desc

Not

findByLastnameNot

… where x.lastname <> ?1

In

findByAgeIn(Collection ages)

… where x.age in ?1

NotIn

findByAgeNotIn(Collection age)

… where x.age not in ?1

True

findByActiveTrue()

… where x.active = true

False

findByActiveFalse()

… where x.active = false

IgnoreCase

findByFirstnameIgnoreCase

… where UPPER(x.firstame)

自定义查询(返回map集合):

上面的例子都是一些简单的查询,但实际开发中,我们可能会需要用到复杂的sq、连接查询或者需要查询结果只包含我们需要的字段。如果实体之间的关联关系都配置得当的话,JPA提供的方法也可以满足我们的需求。当然我们也可以自定义一个继承JPA的模板类,然后封装查询的方法:

BaseRepository

创建一个BaseRepository ,定义两个sq语句查询:

/**

* repository 基类,封装自定义查询方法

*

* @author

* @date 2017/5/12 8:32

* @Package com.base

* @Version v1.0

*/

@NoRepositoryBean //该注解表示 spring 容器不会创建该对象

public interface BaseRepository extends PagingAndSortingRepository,JpaRepository {

/**

* sql查询

*

* @param sql

* @param args

* @return

*/

List findAllByParams(String sql, Object... args);

/**

* sql分页查询

*

* @param sql

* @param args

* @return

*/

Page findPageByParams(String sql, Pageable pageable, Object... args);

}

BaseRepositoryImpl

BaseRepositoryImpl 类,实现BaseRepository 接口:

/**

* @author

* @date 2017/5/12 8:32

* @Package com.base.impl

* @Version v1.0

*/

public class BaseRepositoryImpl extends SimpleJpaRepository implements BaseRepository {

//实体管理类,对持久化实体做增删改查,自动义sq操作模板所需要的核心类

public final EntityManager entityManager;

public BaseRepositoryImpl(JpaEntityInformation entityInformation, EntityManager entityManager) {

super(entityInformation, entityManager);

this.entityManager = entityManager;

}

@Override

@Transactional(rollbackFor = Exception.class)

public List findAllByParms(String sql, Object... args) {

//获取session

Session session = (Session) entityManager.getDelegate();

org.hibernate.Query q = session.createSQLQuery(sql);

//查询结果转map

q.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);

int i = 0;

for (Object arg : args

) {

q.setParameter(i++, arg);

}

return q.list();

}

@Override

@Transactional(rollbackFor = Exception.class)

public Page findPageByParams(String sql, Pageable pageable, Object... args) {

Session session = (Session) entityManager.getDelegate();

org.hibernate.Query q = session.createSQLQuery(sql);

q.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);

int i = 0;

for (Object arg : args

) {

q.setParameter(i++, arg);

}

List totalCount = q.list();

q.setFirstResult(pageable.getPageSize() * (pageable.getPageNumber() - 1));

q.setMaxResults(pageable.getPageSize());

List pageCount = q.list();

Page pages = new PageImpl<>(pageCount, pageable, totalCount.size());

return pages;

}

}

PersonRepositroy

创建一个PersonRepositroy 继承BaseRepository,就可以直接使用定义的查询方法了:

/**

* @author

* @date 2017/5/12 10:07

* @Package com.repository

* @Version v1.0

*/

public interface PersonRepository extends BaseRepository {

}

TestController

@RestController public class TestController {

@Resource

private PersonRepository personRepository;

@GetMapping(value = "/test")

public String test( ){

//订单表与用户表关联,通过用户ID查询该用户的所有订单,只获取订单编号和订单详情。

String sql="select o.no,o.detail from person as p inner join order as o on o.personid=p.id and p.id= ? "

Integer userId=11;

Page orderLists = personRepository.findPageByParams(sql,new PageRequest(1,10),userId);

return orderLists;

}

}

最后,在项目启动类上加一个注解,告诉springboot,我要使用JPA,请到repository包下去扫描我创建的repository 类,我的repository基类是BaseRepositoryImpl:

@EnableJpaRepositories(basePackages = {"com.repository"}, repositoryBaseClass = BaseRepositoryImpl.class)

public class MybootApplication {

public static void main(String[] args) {

SpringApplication.run(MybootApplication.class, args);

}

}

这样启动项目,就可以进行对数据库访问了。上面的例子主要是解决如何使用sq语句对数据库操作,对于其他情况,大家可以自己尝试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值