软件152 尹以操

首先谢谢大佬的简书文章:http://www.jianshu.com/p/45ad65690e33#

这篇文章中讲的是spring中使用spring data jpa,使用了xml配置文件。我现在使用的是spring boot ,没有了xml文件配置就方便多了。我同样尝试了两种方式,也都是简单的查询,需要更复杂的查询,还需要我研究研究。往下看,需要先配置springboot的开发环境,需要大致了解springboot,这里可以看下面两篇文章:

springboot 项目新建

springboot使用小记

创建实体类:

package com.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table; /**
*create by yyc 2017年6月11日上午9:59:59
*/
@Entity
@Table(name="test_user")
public class TestUser { @Id
@GeneratedValue
private int userId;
private Integer userAge;
private String userName;
private Integer high;//高
//省略getter、setter }

为了测试,先创建一个简单的实体类。

写元数据模型:

Criteria API

这套API可用于构建对数据库的查询。

类型安全。通过定义元数据模型,在程序编译阶段就可以对类型进行检查,不像SQL需要与Mysql进行交互后才能发现类型问题。

如下即为元数据模型。创建一个元模型类,类名最后一个字符为下划线,内部的成员变量与UserInfo.class这个实体类的属性值相对应。

package com.entity;

import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.StaticMetamodel;
import com.TestUser;
@StaticMetamodel(TestUser.class)
public class TestUser_ { public static volatile SingularAttribute<TestUser, Integer> userId;// 用户ID,自增量
public static volatile SingularAttribute<TestUser, Integer> userAge;
public static volatile SingularAttribute<TestUser, String> userName;
public static volatile SingularAttribute<TestUser, Integer> high; }

可移植。API并不依赖具体的数据库,可以根据数据库类型的不同生成对应数据库类型的SQL,所以其为可移植的。
面向对象。Criteria API是使用的是各种类和对象如CriteriaQuery、Predicate等构建查询,是面向对象的。而如果直接书写SQL则相对于面向的是字符串。

现在开始SpringBoot中使用Spring Data Jpa 实现简单的动态查询的两种方式方法

第一种方式:通过JPA的Criteria API实现

  1. EntityManager获取CriteriaBuilder
  2. CriteriaBuilder创建CriteriaQuery
  3. CriteriaQuery指定要查询的表,得到Root<UserInfo>,Root代表要查询的表
  4. CriteriaBuilder创建条件Predicate,Predicate相对于SQL的where条件,多个Predicate可以进行与、或操作。
  5. 通过EntityManager创建TypedQuery
  6. TypedQuery执行查询,返回结果
package com.repository;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.entity.TestUser;
import com.entity.TestUser_; /**
*create by yyc 2017年6月11日下午9:08:39
*/
@Repository
public class TestUserExtendDao { // @Autowired
@PersistenceContext//@Autowired和@PersistenceContext注解任取一
EntityManager em; @SuppressWarnings("unused")
public List<TestUser> getTestUserInfo(final Integer age, final String name, final Integer high){
//
CriteriaBuilder cb = em.getCriteriaBuilder();
//
CriteriaQuery<TestUser> query = cb.createQuery(TestUser.class); //3
//from
Root<TestUser> root = query.from(TestUser.class); //4
//where
Predicate p1 = null;
if (age != 0) {
System.out.println("正在操作age!!!");
Predicate p2 = cb.equal(root.get(TestUser_.userAge), age);
if (p1 != null) {
p1=cb.and(p1, p2);
} else {
p1 = p2;
}
}
if (false==name.isEmpty()) {
System.out.println("正在操作name!!!");
Predicate p2 = cb.equal(root.get(TestUser_.userName), name);
if (p1 != null) {
p1=cb.and(p1, p2);
} else {
p1 = p2;
}
}
if (high != 0) {
System.out.println("正在操作high!!!");
Predicate p2 = cb.equal(root.get(TestUser_.high), high);
if (p1 != null) {
p1=cb.and(p1, p2);
} else {
p1 = p2;
}
}
//
query.where(p1);
//
List<TestUser> testUsers = em.createQuery(query).getResultList();
return testUsers;
}
}

第二种方式:DAO层接口实现JpaSpecificationExecutor<T>接口

