当前位置: 首页 > 工具软件 > Grails > 使用案例 >

面向初学者的Grails教程-HQL查询(executeQuery和executeUpdate)

易瀚漠
2023-12-01

该Grails教程将教授使用HQL的基础知识。 Grails支持动态查找器,这使执行简单的数据库查询变得很方便。 但是对于更复杂的情况,Grails提供了Criteria API和HQL。 本教程将重点讨论后者。

介绍

众所周知,Grails位于Spring和Hibernate(这是两种最受欢迎​​的Java框架)的顶部。 Hibernate用作Grails对象关系映射(GORM)的基础技术。

Hibernate与数据库无关。 这意味着,由于Grails基于它,因此我们可以编写与大多数流行数据库兼容的应用程序。 我们不需要为每个可能的数据库编写不同的查询。

执行数据库查询的最简单方法是通过动态查找器。 简单而直观。 查看我以前的帖子 ,以获取有关此主题的教程。 但是动态查找器非常有限。 它可能不适用于复杂的要求以及开发人员需要较低控制级别的情况。 HQL是非常好的替代方法,因为它与SQL非常相似。

HQL完全面向对象,并且了解继承,多态性和关联。 使用它将提供一个非常强大且灵活的API,同时又可以使您的应用程序与数据库无关。 在Grails中,有两种域方法可用于调用HQL

  • executeQuery –执行HQL查询(SELECT操作)
  • executeUpdate –使用DML样式的操作(UPDATE和DELETE)更新数据库

executeQuery

这是一个示例Domain类,我们将从中进行查询:

package asia.grails.test
class Person {
    String firstName
    String lastName
    int age
    static constraints = {
    }
}

检索所有域对象

这是从数据库检索所有Person对象的代码:

def listOfAllPerson = Person.executeQuery("from Person")

注意:

  • executeQuery是Domain类的一种方法,用于检索信息(SELECT语句)
  • 与SQL类似,需要from标识符
  • 无需指定表,而是在from关键字之后指定域类。 我们也可以这样写查询
    def listOfAllPerson = Person.executeQuery("from asia.grails.test.Person")
  • 不指定select子句是有效的。 默认情况下,它将返回指定Domain类的对象实例。 在该示例中,它将返回所有Person对象的列表。

这是我们如何使用结果的示例代码

listOfAllPerson.each { person ->
    println "First Name = ${person.firstName}"
    println "Last Name = ${person.lastName}"
    println "Age = ${person.age}"
}

由于listOfAllPerson是Person实例的列表,因此我们可以对其进行迭代并打印详细信息。

选择子句

当显式使用select子句时,HQL将不返回域对象的列表。 相反,它将返回一个二维列表。 这是一个示例,假定数据库中至少有1条记录:

def list = Person.executeQuery("select firstName, lastName from Person")
def firstPerson = list[0]
def firstName = firstPerson[0]
def lastName = firstPerson[1]
println "First Name = ${firstName}"
println "Last Name = ${lastName}"

变量列表将被分配一个项目列表。 每个项目都是一个列表,对应于select子句中枚举的值。

还可以这样编写代码,以帮助可视化数据结构:

def list = Person.executeQuery("select firstName, lastName from Person")
def firstName = list[0][0]
def lastName = list[0][1]
println "First Name = ${firstName}"
println "Last Name = ${lastName}"

Where子句

与SQL一样,我们可以使用where子句过滤查询结果。 这里有些例子:

母鹿的人

def peopleWithSurnameDoe = Person.executeQuery("from Person where lastName = 'Doe'")

至少18岁的人

def adults = Person.executeQuery("from Person where age >= 18")

名字包含John的人

def peopleWithFirstNameLikeJohn = Person.executeQuery("from Person where firstName like '%John%'")

组条款

组子句也是允许的。 该行为类似于SQL。 这是一个例子:

def list = Person.executeQuery("select age, count(*) from Person group by age")
list.each { item ->
    def age = item[0]
    def count = item[1]
    println "There are ${count} people with age ${age} years old"
}

这将打印出表格中找到的所有年龄以及该年龄的人数。

有条款

Haven子句可用于过滤出分组依据的结果。 这是一个例子:

def list = Person.executeQuery(
    "select age, count(*) from Person group by age having count(*) > 1")
    list.each { item ->
        def age = item[0]
        def count = item[1]
    println "There are ${count} people with age ${age} years old"
}

如果年龄组中有1个以上的人,它将打印表中找到的所有年龄以及具有该年龄的人数。

