JPA实现分页&CRUD笔记&JPA查询语言

散列收集:

1.具体实现

  1. @RequestMapping(value = "/findallByPage")

  2. public Page<User> findAllByPage() {

  3. Sort sort = new Sort(Sort.Direction.ASC,"id");

  4. Pageable pageable = new PageRequest(2,6,sort);

  5. Page<User> page = userRepository.findAll(pageable);

  6. return page;

  7. }

  • 实现删除操作的时候一定要在各层类中 增加
 @Transactional

注释,否则会一直报错

  • 在自己使用@Query定义操作时,会碰到编译器报错,这个时候只需要禁用QL的语法检查即可

以下是部分代码:

//Repository

 
  1. package com.example.myproject.dao;

  2.  
  3. import com.example.myproject.domain.User;

  4. import org.springframework.data.domain.Page;

  5. import org.springframework.data.domain.Pageable;

  6. import org.springframework.data.jpa.repository.JpaRepository;

  7. import org.springframework.data.jpa.repository.Modifying;

  8. import org.springframework.data.jpa.repository.Query;

  9. import org.springframework.data.repository.query.Param;

  10.  
  11. import javax.transaction.Transactional;

  12. import java.util.List;

  13.  
  14. /**

  15. * Created by lenovo on 2017/4/19.

  16. */

  17. @Transactional

  18. public interface UserRepository extends JpaRepository<User,Long> {

  19.  
  20.  
  21. void deleteById(int id);

  22. void deleteByName(String name);

  23. void deleteBySex(String sex);

  24. void deleteByAge(int age);

  25. void removeByNameAndAge(String name, int age);

  26.  
  27. @Modifying

  28. @Query(value = "update user u set u.name = :newName where u.name = :oldName",nativeQuery = true)

  29. void updateNameByName(@Param("oldName") String oldName, @Param("newName") String newName);

  30.  
  31. List<User> findAll();

  32. Page<User> findAll(Pageable pageable);

  33. List<User> findByName(String name);

  34. List<User> findBySex(String sex);

  35. List<User> findByAge(int age);

  36. User findByNameAndSex(String name, String sex);

  37. }