  JpaSpecificationExecutor如下,方法参数Specification接口有一个方法toPredicate,返回值正好是Criteria API中的Predicate,而Predicate相对于SQL的where条件。与上一个方法相比,这种写法不需要指定查询的表是哪一张,也不需要自己通过Criteria API实现排序和分页,只需要通过新建Pageable、Sort对象并传参给findAll方法即可,简便一些。

这是JpaSpecificationExecutor接口中的方法:

public interface JpaSpecificationExecutor<T> {
  T findOne(Specification<T> spec);
  List<T> findAll(Specification<T> spec);
  Page<T> findAll(Specification<T> spec, Pageable pageable);
  List<T> findAll(Specification<T> spec, Sort sort);
  long count(Specification<T> spec);
}

TestRepository继承JpaSpecificationExecutor接口:

package com.repository;

import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.PagingAndSortingRepository;
import com.entity.TestUser; /**
*create by yyc 2017年6月11日上午9:36:27
*测试动态sql
*/
public interface TestRepository extends PagingAndSortingRepository<TestUser, Integer>, JpaSpecificationExecutor<TestUser>{ }

实现Specification:

package com.entity;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.springframework.data.jpa.domain.Specification;
import com.entity.TestUser; /**
* create by yyc 2017年6月11日上午10:17:44
*/
public class TestUserDaoSpec {
public static Specification<TestUser> getSpec(final Integer age, final String name, final Integer high) {
return new Specification<TestUser>() { @SuppressWarnings("unused")
@Override
public Predicate toPredicate(Root<TestUser> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Predicate p1 = null;
if (age != 0) {
System.out.println("正在操作age!!!");
Predicate p2 = cb.equal(root.get(TestUser_.userAge), age);
if (p1 != null) {
p1=cb.and(p1, p2);
} else {
p1 = p2;
}
}
if (false==name.isEmpty()) {
System.out.println("正在操作name!!!");
Predicate p2 = cb.equal(root.get(TestUser_.userName), name);
if (p1 != null) {
p1=cb.and(p1, p2);
} else {
p1 = p2;
}
}
if (high != 0) {
System.out.println("正在操作high!!!");
Predicate p2 = cb.equal(root.get(TestUser_.high), high);
if (p1 != null) {
p1=cb.and(p1, p2);
} else {
p1 = p2;
}
}
return p1;
}
};
} }

Service层的调用测试类:

package com.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.entity.TestUser;
import com.entity.TestUserDaoSpec;
import com.repository.TestRepository;
import com.repository.TestUserExtendDao;
import com.result.Result;//一个方法返回的封装,这里直接忽略即可 /**
*create by yyc 2017年6月11日上午9:40:51
*/
@Service("testService")
public class TestService { @Autowired
private TestRepository testRepository; @Autowired
private TestUserExtendDao testUserExtendDao; //测试第一种方式
public Result getTestUsersByExtendDao(){
List<TestUser> list = testUserExtendDao.getTestUserInfo(20, "", 170);//通过两个条件,string设为空
printTestUserInfo(list);
return new Result("查询成功!", list);
} //测试第二种方式
public Result getTestUsersByThreeParameter(){
List<TestUser> list = testRepository.findAll(TestUserDaoSpec.getSpec(20, "yyc", 170));//通过三个条件
printTestUserInfo(list);
return new Result("查询成功!",list);
}
public Result getTestUsersByTwoParameter1(){
List<TestUser> list = testRepository.findAll(TestUserDaoSpec.getSpec(20, "yyc", 0));//通过两个条件,Integer设为0
printTestUserInfo(list);
return new Result("查询成功!",list);
} public Result getTestUsersByOneParameter(){
List<TestUser> list = testRepository.findAll(TestUserDaoSpec.getSpec(0, "lrs", 0));//通过一个条件查询
printTestUserInfo(list);
return new Result("查询成功!",list);
} private void printTestUserInfo(List<TestUser> list) {
if (list!=null) {
for (TestUser testUser : list) {
System.out.println("userId:"+testUser.getUserId()+
" userName:"+testUser.getUserName()+
" userAge:"+testUser.getUserAge()+
" userHigh:"+testUser.getHigh());
}
} }
}

再次感谢大佬们的文章:

http://www.jianshu.com/p/45ad65690e33#

http://blog.csdn.net/ie8848520/article/details/8161986

http://www.cnblogs.com/jiangxiaoyaoblog/p/5635152.html

SpringBoot中使用Spring Data Jpa 实现简单的动态查询的两种方法的更多相关文章

  1. Spring data jpa 实现简单动态查询的通用Specification方法

