无需部署即可测试JPQL / HQL

您是否曾经想在不完全部署应用程序的情况下测试JPQL / HQL?
我们今天在这里看到的是适用于任何JPA实现的简单解决方案:Hibernate,OpenJPA,EclipseLink等。

这篇文章中找到的基本源代码来自于本书:“ Pro JPA 2:掌握Java™持久性API – Mike Keith,Merrick Schincariol ”。 这篇文章将添加到原始代码中:查询参数和NamedQuery测试。

模型类和数据生成

下面是模型类的代码:

package com.model;

import java.util.*;

import javax.persistence.*;

@Entity
@NamedQueries({
  @NamedQuery(name="Person.findByName", query="select p from Person p where p.name = :name"),
  @NamedQuery(name="Person.findByAge", query="select p from Person p where p.age = :age", hints={@QueryHint(name="org.hibernate.timeout", value="1000")})
})

public class Person {

 public static final String FIND_BY_NAME = "Person.findByName";
 public static final String FIND_BY_AGE = "Person.findByAge";

 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private int id;

 private String name;
 private int age;

 public Person() {

 }

 public Person(int id) {
  this.id = id;
 }

 public Person(String name, int age) {
  this.name = name;
  this.age = age;
 }

 @OneToMany(mappedBy = "person", cascade = CascadeType.ALL)
 private List<Dog> dogs;

 @OneToOne(cascade = CascadeType.ALL)
 @JoinColumn(name="address_id")
 private Address address;

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public int getAge() {
  return age;
 }

 public void setAge(int age) {
  this.age = age;
 }

 public List<Dog> getDogs() {
  if (dogs == null) {
   dogs = new ArrayList<Dog>();
  }

  return dogs;
 }

 public void setDogs(List<Dog> dogs) {
  this.dogs = dogs;
 }

 public Address getAddress() {
  return address;
 }

 public void setAddress(Address address) {
  this.address = address;
 }

 @Override
 public int hashCode() {
  return getId();
 }

 @Override
 public boolean equals(Object obj) {
  if (obj instanceof Person) {
   Person person = (Person) obj;
   return person.getId() == getId();
  }

  return false;
 }

 @Override
 public String toString() {
  return "Person name: " + name;
 }
}
package com.model;

import java.util.Date;

import javax.persistence.*;

@Entity
@NamedQueries(value={@NamedQuery(name="Dog.FindByDateOfBirth", query="select d from Dog d where d.dateOfBirth = :dateOfBirth"),
  @NamedQuery(name="Dog.FindByPerson", query="select d from Dog d where d.person = :personObject")})
public class Dog {

 public static final String FIND_BY_DATE_OF_BIRTH = "Dog.FindByDateOfBirth";

 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private int id;

 private String name;
 private double weight;

 @Temporal(TemporalType.TIMESTAMP)
 private Date dateOfBirth;

 public Dog() {

 }

 public Dog(String name, double weight, Date dateOfBirth) {
  this.name = name;
  this.weight = weight;
  this.dateOfBirth = dateOfBirth;
 }

 public static void main(String[] args) {

  System.out.println(new Date());
 }

 @ManyToOne
 private Person person;

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public double getWeight() {
  return weight;
 }

 public void setWeight(double weight) {
  this.weight = weight;
 }

 public Date getDateOfBirth() {
  return dateOfBirth;
 }

 public void setDateOfBirth(Date dateOfBirth) {
  this.dateOfBirth = dateOfBirth;
 }

 public Person getPerson() {
  return person;
 }

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

 @Override
 public int hashCode() {
  return getId();
 }

 @Override
 public boolean equals(Object obj) {
  if (obj instanceof Dog) {
   Dog dog = (Dog) obj;
   return dog.getId() == getId();
  }

  return false;
 }

 @Override
 public String toString() {
  return "Dog name: " + name;
 }
}
package com.model;

import javax.persistence.*;

@Entity
@NamedQuery(name="Address.FindAll", query="select a from Address a")
public class Address {

 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private int id;

 private String streetName;
 private int houseNumber;

 public Address() {

 }

 public Address(String streetName, int houseNumber) {
  this.streetName = streetName;
  this.houseNumber = houseNumber;
 }

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getStreetName() {
  return streetName;
 }

 public void setStreetName(String streetName) {
  this.streetName = streetName;
 }

 public int getHouseNumber() {
  return houseNumber;
 }

 public void setHouseNumber(int houseNumber) {
  this.houseNumber = houseNumber;
 }

 @Override
 public int hashCode() {
  return getId();
 }

 @Override
 public boolean equals(Object obj) {
  if (obj instanceof Address) {
   Address address = (Address) obj;
   return address.getId() == getId();
  }

  return false;
 }

 @Override
 public String toString() {
  return "Adress street name: " + streetName;
 }
}