//Controller

 
  1. package com.example.myproject.web;

  2.  
  3. import com.example.myproject.dao.UserRepository;

  4. import com.example.myproject.domain.User;

  5. import org.springframework.beans.factory.annotation.Autowired;

  6. import org.springframework.data.domain.Page;

  7. import org.springframework.data.domain.PageRequest;

  8. import org.springframework.data.domain.Pageable;

  9. import org.springframework.data.domain.Sort;

  10. import org.springframework.web.bind.annotation.RequestMapping;

  11. import org.springframework.web.bind.annotation.RequestParam;

  12. import org.springframework.web.bind.annotation.RestController;

  13.  
  14. import javax.transaction.Transactional;

  15. import java.util.List;

  16.  
  17. /**

  18. * Created by lenovo on 2017/4/19.

  19. */

  20. @RestController

  21. @RequestMapping("/")

  22. @Transactional

  23. public class UserController {

  24. @Autowired

  25. private UserRepository userRepository;

  26.  
  27. @RequestMapping(value = "/userSave")

  28. public String userSave(@RequestParam String name,@RequestParam String sex,@RequestParam int age) {

  29. User user = new User();

  30. user.setName(name);

  31. user.setAge(age);

  32. user.setSex(sex);

  33. userRepository.save(user);

  34. return "true";

  35. }

  36.  
  37. @RequestMapping(value = "/deleteById")

  38. public String deleteById(@RequestParam int id) {

  39. userRepository.deleteById(id);

  40. return "success";

  41. }

  42.  
  43. @RequestMapping(value = "/deleteByName")

  44. public String deleteByName(@RequestParam String name) {

  45. userRepository.deleteByName(name);

  46. return "success";

  47. }

  48.  
  49. @RequestMapping(value = "/deleteBySex")

  50. public String deleteBySex(@RequestParam String sex) {

  51. userRepository.deleteBySex(sex);

  52. return "success";

  53. }

  54.  
  55. @RequestMapping(value = "/deleteByAge")

  56. public String deleteByAge(@RequestParam int age) {

  57. userRepository.deleteByAge(age);

  58. return "success";

  59. }

  60.  
  61. @RequestMapping(value = "/deleteByNameAndAge")

  62. public String deleteByNameAndAge(@RequestParam String name, @RequestParam int age) {

  63. userRepository.removeByNameAndAge(name,age);

  64. return "success";

  65. }

  66.  
  67. @RequestMapping(value = "/updateNameByName")

  68. public String updateNameByName(@RequestParam String oldName, @RequestParam String newName) {

  69. userRepository.updateNameByName(oldName,newName);

  70. return "success";

  71. }

  72.  
  73. @RequestMapping(value = "/findall")

  74. public List<User> findAll() {

  75. List<User> l =userRepository.findAll();

  76. return l;

  77. }

  78.  
  79. @RequestMapping(value = "/findallByPage")

  80. public Page<User> findAllByPage() {

  81. Sort sort = new Sort(Sort.Direction.ASC,"id");

  82. Pageable pageable = new PageRequest(2,6,sort);

  83. Page<User> page = userRepository.findAll(pageable);

  84. return page;

  85. }

  86.  
  87. @RequestMapping(value = "/findByName")

  88. public List<User> findByName(@RequestParam String name) {

  89. List<User> list =userRepository.findByName(name);

  90. return list;

  91. }

  92.  
  93. @RequestMapping(value = "/findByAge")

  94. public List<User> findByAge(@RequestParam int age) {

  95. List<User> list =userRepository.findByAge(age);

  96. return list;

  97. }

  98.  
  99. @RequestMapping(value = "/findBySex")

  100. public List<User> findBySex(@RequestParam String sex) {

  101. List<User> list =userRepository.findBySex(sex);

  102. return list;

  103. }

  104.  
  105. @RequestMapping(value = "/findByNameAndSex")

  106. public User findByNameAndSex(@RequestParam String name, @RequestParam String sex) {

  107. User list =userRepository.findByNameAndSex(name,sex);

  108. return list;

  109. }

  110. }



//User

 
  1. package com.example.myproject.domain;

  2.  
  3. import javax.persistence.*;

  4.  
  5. /**

  6. * Created by lenovo on 2017/4/19.

  7. */

  8.  
  9. @Entity

  10. public class User {

  11. @Id

  12. @GeneratedValue()

  13. private Integer id;

  14.  
  15. @Column

  16. private String name;

  17.  
  18. @Column

  19. private String sex;

  20.  
  21. @Column

  22. private int age;

  23.  
  24. public Integer getId() {

  25. return id;

  26. }

  27.  
  28. public String getName() {

  29. return name;

  30. }

  31.  
  32. public void setName(String name) {

  33. this.name = name;

  34. }

  35.  
  36. public String getSex() {

  37. return sex;

  38. }

  39.  
  40. public void setSex(String sex) {

  41. this.sex = sex;

  42. }

  43.  
  44. public int getAge() {

  45. return age;

  46. }

  47.  
  48. public void setAge(int age) {

  49. this.age = age;

  50. }

  51. }

JPA的查询语言 

JPA的查询语言是面向对象而非面向数据库的,它以面向对象的自然语法构造查询语句 ,可以看成是Hibernate HQL的等价物。

Sql代码  收藏代码

  1. SELECT DISTINCT t FROM Topic t WHERE t.topicTitle = ?1  

通过WHERE指定查询条件,?1表示用位置标识参数,尔后,我们可以通过Query的setParameter(1, "主题1")绑定参数。而DISTINCT表示过滤掉重复的数据。

如果需要以命名绑定绑定数据,可以改成以下的方式:

Sql代码  收藏代码

  1. SELECT DISTINCT t FROM Topic t WHERE t.topicTitle = :title  

