jpa 查询 列表_终极JPA查询和技巧列表–第3部分

jpa 查询 列表

在阅读第三部分之前,请记住本系列的第一部分和第二部分

JPA:通过查询创建对象

JPA允许我们使用所需的值在查询内创建对象:

package com.model;

public class PersonDogAmountReport {
 private int dogAmount;
 private Person person;

 public PersonDogAmountReport(Person person, int dogAmount) {
  this.person = person;
  this.dogAmount = dogAmount;
 }

 public int getDogAmount() {
  return dogAmount;
 }

 public void setDogAmount(int dogAmount) {
  this.dogAmount = dogAmount;
 }

 public Person getPerson() {
  return person;
 }

 public void setPerson(Person person) {
  this.person = person;
 }
}
package com.main;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import com.model.PersonDogAmountReport;

public class Page13 {

 @SuppressWarnings('unchecked')
 public static void main(String[] args) {
  CodeGenerator.startConnection();

  CodeGenerator.generateData();

  EntityManager em = CodeGenerator.getEntityManager();

  Query query = em.createQuery('select new com.model.PersonDogAmountReport(p, size(p.dogs)) from Person p group by p.id');

  List<PersonDogAmountReport> persons = query.getResultList();
  for (PersonDogAmountReport personReport : persons) {
   System.out.println(personReport.getPerson().getName() + ' has: ' + personReport.getDogAmount() + ' dogs.');
  }

  CodeGenerator.closeConnection();
 }
}

注意,在查询中我们创建了一个新对象。 好消息是您可以创建任何对象,而不必是一个实体。 您只需要传递类的完整路径,JPA将处理新的类实例化。

对于需要特定字段但实体中不存在这些字段的报表,这是非常有用的功能。

JPQL:批量更新和删除

有时我们需要执行一个操作来更新表数据库中的几行。 例如,更新所有年龄大于70岁的人,并将其定义为老年人。

您可以像这样运行批量更新/删除:

package com.main;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import com.model.Person;

public class Page14 {

 public static void main(String[] args) {
  CodeGenerator.startConnection();

  CodeGenerator.generateData();

  EntityManager em = CodeGenerator.getEntityManager();

  em.clear();
  Query query = em.createQuery('update Person p set p.name = 'Fluffy, the destroyer of worlds!'');
  query.executeUpdate();

  query = em.createQuery('select p from Person p where p.id = 4');

  Person person = (Person) query.getSingleResult();

  System.out.println('My new name is: ' + person.getName());

  query = em.createQuery('delete from Person p where p.dogs is empty');
  query.executeUpdate();

  query = em.createQuery('select p from Person p');

  System.out.println('We had 6, but was found ' + query.getResultList().size() + ' persons in the database');

  CodeGenerator.closeConnection();
 }
}

在这种情况下,级联选项将不会被触发。 您将无法删除对象,并希望JPA删除关系中的级联对象。 一旦我们讨论批量操作,数据库数据的完整性就属于开发人员。 如果要从数据库及其关系中删除对象,则需要在执行删除操作之前将对象更新为将关系设置为null。

我们可以将这种操作定义为非常危险的操作。 如果我们在第17行注释(“ em.clear(); “),我们将看到该人的姓名在更新后仍然保持不变。

问题 ”是持久性上下文将所有数据“ 附加 ”在内存中,但是这类批量操作不会更新持久性上下文。 我们将在数据库中完成一个操作,但尚未在持久性上下文中反映出来。 这种情况可能会给我们带来同步问题。

描绘以下场景:

  • 事务开始。
  • 通过方法em.persist()将人员A保留在数据库中。
  • 人员B的名称通过em.merge()方法更新为“ Louanne”。
  • 批量删除将删除人员A。
  • 人B的名称已通过批量更新更新为“ Fernanda”。
  • 交易完成。

在这种情况下会发生什么? 人员A已被批量操作删除,但持久性上下文将尝试将其持久化到数据库中。 人员B的名称已更新为Fernanda,但“持久性上下文”将尝试更新为Louanne。

对于某种情况,没有默认行为,但是可以使用一些解决方案来避免这些问题:

  • 在批量操作之前启动新事务:对于刚开始于批量操作的新事务,此操作完成时,更新/删除将在数据库中执行。 您将没有实体管理器尝试使用尚未写入数据库的数据。
  • 在批量操作之前调用“ entityManager.clear()”方法:如果调用此方法,则将强制“持久性上下文”释放所有缓存的数据。 批量操作后,如果使用find方法,则持久性上下文将从数据库中获取数据,因为您在批量操作之前清除了缓存的数据。

调用clear()方法不是灵丹妙药,如果多次使用它会给您带来性能问题。 如果您的Persistence Context有很多缓存的对象,并且您调用clear()方法,则Persistence Context将必须执行很多“行程”才能再次获取所需的数据。 持久性上下文具有出色的数据缓存控件,应该利用它。

批量操作是一种可以在多种情况下为我们提供帮助的选项, 但是您必须谨慎使用它。

JPA:条件

JPA是运行查询的一个很好的框架,但是Criteria并不是使用JPA进行查询的一个好方法。

JPA标准过于冗长,复杂,并且需要太多代码才能进行一些基本查询。 不幸的是,作为Hibernate标准并不容易。

下面的代码将显示一个简单的Criteria代码,但是我们不会再看到更多有关此主题的信息。 我已经读了三本关于EJB / JPA的书,而没有一本书谈论它。

下面的代码有一个标准代码:

package com.main;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaQuery;

import com.model.Person;

public class Page15 {

 @SuppressWarnings({ 'unchecked', 'rawtypes' })
 public static void main(String[] args) {
  CodeGenerator.startConnection();

  CodeGenerator.generateData();

  EntityManager em = CodeGenerator.getEntityManager();

  CriteriaQuery criteriaQuery = em.getCriteriaBuilder().createQuery();
  criteriaQuery.select(criteriaQuery.from(Person.class));

  List<Person> result = em.createQuery(criteriaQuery).getResultList();

  System.out.println('Found ' + result.size() + ' persons.');

  CodeGenerator.closeConnection();
 }
}

很遗憾,我在这里这么说我对Criteria的看法,但是到目前为止,除非对于A ListALL,否则我认为在您的代码中使用Criteria并不简单。

上面的代码很容易应用于通用DAO,因此列出所有对象会更加容易。

以下链接显示了应用程序中的通用DAO: 完整的WebApplication JSF EJB JPA JAAS

结束!

希望这篇文章对您有所帮助。

点击此处下载源代码。

您无需编辑任何配置即可运行本文的代码,只需将其导入Eclipse。

如果您有任何疑问/意见,请在下面将其发布。

再见。

有用的链接:

  • http://www.mkyong.com/hibernate/how-to-display-hibernate-sql-parameter-values-log4j/
  • http://stackoverflow.com/questions/1659030/how-to-get-the-database-time-with-jpql
  • Pro EJB 3:Java持久性API,Mike Keith,Merrick Schincariol
  • 企业JavaBeans 3.0 – Richard Monson-Haefel,Bill Burke

参考: uaiHebert博客上来自JCG合作伙伴 Hebert Coelho的JPA查询和技巧


翻译自: https://www.javacodegeeks.com/2012/07/ultimate-jpa-queries-and-tips-list-part_7092.html

jpa 查询 列表

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值