    本篇前提: SpringBoot中使用Spring Data Jpa 实现简单的动态查询的两种方法 这篇文章中的第二种方法 实现Specification 这块的方法 只适用于一个对象针对某一个固定字 ...

  2. springboot(五):spring data jpa的使用

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

  3. SpringBoot(五) :spring data jpa 的使用

    原文出处: 纯洁的微笑 在上篇文章springboot(二):web综合开发中简单介绍了一下spring data jpa的基础性使用,这篇文章将更加全面的介绍spring data jpa 常见用法 ...

  4. 最近项目中使用Spring data jpa 踩过的坑

    最近在做一个有关OA项目中使用spring data JPA 操作数据库,结果遇到了补个不可思议的麻烦.困惑了好久. 首先看一下问题吧,这就是当时测试“设置角色时,需要首先删除该用户已经拥有的角色时” ...

  5. SpringBoot系列之Spring Data Jpa集成教程

    SpringBoot系列之Spring Data Jpa集成教程 Spring Data Jpa是属于Spring Data的一个子项目,Spring data项目是一款集成了很多数据操作的项目,其下 ...

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

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

  7. spring data jpa 的简单使用

    先说简单一下JPA 概念:JPA(Java Persistence API)是Sun官方提出的Java持久化规范.它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据. 影响 ...

  8. Hibernate中使用Spring Data JPA

    一.配置文件的方式 1.pom.xml中引入相关依赖 <properties> <project.build.sourceEncoding>UTF-8</project. ...

  9. SpringBoot总结之Spring Data Jpa

    一.Spring Data Jpa简介 JPA(Java Persistence API)定义了一系列对象持久化的标准,目前实现这一规范的产品有Hibernate.TopLink等. Spring D ...

随机推荐

  1. 《从零开始学Swift》学习笔记(Day 50)——扩展计算属性、方法

    原创文章,欢迎转载.转载请注明:关东升的博客 可以在原始类型上扩展计算属性,包括实例计算属性和静态计算属性.添加计算属性的定义,与普通的计算属性的定义是一样的. 实例计算属性示例:在网络编程时,为了减 ...

  2. Nginx 解决WebSocket TCP 转发问题

    背景:   IM 即时通讯时候  , 前期我用的是IP 没什么问题,当然上线肯定要搞个域名搞搞了! 那么问题来了------>Nginx  我按照原先那样配置时候不行了, 连接不了. 解决方法: ...

  3. iOS RunLoop详解

    1. RunLoop简介 1.1 什么是RUnLoop 可以理解为字面的意思:Run表示运行,Loop表示循环.结合在一起就是运行的循环.通常叫做运行循环. RunLoop实际上是一个对象,这个对象在 ...

  4. PHP与ASP转义双引号的区别

    PHP: 转义双引号:\" ASP: 转义双引号:"" PHP与ASP转义双引号的区别

  5. c#下载文件,最简单代码

    /// <summary> /// 下载文件 /// </summary> /// <param name="url">下载地址</par ...

  6. Spring Boot之AOP面向切面编程-实战篇

    目录 前言 编程范式主要有以下几类 引入pom依赖 aop注解 实现日志分割功能 前言 AOP是一种与语言无关的程序思想.编程范式.项目业务逻辑中,将通用的模块以水平切割的方式进行分离统一处理,常用于 ...

  7. selenium之坑:点击后页面刷新重新获取刷新前的页面(StaleElementReferenceException:Message:Element not found in the cache...)

    循环点击一列链接,但只能点到第一个,第二个失败,这是为什么,因为第二个已经是新页面,当然找不到之前页面的元素,虽然元素没变,甚至是后退回来,页面都没有变,为什么是新页面,页面长的一样不代表是同一张页面 ...

  8. node.js应用生成windows service的plugin——winser

    from:http://xiaomijsj.blog.163.com/blog/static/89685520135854036206/ 针对项目中windows server machine 不断重 ...

  9. iOS11 仿大标题 导航栏

    iOS11 SytleTitleController  仿大标题 风格 导航栏 仿 iOS11 大导航标题 风格 UI 适用范围 iOS8 + 前言 iOS11全面应用大标题设计,(岂止于大—— 比逼 ...

  10. $Android连续按返回键两次实现退出程序

    思路:重写Activity的onKeyDown方法,判断按键是不是返回键,如果是,则再判断按下的时间和上次按下的时间之间的差值(毫秒数)是不是大于2000,如果不大于,则用finish()方法结束程序 ...