通过使用 Java 持久性 API,可以为这些预定义的查询创建命名查询。代码可通过“查询 API”来使用这些命名查询。如果要将某个查询运行几次并仅为其设置参数,则可以使用命名查询。这些查询通常称为静态查询。您可以为所有预定义的查询执行此操作。
使用命名查询是一种很好的做法,原因如下:
命名查询是线程安全的,因为它们必须可供很多类和实例重复使用。请注意,应指定命名查询名称的范围,这对于避免名称冲突至关重要。使用标注来定义命名查询时,名称范围在持久性单元中是可见的。可以使用部署描述符使名称在应用程序范围内可见。在代码中使用命名查询时,我们使用在类的名称前面加前缀的命名约定;在这种命名约定中,将命名查询定义在查询名称的前部。
只能在某些特定的类上定义命名查询。您只能在实体和映射的超类上定义和放置命名查询。
请注意,命名查询可用于本地 SQL 查询以及使用 Java 持久性查询语言表示的查询。
之前的代码 | 使用命名查询后的代码 |
public class MyDataFacade ... { query.setParameter
("cID",catID);
List<Item> items =
query.getResultList(); 请注意,此代码可以将查询放在字符串常量中,但仍然没有对其进行预编译。 |
请注意,在类上使用了标注:
@NamedQuery( MyEntity. getItemsPerProductCategory",
public class MyDataFacade ... { private EntityManager em; public
List<Items> getItems(String catID) { |
正像从上面的示例中所看到的那样,使用命名查询的重构代码要相对简单一些。
一个较小的命名查询设计选择是,使用位置参数还是使用命名参数。命名参数是首选的,因为它可使代码更易于理解和维护。上面的示例代码说明了在 query="SELECT i FROM Item i WHERE i.product.categoryID LIKE :cID
"
中使用命名参数 ":cID
" 的命名查询,随后调用 query.setParameter("cID",catID)
对其进行了设置。这非常简单明了。
NamedQueries
标注来创建类中使用的所有命名查询的列表。下面是如何使用此标注的示例。请注意,在类上使用了该标注:
@NamedQueries(
{
@NamedQuery(
name="MyEntity.getItemsPerProductCategory",
query="SELECT i FROM Item i WHERE i.productID.categoryID LIKE :cID"
),
@NamedQuery(
name="MyEntity.getAllZipCityState",
query="SELECT z FROM ZipLocation z"
)
}
)
@Entity
public class MyEntity {...
然后,代码只需按通常方式使用每个命名查询即可,
虽然看上去命名查询的语法不太直观,实际上它是相当简单的。public class MyDataFacade ... {
...
Query query = em.createNamedQuery("MyEntity.getItemsPerProductCategory");
NamedQuery
的 JavadocNamedQueries
的 Javadoc