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. JAVA类加载器概念与线程类加载器

    类加载器的功能:通过一个类的全限定名来获取描述此类的二进制字节流的过程 java的类加载器大致可以分为两类,一类是系统提供的,一类是由应用开发人员编写的.系统提供的类加载器有以下三种: 引导类加载器( ...

  2. python 使用urllib.urlopen超时问题的解决方法

    准备写一个python脚本抓取网页数据,前面抓了几个都没有什么问题,但总会抓取不完整,在中间过程中没有反应,发现执行urlopen的地方总是提示超时,百度了一下,因为我使用的是urllib不是urll ...

  3. 02、Universal app 中按钮图标使用

    前言,windows10 昨天凌晨发布了,windows store 开发模型比以前的 silverlight 模型由很多优势, 我也小兴奋了一把. 正文: 在 windows phone 8.0 以 ...

  4. kafka启动及查看topic命令【已用过的,待更新】

    以下均为开发测试环境下: 启动Zookeeperbin/zookeeper-server-start.sh config/zookeeper.properties &启动kafkabin/ka ...

  5. lua错误收集

    这里放一些我遇到的lua错误,希望大家分享一些错误给我,统一放在这里. 1.lua表的引用传值 上面的代码运行后会发现t2[2],t2[3]表里的内容也被删除了,实际上它们 与t2[1]表里的内容都是 ...

  6. 对map进行排序

    public class TreeMapTest {    public static void main(String[] args) {        Map<String, String& ...

  7. Hadoop源码分析之Configuration

    转自:http://www.it165.net/admin/html/201312/2178.html org.apache.hadoop.conf.Configuration类是Hadoop所有功能 ...

  8. create the web service by yourshelf

    start cmd node demo.js var http = require('http'); http.createServer(function (request, response) { ...

  9. jQuery替换内容

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  10. 第二百六十三节,Tornado框架-基于正则的动态路由映射

    Tornado框架-基于正则的动态路由映射 1.在路由映射条件里用正则匹配访问路径后缀2.给每一个正则匹配规则(?P<设置名称>)设置一个名称,3.在逻辑处理的get()方法或post() ...