这时,需要通过Query的setParameter("title", "主题1")绑定参数。

关联查询:从One的一方关联到Many的一方

返回PollOptions对应的PollTopic对象,可以使用以下语句:

Sql代码  收藏代码

  1. SELECT DISTINCT p FROM PollTopic p, IN(p.options) o WHERE o.optionItem LIKE ?1  

这个语法和SQL以及HQL都有很大的区别,它直接实体属性连接关联的实体,这里我们通过PollTopic的options属性关联到PollOption实体上,对应的SQL语句为:

Sql代码  收藏代码

  1. SELECT DISTINCT t0.TOPIC_ID, t0.TOPIC_TYPE, t0.TOPIC_TITLE,  
  2. t0.TOPIC_TIME, t0.TOPIC_VIEWS, t0.MULTIPLE, t0.MAX_CHOICES   
  3.   
  4. FROM T_TOPIC t0,T_POLL_OPTION t1   
  5.   
  6. WHERE (((t1.OPTION_ITEM LIKE ?) AND (t0.TOPIC_TYPE = ?))  
  7. AND (t1.TOPIC_ID = t0.TOPIC_ID))  

该查询语句的另外两种等价的写法分别是:

Sql代码  收藏代码

  1. SELECT DISTINCT p FROM PollTopic p JOIN p.options o WHERE o.optionItem LIKE ?1  
  2.   
  3. 和  
  4.   
  5. SELECT DISTINCT p FROM PollTopic p WHERE p.options.optionItem LIKE ?1  

关联查询:从Many的一方关联到One的一方

从Many一方关联到One一方的查询语句和前面所讲的也很相似。如我们希望查询某一个调查主题下的所示调查项,则可以编写以下的查询语句:

Sql代码  收藏代码

  1. SELECT p FROM PollOption p JOIN p.pollTopic t WHERE t.topicId = :topicId  

JPQL

一、什么是JPQL

在 Java EE 中,JPQL( Java 持久性查询语言)是专门为Java 应用程序访问和导航实体实例设计的。JPQL是EJB2使用的查询语言EJB QL的扩展,它继承了EJB QL并对其做了一些改变。

二、JPQL与SQL

JPQL 和 SQL 有很多相似之处。归根结底,它们都用于访问和操作数据库数据。而且,二者都使用非过程语句 — 通过特殊解释程序识别的命令。此外,JPQL 在语法上与 SQL 也相似。

JPQL 和 SQL 的主要区别在于,前者处理 JPA 实体,后者直接在数据库空间内对表、列、行等关系数据进行处理。

三、使用JPQL

要从 Java 代码内发出 JPQL 查询,您需要利用 EntityManager API 和 Query API 的相应方法,执行以下一般步骤:

1.   使用注入或通过 EntityManagerFactory 实例获取一个 EntityManager 实例。

2.   通过调用相应 EntityManager 的方法(如 createQuery),创建一个 Query 实例。

3.   如果有查询参数,使用相应 Query 的 setParameter 方法进行设置。

4.   如果需要,使用 setMaxResults 和/或 setFirstResult Query 的方法设置要检索的实例的最大数量和/或指定检索的起始实例位置。

5.   如果需要,使用 setHint Query 的方法设置供应商特定的提示。

6.   如果需要,使用 setFlushMode Query 的方法设置查询执行的刷新模式,覆盖实体管理器的刷新模式。

7.   使用相应 Query 的方法 getSingleResult 或 getResultList 执行查询。如果进行更新或删除操作,您必须使用 executeUpdate 方法,它返回已更新或删除的实体实例的数量。

JPQL的查询可以分为命名查询和动态查询。

动态查询

可以使用EntityManager.createQuery方法创建动态查询,唯一的要求是把合法的JPQL语句传递给此方法。如下:

Query query = em.createQuery(“select p from Person p where p.id=1033”);

其中where语句可是可选的。在这里JPQL看上去和SQL语句很像,但应当注意到的是from后边的Person是实体Bean而不是数据表。

