跳到主要内容

存储过程

DeepSeek V3 中英对照 Stored Procedures

JPA 2.1 规范引入了通过使用 JPA 条件查询 API 调用存储过程的支持。我们引入了 @Procedure 注解,用于在仓库方法上声明存储过程的元数据。

以下示例使用了以下存储过程:

示例 1. HSQL DB 中 plus1inout 过程的定义。

/;
DROP procedure IF EXISTS plus1inout
/;
CREATE procedure plus1inout (IN arg int, OUT res int)
BEGIN ATOMIC
set res = arg + 1;
END
/;
sql

存储过程的元数据可以通过在实体类型上使用 NamedStoredProcedureQuery 注解进行配置。

示例 2. 实体上的存储过程元数据定义。

@Entity
@NamedStoredProcedureQuery(name = "User.plus1", procedureName = "plus1inout", parameters = {
@StoredProcedureParameter(mode = ParameterMode.IN, name = "arg", type = Integer.class),
@StoredProcedureParameter(mode = ParameterMode.OUT, name = "res", type = Integer.class) })
public class User {}
java

请注意,@NamedStoredProcedureQuery 为存储过程定义了两个不同的名称。name 是 JPA 使用的名称,而 procedureName 是数据库中存储过程的名称。

你可以通过多种方式在仓库方法中引用存储过程。要调用的存储过程可以直接通过使用 @Procedure 注解的 valueprocedureName 属性来定义。这直接引用了数据库中的存储过程,并忽略通过 @NamedStoredProcedureQuery 进行的任何配置。

或者,你可以将 @NamedStoredProcedureQuery.name 属性指定为 @Procedure.name 属性。如果 valueprocedureNamename 均未配置,则使用仓库方法的名称作为 name 属性。

以下示例展示了如何引用显式映射的过程:

示例 3. 在数据库中引用显式映射的名为 "plus1inout" 的过程。

@Procedure("plus1inout")
Integer explicitlyNamedPlus1inout(Integer arg);
java

以下示例与之前的示例等效,但使用了 procedureName 别名:

示例 4. 通过 procedureName 别名引用数据库中名为 "plus1inout" 的隐式映射过程。

@Procedure(procedureName = "plus1inout")
Integer callPlus1InOut(Integer arg);
java

以下内容再次等同于前两种情况,但使用的是方法名称而不是显式的注解属性。

示例 5. 通过使用方法名在 EntityManager 中引用隐式映射的命名存储过程 "User.plus1"。

@Procedure
Integer plus1inout(@Param("arg") Integer arg);
java

以下示例展示了如何通过引用 @NamedStoredProcedureQuery.name 属性来引用存储过程。

示例 6. 在 EntityManager 中引用显式映射的命名存储过程 "User.plus1IO"。

@Procedure(name = "User.plus1IO")
Integer entityAnnotatedCustomNamedProcedurePlus1IO(@Param("arg") Integer arg);
java

如果被调用的存储过程只有一个输出参数,该参数可以作为方法的返回值返回。如果在 @NamedStoredProcedureQuery 注解中指定了多个输出参数,这些参数可以作为一个 Map 返回,其中键是 @NamedStoredProcedureQuery 注解中给定的参数名称。

备注

请注意,如果存储过程返回一个 ResultSet,那么任何 OUT 参数都会被省略,因为 Java 只能返回单个方法返回值,除非方法声明为返回 Map 类型。

以下示例展示了如果存储过程有多个 OUT 参数并且注册为 @NamedStoredProcedureQuery,如何获取多个 OUT 参数。@NamedStoredProcedureQuery 注册是为了提供参数元数据。

示例 7. 实体上的存储过程元数据定义。

@Entity
@NamedStoredProcedureQuery(name = "User.multiple_out_parameters", procedureName = "multiple_out_parameters", parameters = {
@StoredProcedureParameter(mode = ParameterMode.IN, name = "arg", type = Integer.class),
@StoredProcedureParameter(mode = ParameterMode.REF_CURSOR, name = "some_cursor", type = void.class),
@StoredProcedureParameter(mode = ParameterMode.OUT, name = "res", type = Integer.class) })
public class User {}
java

示例 8. 返回多个 OUT 参数

@Procedure(name = "User.multiple_out_parameters")
Map<String, Object> returnsMultipleOutParameters(@Param("arg") Integer arg);
java