klg-jpa:spring-data-jpa 最佳实践

项目介绍

码云地址:https://gitee.com/klguang/klg-jpa

JPA是sun为POJO持久化制定的标准规范,用来操作实体对象,执行CRUD操作,让开发者从繁琐的JDBC和SQL代码中解脱出来。 但是JPA有以下两个缺陷:
1.臃肿的动态条件查询 

2.众所周知,复杂查询(联接表查询)的效率低 
spring-data-jpa和mybatis可以整合在一起使用有什么优缺点,这个问答种了解到 spring-data-jpa-extra这个库,让我们可用更方便的写sql查询。

klg-jpa,spring-data-jpa 最佳实践,用起来就像开了挂,更多例子klg-j2ee-dataacess-demo 演示

单表查询最佳实践

1. find by attribute是一种较灵活的方式,需要用到jpa生成的metamodel,在快速开发的利器 

BaseRepository api:

	//-------------find by attribute------------------------
public Page<T> findPage(Pageable pageable,AttrExpression...exprs);
public List<T> findList(Sort sort,AttrExpression...exprs);
public List<T> findList(AttrExpression...exprs);
public T getOne(AttrExpression...exprs);
public long count(AttrExpression...exprs);

find by attribute 适合不定条件单表查询,默认是不忽略空值的(null或者""),如果要忽略空值,请用AExpr属性表达式构造器的igEmpty()方法。

Pageable pageable = new PageRequest(0, 10, new Sort(Direction.DESC, "userId"));
Page<User> userPage = userDAO.findPage(pageable,
AExpr.eq(User_.account, "").igEmpty(),
AExpr.contain(User_.userName, "fd"));

含有开始和结束时间 动态查询的处理

@ResponseBody
@RequestMapping("/findpage")
public EasyUIPage findpage(
@RequestParam int page,
@RequestParam int rows,
@RequestParam(required=false) Long employeeid,
@RequestParam(required=false) @DateTimeFormat(pattern="yyyy-MM-dd") Date startDate,
@RequestParam(required=false) @DateTimeFormat(pattern="yyyy-MM-dd") Date endDate){
Pageable pageable=new PageRequest(page<1?0:page-1, rows, new Sort(Direction.DESC,"numId"));
_EmployeeName employeeName=employeeid==null?null:MyReflectUtil.createWithSet(_EmployeeName.class, "id", employeeid); Page<DrugOut> pageData=drugOutService.findPage(pageable,
AExpr.eq(DrugOut_.employeeName, employeeName).igEmpty(),
AExpr.gte(DrugOut_.saledate, startDate).igEmpty(),
AExpr.lte(DrugOut_.saledate, endDate).igEmpty()); return new EasyUIPage(pageData);
}

注意: 
1).复杂属性的表达式处理:先判断复杂属性的实体的id是否为空
2).动态查询,参数(required=false)、查询的属性表达式列表(igEmpty)

2. 通过解析Repository中的方法名创建查询,是spring-data-jpa的一大特色。符合经典的java三层架构:表现层(UI),业务逻辑层(BLL),数据访问层(DAL) 

这是spring官网的例子:通过EmailAddress和Lastname来查找用户

public interface UserRepository extends Repository<User, Long> {

  List<User> findByEmailAddressAndLastname(String emailAddress, String lastname);
}

详见spring-data-jpa#Query Creation

3. 页面参数封装到实体,然后运用qbe(query by example)。qbe会自动忽略null值 
BaseRepository api:

	//--------------qbe(query by example)--------------------
public Page<T> findPage(T example,Pageable pageable);
public List<T> findList(T example,Sort sort);
public List<T> findList(T example);
public T getOne(T example);
public long count(T example);

qbe复杂查询只支持String的模糊查询,大于、小于、between and均不支持。
ExampleMatcher例字,嵌套属性模糊匹配

//User有属性logrole
ExampleMatcher matcher=ExampleMatcher.matching()
.withMatcher("logrole.logRoleName", GenericPropertyMatcher.of(StringMatcher.CONTAINING).ignoreCase());
List<User> users=userDAO.findAll(Example.of(user,matcher));

详见spirng-data-jpa#query-by-example

复杂查询最佳实践

复杂查询,无论是用java代码进行sql拼接还是臃肿的Criteria动态查询都是不推荐的。因为这么做一方面是不够优雅,更重要的是难以维护。Mybatis的流行给了我们很多启发,复杂查询用sql配置文件,是一种灵活且方便维护的方式。
以下两种方式是我推荐大家使用的:

  1. 可用使用@NamedQuery,或spring-data-jpa的@Query
  2. 引入spring-data-jpa-extra这个库

使用说明

  1. 下载本项目,并执行maven install ,在项目引入依赖
  2. 项目中Repository继承BaseRepository,Service接口继承BaseService,ServiceImpl继承BaseServiceImpl;BaseService的接口中有BaseRepository的大部分方法
  3. spring配置如下:
	<!-- 指定 BaseRepositoryFactoryBean -->
<jpa:repositories base-package="demo,com.slyak.spring.jpa"
factory-class="klg.common.dataaccess.BaseRepositoryFactoryBean"
entity-manager-factory-ref="entityManagerFactory"
transaction-manager-ref="transactionManager" repository-impl-postfix="Impl" /> <!-- 配置 freemarkerSqlTemplates解析相关-->
<bean id="freemarkerSqlTemplates" class="com.slyak.spring.jpa.FreemarkerSqlTemplates">
<property name="suffix" value=".sftl" />
<property name="templateLocation" value="classpath*:/sqls"/>
</bean>