在上面的代码中,我们获得了几个JPA关系作为示例。

贝娄(Bellow)是将处理事务和将写入HSQLDB数据库的数据的类:

package com.main;

import java.text.*;
import java.util.Date;

import javax.persistence.*;

import com.model.*;

public class CodeGenerator {
 private static EntityManagerFactory emf;
 private static EntityManager em;

 public static final String PERSON01_NAME = "John";
 public static final String PERSON02_NAME = "Mary";
 public static final String PERSON03_NAME = "Anna";
 public static final String PERSON04_NAME = "Joseph";
 public static final String PERSON05_NAME = "Mark";
 public static final String PERSON06_NAME = "I will not have any relationship";

 public static void startConnection() {
  emf = Persistence.createEntityManagerFactory("QueryTester");
  em = emf.createEntityManager();
  em.getTransaction().begin();
 }

 public static void closeConnection() {
  em.getTransaction().commit();
  emf.close();
 }

 public static void generateData() {
  int year = 1995;
  int month = 1;
  int day = 10;

  Dog dog01 = new Dog("Yellow", 3.5d, createNewDate(day, month, year));
  Dog dog02 = new Dog("Brown", 8.5d, createNewDate(++day, ++month, ++year));
  Dog dog03 = new Dog("Dark", 15.5d, createNewDate(++day, ++month, ++year));
  Dog dog04 = new Dog("Kaka", 4.3d, createNewDate(++day, ++month, ++year));
  Dog dog05 = new Dog("Pepe", 8.2d, createNewDate(++day, ++month, ++year));
  Dog dog06 = new Dog("Casillas", 6.1d, createNewDate(++day, ++month, ++year));
  Dog dog07 = new Dog("Fish", 6.7d, createNewDate(++day, ++month, ++year));
  Dog dog08 = new Dog("Lion", 3.1d, createNewDate(++day, ++month, ++year));
  Dog dog09 = new Dog("Cat", 5.5d, createNewDate(++day, ++month, ++year));
  Dog dog10 = new Dog("Java", 21.7d, createNewDate(++day, ++month, ++year));
  Dog dog11 = new Dog("JSF", 23.65d, createNewDate(++day, ++month, ++year));
  Dog dog12 = new Dog("VRaptor", 24.0d, createNewDate(++day, ++month, ++year));
  Dog dog13 = new Dog("Ferrari", 3.7d, createNewDate(++day, ++month, ++year));
  Dog dog14 = new Dog("Porshe", 1.33d, createNewDate(++day, ++month, ++year));
  Dog dog15 = new Dog("Bike", 4.44d, createNewDate(++day, ++month, ++year));
  Dog dog16 = new Dog("Rambo", 5.44d, createNewDate(++day, ++month, 2015));
  Dog dog17 = new Dog("Terminator", 3.88d, createNewDate(++day, ++month, 2016));
  Dog dog18 = new Dog("John McClan", 3.88d, createNewDate(++day, ++month, 2016));

  Person person01 = new Person(PERSON01_NAME, 33);
  person01.getDogs().add(dog01);
  person01.getDogs().add(dog02);
  person01.getDogs().add(dog03);
  person01.setAddress(new Address("Street A", 30));
  dog01.setPerson(person01);
  dog02.setPerson(person01);
  dog03.setPerson(person01);

  Person person02 = new Person(PERSON02_NAME, 27);
  person02.getDogs().add(dog04);
  person02.getDogs().add(dog05);
  person02.getDogs().add(dog06);
  person02.setAddress(new Address("Street B", 60));
  dog04.setPerson(person02);
  dog05.setPerson(person02);
  dog06.setPerson(person02);

  Person person03 = new Person(PERSON03_NAME, 7);
  person03.getDogs().add(dog07);
  person03.getDogs().add(dog08);
  person03.getDogs().add(dog09);
  person03.setAddress(new Address("Street B", 90));
  dog07.setPerson(person03);
  dog08.setPerson(person03);
  dog09.setPerson(person03);

  Person person04 = new Person(PERSON04_NAME, 43);
  person04.getDogs().add(dog10);
  person04.getDogs().add(dog11);
  person04.getDogs().add(dog12);
  person04.setAddress(new Address("Street C", 120));
  dog10.setPerson(person04);
  dog11.setPerson(person04);
  dog12.setPerson(person04);

  Person person05 = new Person(PERSON05_NAME, 70);
  person05.getDogs().add(dog13);
  person05.getDogs().add(dog14);
  person05.getDogs().add(dog15);
  person05.getDogs().add(dog16);
  person05.setAddress(new Address("Street D", 150));
  dog13.setPerson(person05);
  dog14.setPerson(person05);
  dog15.setPerson(person05);
  dog16.setPerson(person05);

  Person person06 = new Person(PERSON06_NAME, 45);

  em.persist(person01);
  em.persist(person02);
  em.persist(person03);
  em.persist(person04);
  em.persist(person05);
  em.persist(person06);

  em.persist(dog17);
  em.persist(dog18);

  em.flush();
 }