在所写的JPQL语句中你可以像示例中那样的直接将查询条件写在语句中。但是还有更好的方法。在这里你可以使用设置查询参数的方式,其中又有位置参数和命名参数的分别。

使用位置参数如下所示:

Query query = em.createQuery(“select p from Person p where p.id=?1”);

Query.setParameter(1, 1033);//第一个参数是位置,第二个参数查询条件

使用命名参数如下所示:

Query query = em.createQuery(“select p from Person p where p.id=:id”);

Query.setParameter(“id”, 1033);//第一个参数是参数名称,第二个参数查询条件

需要注意的是位置参数的是位置前加符号”?”,命名参数是名称前是加符号”:”。

如果你需要传递java.util.Date或java.util.Calendar参数进一个参数查询,你需要使用一个特殊的setParameter()方法。因为一个Date或Calendar对象能够描述一个真实的日期、时间或时间戳.所以我们需要告诉Query对象怎么使用这些参数,我们把javax.persistence.TemporalType作为参数传递进setParameter方法,告诉查询接口在转换java.util.Date或java.util.Calendar参数到本地SQL时使用什么数据库类型。

查询结果

使用Query. getSingleResult方法得到查询的单个实例,返回Object。要确保使用此方法时查询只检索到一个实体。

使用Query. getResultList方法得到查询的实例集合,返回List。

通常的,我们会如示例中所示的是获取查询返回的是实体,但是在JPQL里我们也可以得到实体的部分属性,就如同使用SQL得到表中的部分列一样。如果是获取部分属性的话,Query.getResultList方法返回的会是Object数组的List每个Object数组项相当于是一条结果,数组的成员是属性值,顺序和所写的JPQL中的SELECT中所写顺序一致。

查询中使用构造器(Constructor)

可以在SELECT子句中使用构造器返回一个或多个java实例。如下所示:

Query query = em.createQuery("select new com.demo.bean.Person(p.id, p.name) from Person p order by p.id desc");

查询分页

JPA提供了在结果集合中使用分页的功能,使用这个功能我们可以轻松的达到对查询结果分页的目的。如下

Query.setMaxResults(10);//设置分页大小,在这里为每页10条记录

Query.setFirstResult(10);//指定第一个结果的位置。这里是指定第11条作为起始结果。

这里只要在setFirstResult中使用动态参数即可方便的对结果进行分页了。

使用操作符

在where子句中我们可以使用一些操作符来进行条件的选择。

NOT操作符

select p from Person p where not(p.id = 1036)

//查询id不是1036的所有人

BETWEEN操作符

select p from Person p where p.age between 20
and 26

//查询年龄在20到26的所有人;上限和下限必须是相同的数据类型

IS  NULL操作符

select p from Person p where p.name is not null

//查询名字不为NULL的所有人

IS  EMPTY操作符

IS EMPTY是针对集合属性(Collection)的操作符。可以和NOT 一起使用。注:低版权的Mysql 不支持IS EMPTY

select p from Person p where p.interest is empty

//查询兴趣(是集合)是空的所有人

IN 操作符

select p from Person p where p.id in (101,102)

//查询id是101和102的人

EXISTS 操作符

[NOT]EXISTS 需要和子查询配合使用。注:低版权的Mysql 不支持EXISTS

select p from Person p where exists (select b from Book b where b.name like ‘%EJB%’ )

//如果书籍名字中包含有EJB字样,则得到所有人

MEMBER OF操作符

可以使用MEMBER OF操作符检查集合-值路径表达式中是否存在标识符变量、单一值表达式或是输入参数。

select p from Person p where :interest member of p.interest

//查询兴趣(是集合)是中包含所输入的兴趣实体实例(:interest)的所有人

使用字符串函数

JPQL定义了内置函数方便使用。这些函数的使用方法和SQL中相应的函数方法类似。包括:

1. CONCAT 字符串拼接

2. SUBSTRING 字符串截取

3. TRIM 去掉空格

