打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
springMVC+hibernate+springdata+querydsl搭建框架(优缺点分析+springdata介绍)

简介:springdata(以下简称data) 是spring家族的一大开源框架,其主要目的是规范数据持久化层,目的在于消除不同数据库(NOSQL和关系型数据库)之间的矛盾,提供了一套DAO层简化开发接口(即用户使用时,只需要新建一个接口继承data提供的一套接口(CrudRepository ,PagingAndSortingRepository …),data就会自动帮你自动生成并注入dao实体对象,几乎能完成所有的简单的业务逻辑,效果相似mybatis

为什么要选择这样的框架搭建模式?
1.利用data的优点,简化dao层开发,开发时只需要写dao接口,便可以完成开发,加快开发速度
例子:

/** * @author jiangjintai * */public interface AdminDao extends JpaRepository,QueryDslPredicateExecutor {}

ps:相比也与baseDao的开发方法,他的优点在于面向接口编程

2.利用hibernate的ORM思想,配合data,这里不再累述

3.复杂查询交给querydsl处理,摆脱sql语言,java里面不再有sql语言的存在(除非非常特殊情况)

缺点:
1.影响性能,把工作都交给了spring处理。
2.优化方面难以提升,该框架封装了所有的sql语言,我们无法从sql语言方面进行优化。

spring data 功能详解

1.data 提供了一个整个框架主要的核心接口 Repository,根据该接口,data实现了一个领域类去管理所有的dao领域模型,根据该超级接口,衍生了CrudRepository接口,该接口主要负责普通的crud操作:

public interface CrudRepositoryextends Repository {S save(S entity);//增T findOne(ID primaryKey);//查Iterable findAll();//查全部Long count();//查全部数量void delete(T entity);//删除boolean exists(ID primaryKey);//判断是否存在// … more functionality omitted.}

基于该接口,又衍生出了JpaRepositoryMongoRepository,等接口,主要面向与不同的持久化层。

除了普通的curb操作,数据分页,排序,对我们来说也是经常用到的逻辑,记得读者以前不懂该框架时,自己又没封装,每次分页都是自己用hql写的查询。现在PagingAndSortingRepository可以帮助我们解决这些难题。

public interface PagingAndSortingRepositoryextends CrudRepository {Iterable findAll(Sort sort);Page findAll(Pageable pageable);}//这里的Page是data对结果集进行封装,包括//1.结果List//2.当前页面和总页面//3.当前每页数据量//4.当前全部页面数据总量//5.上一页下一页的数据转换//相关数据data不会查询好了给你,是延时加载形式

可以看到,接口方法提供了一个Pageable参数,该参数即是让你用来设置你要查询的结果集的数量和页面数,使用方法

Pageable pageable = new PageRequest(0,20);//从0开始查询二十条

有了页面查询外,PageRequest还提供另一个构造方法,让使用者可以使用他进行排序

new PageRequest(0, 20, new Sort(Direction.DESC,"id"))//Sort是一个排序对象,让使用者可以根据entity的某个属性或多个属性进行排序//Direction是一个枚举,里面只提供两个排序,升序ASC,降序DESC

2.查询方法
当你发现JpaRepository(继承CrubRepository和PagingAndSortingRepository)里面提供的方法不够用时,你可以通过这样的方式命名自己的方法,data将会检查你的方法名,然后根据您的方法名进行处理

public TbUser findByUserName(String userName);//注意,这里的findBy是固定的,后面接的属性名一定要和该entity一致,不然会报出没有该属性错误//特别注意,传入参数的类型,一定一定要和entity的属性类型一样,不然也会报错,即使是Integer和int也要分清楚,作者就在这里吃了很多亏,data不会帮你自动解包装包

补充一下,如果使用了hibernate 的实体对象,如想要查询
user.address.name属性时
直接使用

public TbUser findByTbAddressName(String name)//进行查询//有时候我们的一级实体类里面有同名属性,假设有一个属性就叫TbAddressName时

我们可以使用

public TbUser findByTbUserTbAddress_Name(String name);//进行区分
//根据页面页码查询public Page findByUserName(String userName,Pageable pageable);
//特殊删除public Long deleteByUserName(String userName);

当然,也包含很多逻辑处理方法



3.data还有适应于其他持久化层,作者还未设计过NOSQL数据库,在这里就不做详述,具体可查询api。

4.data还支持,屏蔽CrubRepository接口的方法,这里作者也不做累述,具体实现思路是
4.1新建一个接口继续data接口,加上@NoRepositZ喎?http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcnlCZWFuo6y4srjHxOPQ6NKqtcS907/ao6zKudPDuMO907/a1/fOqsTjz+7Ev7XEs6y8tr3Tv9o8L3A+DQo8cD41Lsq508NAcXVlcnnX9szYyuKy6dGvPGJyIC8+DQq1scTj0/a1vczYyuK1xMfpv/ajrNDo0qpzcWzT777kvfjQ0L3ivvbKsaOsxOO/ydLUyrnTw9K7z8KwobXEt723qL340NCy6dGvPC9wPg0KPHByZSBjbGFzcz0="brush:java;"> @Query("select u from User u") Stream findAllByCustomQueryAndStream(); Stream readAllByFirstnameNotNull(); @Query("select u from User u") Stream streamAllPaged(Pageable pageable); //这里返回的时候一个流对象,当你需要使用时,你需要使用

try (Stream stream = repository.findAllByCustomQueryAndStream()) {stream.forEach(…);}//方法进行遍历,回到原始状态

这里也可以采用hibernate里面的具名查询方式,具体如下

@Entity@NamedQuery(name = "User.findByEmailAddress",query = "select u from User u where u.emailAddress = ?1")public class User {}
public interface UserRepository extends JpaRepository {List                                                                           

使用@query查询时会先对@query里面的sql|hql语句进行查询,但是命名格式需要完全按照data格式,不然会报错

public interface UserRepository extends JpaRepository {@Query("select u from User u where u.emailAddress = ?1")User findByEmailAddress(String emailAddress);}
public interface UserRepository extends JpaRepository {@Query("select u from User u where u.firstname like %?1")List findByFirstnameEndsWith(String firstname);}

使用原生sql查询

public interface UserRepository extends JpaRepository {@Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?1", nativeQuery = true)//加上标志User findByEmailAddress(String emailAddress);}

//这里也可以配置Pageable查询

public interface UserRepository extends JpaRepository {@Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1",countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",nativeQuery = true)Page findByLastname(String lastname, Pageable pageable);}

可以传入具名参数

public interface UserRepository extends JpaRepository {@Query("select u from User u where u.firstname = :firstname or u.lastname = :lastname")User findByLastnameOrFirstname(@Param("lastname") String lastname,@Param("firstname") String firstname);}

6.当你需要在dao接口处理特殊的逻辑时你可以写一个自己的接口,然后在同 java文件下使用一个类去继承该接口,然后打上@NoRepositoryBean标志,再用自己最终的dao接口去继承,便可以实现接口的个性化拓展

7.data对于querydsl的拓展
Querydsl 是对sql语言静态结构化的一个框架,使用其api,可以进行SQL相似查询。
data提供接口QueryDslPredicateExecutor

public interface QueryDslPredicateExecutor {T findOne(Predicate predicate);Iterable findAll(Predicate predicate);long count(Predicate predicate);boolean exists(Predicate predicate);// … more functionality omitted.}//Predicate 类是指使用querydsl 后的得到的断言,把断言传给data,data就能按你想要的结果进行逻辑运算。//在这里顺便提醒一下,data使用的api是com.querydsl.*系列包//而不是com.mysema.querydsl.*系列包,主要不要混淆,作者就在这里吃了很大的亏,两包都是由同一间公司维护开发,但是是因为包名不同,所以不能整合,调试了很久才发现是细节上的错误

下面给出一个查询的例子

Predicate predicate = user.firstname.equalsIgnoreCase("dave").and(user.lastname.startsWithIgnoreCase("mathews"));userRepository.findAll(predicate);//这里是querydsl查询,具体调用方式作者会在下篇文章说明,或者查阅querydsl相关说明

如果我们使用了data对querydsl的支持,我们将使用java模拟sql语句书写我们的特殊查询方式,帮助我们克服特殊的查询

8.data对springMVC的支持
data提供了一系列IOC 对springmvc 请求的支持,在这里,需要特殊说明一下,官方文档上面提到,要拓展data对springMVC的支持要使用两种办法
8.1 在配置java文件类上面标注
@EnableWebMvc
@EnableSpringDataWebSupport

8.2在xml文件里面注入

但是作者两者都试过了都没办法使之与mvc整合,最后得通过mvc的参数解析器配置才能解决问题,具体如下:

      

这里给出一个例子

@Controller@RequestMapping("/users")public class UserController {@Autowired UserRepository repository;@RequestMappingpublic String showUsers(Model model, Pageable pageable) {model.addAttribute("users", repository.findAll(pageable));return "users";}}//看到这里,我们可以把Pageable 作为参数直接传送给控制器方法,此时,我们只需要按照data给的参数规范,springmvc将会自动帮助我们注入规范如下

1.page:获取页码0为起始点
2.size:每页数据总数
3.sort:使用 属性,ASC|DESC 格式决定排序 例如:?sort=firstname&sort=lastname,asc
4.当你遇到有两个以上页面选项的时候,你可以使用

public String showUsers(Model model,@Qualifier("foo") Pageable first,@Qualifier("bar") Pageable second) { … }

方法区分不同的页面,传参时,在上述四个点前面修改
如页面数:
foo_page 和 bar_page 使用下划线隔开分别

在这里,data还提供了一个PagedResourcesAssembler类可以对page进行封装解析

@Controllerclass PersonController {@Autowired PersonRepository repository;@RequestMapping(value = "/persons", method = RequestMethod.GET)HttpEntity<>> persons(Pageable pageable,PagedResourcesAssembler assembler) {Page persons = repository.findAll(pageable);return new ResponseEntity<>(assembler.toResources(persons), HttpStatus.OK);}}

他将会把page里面的结果自动进行处理,封装后的结果例子如下:

{ "links" : [ { "rel" : "next","href" : "http://localhost:8080/persons?page=1&size=20 }],"content" : [… // 20 Person instances rendered here],"pageMetadata" : {"size" : 20,"totalElements" : 30,"totalPages" : 2,"number" : 0}}

9.还可以使用querydsl在mvc参数中进行注入,较为复杂,不做详解

10.data对Specifications的支持
Specifications类似于hibernate的QBC查询,使用时需要自己进行封装,比较麻烦,这里不做详解,当然网上也有开源的封装代码,大家有兴趣可以进行了解

springdata 功能非常强大,这里只是介绍小部分,大家有兴趣可以去参考官方文档,一个帮助大家快速开发的框架

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Spring Data JPA 参考文档三
spring-data-jpa 中文文档(1)
spring data jpa 创建方法名进行简单查询
Spring Data JPA 指南
程序员应知应会之Spring Data Jpa为什么不用写@Repository注解?
springdata常用方法和基本操作
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服