 private static Date createNewDate(int day, int month, int year) {
  SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
  try {
   return formatter.parse("" + day + "/" + month + "/" + year);
  } catch (ParseException e) {
   e.printStackTrace();
   return null;
  }
 }

 public static EntityManager getEntityManager() {
  return em;
 }
}

可以在以下代码的“ src / META-INF”文件夹中找到“ persistence.xml”文件:

<?xml version="1.0" encoding="UTF-8"?>

<persistence version="2.0"
 xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

 <persistence-unit name="QueryTester"
  transaction-type="RESOURCE_LOCAL">
  <provider>org.hibernate.ejb.HibernatePersistence</provider>

  <properties>
   <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver" />
   <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:mem:." />
   <property name="javax.persistence.jdbc.user" value="sa" />
   <property name="javax.persistence.jdbc.password" value="" />
   <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
   <property name="hibernate.connection.shutdown" value="true" />
   <property name="hibernate.hbm2ddl.auto" value="update" />
   <property name="hibernate.show_sql" value="false" />
            <property name="hibernate.format_sql" value="false"/>
  </properties>
 </persistence-unit>
</persistence>

抽象测试班

package com.main;

import javax.persistence.Query;

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import com.model.Person;

/**
 * @author Pro JPA 2 book
 * @Empowered by uaiHebert
 * 
 */
public abstract class AbstractQueryTester {

 protected static void populateParameters(Query query, String parameters) {
  for (String parameter : parameters.split(";")) {
   String parameterKey = parameter.split("-")[0];
   String parameterValue = parameter.split("-")[1];
   String parameterType = parameter.split("-")[2];

   query.setParameter(parameterKey, configureParameterValue(parameterValue, parameterType));
  }
 }

 private static Object configureParameterValue(String parameterValue, String parameterType) {
  if (parameterType.equalsIgnoreCase("integer")) {
   try {
    return Integer.parseInt(parameterValue);
   } catch (Exception e) {
    throw new IllegalArgumentException("Invalid parameter value as number: " + parameterValue);
   }
  }

  if (parameterType.equalsIgnoreCase("string")) {
   return parameterValue;
  }

  if (parameterType.equalsIgnoreCase("person")) {
   int personId;

   try {
    personId = Integer.valueOf(parameterValue);
   } catch (Exception e) {
    throw new IllegalArgumentException("Invalid parameter value as number: " + parameterValue);
   }

   return new Person(personId);
  }

  throw new IllegalArgumentException("Invalid parameter type: " + parameterType);
 }

 protected static void printResult(Object result) throws Exception {
  if (result == null) {
   System.out.print("NULL");
  } else if (result instanceof Object[]) {
   Object[] row = (Object[]) result;
   System.out.print("[");
   for (int i = 0; i < row.length; i++) {
    printResult(row[i]);
   }
   System.out.print("]");
  } else if (result instanceof Long || result instanceof Double || result instanceof String) {
   System.out.print(result.getClass().getName() + ": " + result);
  } else {
   System.out.print(ReflectionToStringBuilder.toString(result, ToStringStyle.SHORT_PREFIX_STYLE));
  }

  System.out.println();
 } 
}

关于上面的代码:

  • populateParameters方法将自动填充所有查询参数。 如果需要,Eclipse控制台将要求开发人员键入查询信息和查询参数。 查询参数应遵循以下语法要求:
    • 0个参数:只需按“ Enter”
  • configureParameterValue方法会将参数值“广播”为查询所需的正确类型。 它允许原始值和类。
  • printResult方法将显示查询结果。

动态查询测试

package com.main;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;

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

/**
 * @author Pro JPA 2 book
 * @Empowered by uaiHebert
 * 
 */
public class DynamicQueryTester extends AbstractQueryTester {
 public static void main(String[] args) throws IOException {
  CodeGenerator.startConnection();

  CodeGenerator.generateData();

  EntityManager em = CodeGenerator.getEntityManager();

  BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

  for (;;) {
   System.out.print("Type your JPQL and press Enter > ");
   String dynamicQuery = reader.readLine();

   if (dynamicQuery.equals("quit")) {
    break;
   }

   if (dynamicQuery.length() == 0) {
    continue;
   }

   System.out.println("Type the namedQuery parameters.");
   System.out.println("All paramters should be like: id-2-integer;name-John-string");
   System.out.println("Or just press enter for 0 parameters");
   String parameters = reader.readLine();

   try {
    Query query = em.createQuery(dynamicQuery);

    if (parameters.length() > 0) {
     populateParameters(query, parameters);
    }

    @SuppressWarnings("rawtypes")
    List result = query.getResultList();

    if (result.size() > 0) {
     int count = 0;
     for (Object o : result) {
      System.out.print(++count + " ");
      printResult(o);
     }
    } else {
     System.out.println("0 results returned");
    }
   } catch (Exception e) {
    e.printStackTrace();
   }
  }

  CodeGenerator.closeConnection();
 }
}

