springboot学习笔记5(JPA 实现分页、排序、返回map集合)
2017-09-06 20:07
435 查看
前言
在相当长的一段时间里,实现应用程序的数据访问层非常麻烦。必须编写太多的模板代码来执行简单的查询,以及执行分页。Spring data JPA旨在通过减少实际需要的工作量来显著改进数据访问层的实现。作为开发人员,您可以编写存储库接口,包括自定义查找程序方法。spring data JPA核心接口是Repository,其它所有接口都在此类的基础上进行了扩展。下面是JPA关系图解图:
熟悉JPA的几个API
CurdRepository提供了增删改产方法,PagingAndSortingRepositroy增加了分页查询方法,JpaRepositroy又增加了实例查询方法。实际应用中可以有选择的继承上面接口即可。上面说过,jpa提供了封装查询数据库模板方法。下面就来一一介绍JPA给我们提供的模板方法:CurdRepository
接口,提供增删改查基本的功能:@NoRepositoryBean public interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID> { <S extends T> S save(S entity); <S extends T> Iterable<S> save(Iterable<S> entities); T findOne(ID id); boolean exists(ID id); Iterable<T> findAll(); Iterable<T> findAll(Iterable<ID> ids); long count(); void delete(ID id); void delete(T entity); void delete(Iterable<? extends T> entities); void deleteAll(); }
PagingAndSortingRepositroy
接口 ,分页查询,和排序:@NoRepositoryBean public interface PagingAndSortingRepository<T, ID extends Serializable> extends CrudRepository<T, ID> { //分类查询 Iterable<T> findAll(Sort sort); //分页查询 Page<T> findAll(Pageable pageable); }
JpaRepositroy
接口,提供实例查询方法@NoRepositoryBean public interface JpaRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> { <S extends T> S saveAndFlush(S entity); void deleteInBatch(Iterable<T> entities); void deleteAllInBatch(); T getOne(ID id); //实例查询 @Override <S extends T> List<S> findAll(Example<S> example); //实例查询,分类排序 @Override <S extends T> List<S> findAll(Example<S> 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方法 }
持久层
PersonRepository 接口下面介绍了JPA查询方法,条件查询,list集合查询,分页查询,排序查询,sql语句查询,指定字段查询,实例查询,基本上包含了实际开发中所需要的查询方法。
//省略了注释。 public interface PersonRepository extends JpaRepository<Person, Integer> { //自定义查询,AND为jpa 关键字,相当于(where x.lastname = ?1 and x.firstname = ?2) jpa关键字应该都要熟悉 Person findByNameAndPassword(String name ,String password); //指定字段查询,只返回name PersonName findById(Integer id); //排序查询,返回list集合 List<Person> findByNameAndPassword(String name ,String password,Sort sort); //分页查询 查询计算元素总个数总页数,数据多的情况下,代价是昂贵的 Page<Person> findByNameAndPassword(String name ,String password,Pageable pageable); //分页查询,返回的是一个片段,它只知道下一片段或者上一片段是否可用。 Slice<Person> 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) }
说明: spring data 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<Person> p1 = personRepository.findByNameAndPassword("张三","123", new Sort(Sort.Direction.ASC,"id")); //分页 Page<Person> 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.s cdc3 tartDate 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<Age> ages) | … where x.age in ?1 |
NotIn | findByAgeNotIn(Collection<Age> 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<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID>,JpaRepository<T,ID> { /** * sql查询 * * @param sql * @param args * @return */ List<Map> findAllByParams(String sql, Object... args); /** * sql分页查询 * * @param sql * @param args * @return */ Page<Map> 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<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements BaseRepository<T, ID> { //实体管理类,对持久化实体做增删改查,自动义sq操作模板所需要的核心类 public final EntityManager entityManager; public BaseRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager) { super(entityInformation, entityManager); this.entityManager = entityManager; } @Override @Transactional(rollbackFor = Exception.class) public List<Map> 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<Map> 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<Map> totalCount = q.list(); q.setFirstResult(pageable.getPageSize() * (pageable.getPageNumber() - 1)); q.setMaxResults(pageable.getPageSize()); List<Map> pageCount = q.list(); Page<Map> 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<Person, Integer> { }
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<Map> 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语句对数据库操作,对于其他情况,大家可以自己尝试。
相关文章推荐
- springboot学习笔记5(JPA 实现分页、排序、返回map集合)
- Silverlight学习笔记二:DataGrid 服务器端分页、排序的实现
- SpringBoot JPA实现增删改查、分页、排序、事务操作等功能
- JavaSE学习实战完全笔记--集合的实现细节--Set和Map
- [C++学习笔记14]动态创建对象(定义静态方法实现在map查找具体类名对应的创建函数,并返回函数指针,map真是一个万能类)good
- python数据结构学习笔记-2016-10-24-02-使用排序列表实现集合ADT
- java学习笔记—自定义实现linkedList集合
- My_Java之笔记(8)- 实现TreeSet集合的排序方法
- 分页学习笔记---真分页和假分页实现
- 黑马程序员---Map集合 学习笔记
- jsp学习笔记2——分页功能实现
- 集合框架map学习笔记-WeakHashMap
- JPA实现分页 返回总数
- Ruby On Rails 学习:Rails3中实现数据分页和排序
- 集合框架map学习笔记一HashMap
- java学习笔记——自定义实现Stack集合
- {传智播客} (学习笔记)--Java调用存储过程实现Oracle数据库分页
- Effective C# 学习笔记(三十一)利用IComparable<T>和IComparer<T>接口来实现排序关系
- 黑马程序员________Java集合Map及其JDK1.5新特性泛型机制的学习笔记
- Hibernate学习笔记:集合映射之映射Map