4. LOWER 转换成小写

5. UPPER 装换成大写

6. LENGTH 字符串长度

7. LOCATE 字符串定位

使用算术函数

JPQL仅仅支持了最低限度的算术函数集合,可以在JPQL的where和having子句中使用算术函数。JPQL定义的算术函数包括:

ABS 绝对值

SQRT 平方根

MOD 取余数

SIZE 取集合的数量

使用时间函数

JPQL像大多数语言一样提供了获得当前日期、时间或是时间标记的函数。这些函数转换为数据库专有的SQL函数,从数据库检索当前日期、时间或时间标记。包含的时间函数如下:

CURRENT_DATE 返回当前日期

CURRENT_TIME 返回当前时间

CURRENT_TIMESTAMP 返回当前时间标记

       联结(连接/关联)

       JPQL仍然支持和SQL中类似的关联语法:

       left out join/left join

       left out join/left join等,都是允许符合条件的右边表达式中的Entities 为空(需要显式使用left join/left outer join 的情况会比较少。)

       inner join

       inner join 要求右边的表达式必须返回Entities。

       left join fetch/inner join fetch

       在默认的查询中,Entity中的集合属性默认不会被关联,集合属性默认是延迟加载( lazy-load )。那么,left fetch/left out fetch/inner join fetch提供了一种灵活的查询加载方式来提高查询的性能(集合属性被关联,同Entity同时加载而不是在需要时再加载,这样就转换为SQL语句时为一条SQL语句,而不是加载Entity时一条语句,加载集合属性时有N(等于Entity数量)条语句,避免了N+1问题,提高了查询性能)。

使用聚合函数

JPQL提供的聚合函数有AVG、COUNT、MAX、MIN、SUM。在AVG、MAX、MIN、SUM函数中只能使用持久化字段,而在COUNT中可以使用任何类型的路径表达式或标识符。

COUNT返回的类型是Long,AVG是Double,SUM可能返回Long或Double。

分组

如果聚合函数不是select...from的唯一一个返回列,需要使用"GROUP BY"语句。"GROUP BY"应该包含select 语句中除了聚合函数外的所有属性。如果还需要加上查询条件,需要使用"HAVING"条件语句而不是"WHERE"语句

select p.grade, count(p) from Person p where p.age > 20 group by p.grade having count(*)>120

//返回年龄大于20的各年级的总人数(人数大于120)

排序

在JPQL中像SQL一样使用order by 来进行排序。"ASC"和"DESC"分别为升序和降序,JPQL中默认为ASC升序。

批删除和批更新

JPQL支持批量删除和批量更新的操作。和查询相同的是也是要使用EntityManager.createQuery方法来创建一个Query实例,不同的是在这里要使用Query.executeUpdate方法来直行删除和更新,该方法返回的值是操作的记录数。

命名查询

可以在实体bean上通过@NamedQuery or @NamedQueries预先定义一个或多个查询语句,减少每次因书写错误而引起的BUG。通常把经常使用的查询语句定义成命名查询。

定义单个命名查询:

@NamedQuery(name="getPerson", query=
"select p from  Person p where p.id=?1")

@Entity

public class Person
implements Serializable{

如果要定义多个命名查询,应在@javax.persistence.NamedQueries里定义@NamedQuery:

@NamedQueries({

@NamedQuery(name="getPerson", query=
"select p from  Person p where p.id=?1"),

@NamedQuery(name="getPersonList", query=
"select p from Person as p where p.age>?1")

})

@Entity

public class Person
implements Serializable{

当命名查询定义好了之后,我们就可以通过名称执行其查询。代码如下:

Query query = em.createNamedQuery("getPerson");

query.setParameter(1, 1);

四、注意

1.       JPQL语句的大小写敏感性:除了Java 类和属性名称外,查询都是大小写不敏感的。

2.       使用参数查询的时候除了基本类型的参数还可以使用实体参数。

猜你喜欢

转载自blog.csdn.net/qq_39659876/article/details/82056267