如有疑问下载klg-j2ee-dataacess-demo 演示

注意

本项目依赖spring-data-jpa-extra-2.1.2.RELEASE,但我做了一些改动,然后打成jar包
项目地址:https://github.com/klguang/spring-data-jpa-extra/tree/2.1.2.RELEASE

  1. com.slyak.spring.jpa.ContextHolder 访问控制为public,目的是让原来项目中已经存在的BaseRepositoryFactoryBean能工作。
  2. 模板文件名为Entity的java full name
  3. 测试用例跑通

klg-jpa:spring-data-jpa 最佳实践的更多相关文章

  1. spring data jpa 全面解析(实践 + 源码分析)

    前言 本文将从示例.原理.应用3个方面介绍spring data jpa. 以下分析基于spring boot 2.0 + spring 5.0.4版本源码 概述 JPA是什么? JPA (Java ...

  2. 【spring boot 系列】spring data jpa 全面解析(实践 + 源码分析)

    前言 本文将从示例.原理.应用3个方面介绍spring data jpa. 以下分析基于spring boot 2.0 + spring 5.0.4版本源码 概述 JPA是什么? JPA (Java ...

  3. 来说说JPA、Hibernate、Spring Data JPA之间的什么关系?

    目录 JPA Hibernate Spring Data JPA 实践 来说说JPA.Hibernate.Spring Data JPA之间的什么关系 Java 持久层框架访问数据库的方式大致分为两种 ...

  4. JPA && Spring Data && Spring Data JPA

    1.JPA  Java Persistence API,用于对象持久化的一组API,JPA本身是一组规范,让开发者用同一种方式访问不同的ORM框架.其实也就是java实体对象和关系型数据库建立起映射关 ...

  5. SpringBoot入门:Spring Data JPA 和 JPA(理论)

    参考链接: Spring Data JPA - Reference Documentation Spring Data JPA--参考文档 中文版 纯洁的微笑:http://www.ityouknow ...

  6. 干货|一文读懂 Spring Data Jpa!

    有很多读者留言希望松哥能好好聊聊 Spring Data Jpa!其实这个话题松哥以前零零散散的介绍过,在我的书里也有介绍过,但是在公众号中还没和大伙聊过,因此本文就和大家来仔细聊聊 Spring D ...

  7. spring-boot (三) spring data jpa

    学习文章来自:http://www.ityouknow.com/spring-boot.html spring data jpa介绍 首先了解JPA是什么? JPA(Java Persistence ...

  8. springboot:spring data jpa介绍

    转载自:https://www.cnblogs.com/ityouknow/p/5891443.html 在上篇文章springboot(二):web综合开发中简单介绍了一下spring data j ...

  9. Spring Data JPA例子[基于Spring Boot、Mysql]

    关于Spring Data Spring社区的一个顶级工程,主要用于简化数据(关系型&非关系型)访问,如果我们使用Spring Data来开发程序的话,那么可以省去很多低级别的数据访问操作,如 ...

  10. spring boot(五)Spring data jpa介绍

    在上篇文章springboot(二):web综合开发中简单介绍了一下spring data jpa的基础性使用,这篇文章将更加全面的介绍spring data jpa 常见用法以及注意事项 使用spr ...

随机推荐

  1. 从pdf 文件中抽取特定的页面

    前段时间买了一个kindle 电子书阅读器.我想用它来读的pdf文档.当然最主要是用来读python标准库&mysql的官方文档. 问题就来了.这两个都是大头书.之前用mac看还好.用kind ...

  2. openWRT学习之LUCI之中的一个helloworld演示样例

    备注1:本文 讲述的是原生的openWRT环境下的LUCI 备注2:本文參考了诸多资料.感谢网友分享.參考资料: http://www.cnblogs.com/zmkeil/archive/2013/ ...

  3. [svc]linux查看主板型号及内存硬件信息

    公司服务器内存不够用了. 想看看买啥型号的. 购买内存条注意点: ddr3 or4 频率 块钱. 内存槽及内存条: dmidecode |grep -A16 "Memory Device$& ...

  4. 【转】如何把hadoop-1.x源码关联到Eclipse工程

    [转]http://www.tuicool.com/articles/mIb2EzU

  5. Linux之目录的操作(创建、移动、改名、删除、复制)

    .创建 mkdir [dirname] //创建单个目录 mkdir -p newdir1/newdir2/newdir3 //递归创建多级目录 mkdir dir1/dir2/newdir3 //在 ...

  6. javascript 异步实现方案

    1.回调函数 fn1( fn2 ); 2.事件监听 fn1.on('done', fn2); function fn1() { setTimeout(function(){ fn1.trigger(' ...

  7. a标签去掉下划线

    转载自:http://jingyan.baidu.com/article/a17d52853095838099c8f24e.html <a>是默认有下划线的.所以有时候为了美观,我们需要去 ...

  8. Asp.net回调技术Callback学习

    .aspx: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.a ...

  9. selenium:chromedriver与chrome版本的对应关系

    转自:http://blog.csdn.NET/huilan_same/article/details/51896672 再使用selenium打开chrome浏览器的时候,需要用chromedriv ...

  10. 【BZOJ】1093: [ZJOI2007]最大半连通子图(tarjan+拓扑序)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1093 两个条件综合起来加上求最大的节点数,那么很明显如果是环一定要缩点. 然后再仔细思考下就是求da ...