上面的代码将启动一个事务,在运行时内存中创建数据库数据,并允许开发人员测试任何类型的动态查询。 要测试JPQL / HQL,开发人员只需在控制台中键入查询代码。

要结束循环,请不要键入任何查询数据,只需键入“ quit”并按“ Enter”即可。

NamedQuery测试
 

package com.main;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;

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

/**
 * @author Pro JPA 2 book
 * @Empowered by uaiHebert
 * 
 */
public class NamedQueryTester extends AbstractQueryTester {
 public static void main(String[] args) throws IOException {
  CodeGenerator.startConnection();

  CodeGenerator.generateData();

  EntityManager em = CodeGenerator.getEntityManager();

  BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

  for (;;) {
   System.out.print("Type the NamedQuery name > ");
   String namedQueryName = reader.readLine();

   if (namedQueryName.equals("quit")) {
    break;
   }

   if (namedQueryName.length() == 0) {
    continue;
   }

   System.out.println("Type the namedQuery parameters.");
   System.out.println("Press enter for 0 parameters");
   System.out.println("Or type all paramters like: id-2,name-4");
   String parameters = reader.readLine();

   try {
    Query query = em.createNamedQuery(namedQueryName);

    if (parameters.length() > 0) {
     populateParameters(query, parameters);
    }

    @SuppressWarnings("rawtypes")
    List result = query.getResultList();

    if (result.size() > 0) {
     int count = 0;
     for (Object o : result) {
      System.out.print(++count + " ");
      printResult(o);
     }
    } else {
     System.out.println("0 results returned");
    }
   } catch (Exception e) {
    System.err.println(e.getClass() + e.getMessage());
   }
  }

  CodeGenerator.closeConnection();
 }
}

上面的代码将启动一个事务,在运行时内存中创建数据库数据,并允许测试在模型类中配置的NamedQueries。 要测试NamedQueries,只需在控制台中键入其名称。

要结束循环,请不要键入任何NamedQuery名称,只需键入“ quit”并按“ Enter”即可。

运行应用程序

运行类DynamicQueryTester,然后在控制台中键入以下文本:“ 从Person p中选择p ”。 按Enter键两次,以下文本将出现在控制台中:

在第一个“ Enter”键上,将显示一条消息,询问是否有参数。

在控制台中键入:“ 从Person p中选择p,其中p.age>:age ”,然后按“ Enter”。 输入参数:“ age-69-integer ”。 按回车,将显示以下结果:

要完成正在运行的代码,请输入单词“ quit”,然后按“ Enter”按钮。

现在运行类NamedQueryTester的代码。

在控制台中键入NamedQuery名称“ Dog.FindByPerson”,然后按Enter。 输入“ personObject-1-person”参数,将显示以下结果:

将此邮政编码与您的应用程序代码一起使用

您可以通过两种方式使用本文的代码:将应用程序模型类添加到本文的项目中,或在应用程序中使用该项目的主包中的代码。

将您的模型类添加到这篇文章的项目中

  • 将模型类复制到“ com.model”包中。
  • 设置persistence.xml以访问数据库

使用应用程序主包中的代码

  • 设置在CodeGenerator类中找到的PersistenceUnit。
  • 使用在libs文件夹中找到的Apache库:“ commons-lang3-3-1.jar ”。

对于这两种方法,都需要以下步骤:

  • 编辑方法“ AbstractQueryTester.configureParameterValue ”以接受将与查询一起使用的所有属性值/类型/类。
  • 将“ hibernate.hbm2ddl.auto ”配置编辑为“ none”或“ validate”。 该配置位于“ persistence.xml ”文件中。
  • 仅在CodeGenerator类中调用方法以启动/关闭连接。

提案

在下面,您会发现一些与此代码有关的建议:

  • 使用反射技术在“ AbstractQueryTester.configureParameterValue ”方法中创建类。
  • 提交后,应用Jenkins验证某些JPQL是否具有正确的语法。

结束

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

单击此处下载此帖子的源代码

如果您有任何疑问/建议,请将其发布。

参考:uaiHebert博客上, 如何从我们的JCG合作伙伴 Hebert Coelho进行部署而无需部署即可测试JPQL / HQL


翻译自: https://www.javacodegeeks.com/2012/07/test-jpql-hql-without-deploy.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值