分页

一次检索所有表中的所有记录对性能不利。 分页结果更有效。 例如,一次获取10条记录。 这是有关如何执行此操作的代码示例:

def listPage1 = Person.executeQuery("from Person order by id", [offset:0, max:10])
def listPage2 = Person.executeQuery("from Person order by id", [offset:10, max:10])
def listPage3 = Person.executeQuery("from Person order by id", [offset:20, max:10])

参数max通知GORM仅获取最多10条记录。 偏移量表示在读取第一个结果之前要跳过多少条记录。

  • 在第1页上,我们不会跳过任何记录并获得前10个结果
  • 在第2页上,我们跳过前10条记录,而获得第11至20条记录。
  • 在第3页上,我们跳过前20条记录,而获得第21至30条记录。

GORM / Hibernate会根据数据库将分页信息转换为正确的SQL语法。

注意:在对结果进行分页时,通常最好使用order by子句,否则大多数数据库无法保证每个查询之间的记录排序方式。

清单参数

HQL语句可以具有参数。 这是一个例子:

def result = Person.executeQuery(
    "from Person where firstName = ? and lastName = ?", ['John', 'Doe'])

参数可以作为列表传递。 第一个参数(John)用于第一个问号,第二个参数(Doe)用于第二个问号,依此类推。

结果也可以分页

def result = Person.executeQuery(
    "from Person where firstName = ? and lastName = ?", ['John', 'Doe'], [offset:0, max:5])

命名参数

提供列表参数通常很难读取并且容易出错。 使用命名参数更容易。 例如:

def result = Person.executeQuery(
    "from Person where firstName = :searchFirstName and lastName = :searchLastName", 
    [searchFirstName:'John', searchLastName:'Doe'])

冒号表示命名参数变量。 然后可以将值作为值的映射传递。

结果也可以分页:

def result = Person.executeQuery(
    "from Person where firstName = :searchFirstName and lastName = :searchLastName",
    [searchFirstName:'John', searchLastName:'Doe'], [offset:0, max:5])

这是一个简短的版本:

def result = Person.executeQuery(
    "from Person where firstName = :searchFirstName and lastName = :searchLastName",
    [searchFirstName:'John', searchLastName:'Doe'], [offset:0, max:5])

如何执行JOIN

这是一对多关系域类的示例:

package asia.grails.test
class Purchase {
    static hasMany = [items:PurchaseItem]
    String customer
    Date dateOfPurchase
    double price
}
package asia.grails.test
class PurchaseItem {
    static belongsTo = Purchase
    Purchase parentPurchase
    String product
    double price
    int quantity
}

这是连接两个表的示例代码:

def customerWhoBoughtPencils = Purchase.executeQuery(
    "select p.customer from Purchase p join p.items i where i.product = 'Pencil' ")

这将返回所有购买铅笔的客户

executeUpdate

我们可以使用executeUpdate更新或删除记录。 特别是在处理大量记录时,这有时会更有效率。

删除

以下是一些有关如何使用executeUpdated删除记录的示例。

删除数据库中的所有人员记录

Purchase.executeUpdate("delete Person")

这是删除名字为John的人的不同方法

Person.executeUpdate("delete Person where firstName = 'John'")
Person.executeUpdate("delete Person where firstName = ? ", ['John'])
Person.executeUpdate("delete Person where firstName = :firstNameToDelete ", [firstNameToDelete:'John'])

更新资料

以下是一些有关如何使用executeUpdated删除记录的示例。

以下是关于如何使所有人都达到15岁的不同方法

Person.executeUpdate("update Person set age = 15")
Person.executeUpdate("update Person set age = ?", [15])
Person.executeUpdate("update Person set age = :newAge", [newAge:15])

以下是将John Doe的年龄设置为15岁的不同方法。

Person.executeUpdate(
    "update Person set age = 15 where firstName = 'John' and lastName = 'Doe'")
Person.executeUpdate(
    "update Person set age = ? where firstName = ? and lastName = ?", [15, 'John', 'Doe'])
Person.executeUpdate(
    "update Person set age = :newAge where firstName = :firstNameToSearch and lastName = :lastNameToSearch",
    [newAge:15, firstNameToSearch:'John', lastNameToSearch:'Doe'])

翻译自: https://www.javacodegeeks.com/2015/01/grails-tutorial-for-beginners-hql-queries-executequery-and-executeupdate.html

 类似资料: