|
此版本仍在开发中,尚未被视为稳定版。如需使用最新的稳定版本,请访问 Spring Data JPA 4.0.4! |
存储过程
JPA 2.1 规范引入了通过 JPA 标准查询 API 调用存储过程的支持。
我们引入了 @Procedure 注解,用于在仓库方法上声明存储过程的元数据。
以下示例使用了以下存储过程:
plus1inout 存储过程的定义。/;
DROP procedure IF EXISTS plus1inout
/;
CREATE procedure plus1inout (IN arg int, OUT res int)
BEGIN ATOMIC
set res = arg + 1;
END
/;
存储过程的元数据可以通过在实体类型上使用 NamedStoredProcedureQuery 注解进行配置。
@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 {}
请注意,@NamedStoredProcedureQuery 为存储过程定义了两个不同的名称。
name 是 JPA 使用的名称。procedureName 是该存储过程在数据库中的名称。
你可以通过多种方式从仓库方法中引用存储过程。
要调用的存储过程可以直接通过 value 注解的 procedureName 或 @Procedure 属性来定义。
这种方式直接引用数据库中的存储过程,并忽略通过 @NamedStoredProcedureQuery 进行的任何配置。
或者,您可以将 @NamedStoredProcedureQuery.name 属性指定为 @Procedure.name 属性。
如果未配置 value、procedureName 和 name 中的任何一个,则会使用仓库方法的名称作为 name 属性。
以下示例展示了如何引用一个显式映射的存储过程:
@Procedure("plus1inout")
Integer explicitlyNamedPlus1inout(Integer arg);
以下示例与前一个示例等效,但使用了 procedureName 别名:
procedureName 别名引用数据库中名为“plus1inout”的隐式映射存储过程。@Procedure(procedureName = "plus1inout")
Integer callPlus1InOut(Integer arg);
以下内容再次等同于前两种方式,但使用的是方法名而非显式的注解属性。
EntityManager 中引用隐式映射的命名存储过程 "User.plus1"。@Procedure
Integer plus1inout(@Param("arg") Integer arg);
以下示例展示了如何通过引用 @NamedStoredProcedureQuery.name 属性来调用存储过程。
EntityManager 中引用显式映射的命名存储过程 "User.plus1IO"。@Procedure(name = "User.plus1IO")
Integer entityAnnotatedCustomNamedProcedurePlus1IO(@Param("arg") Integer arg);
如果被调用的存储过程具有单个输出参数,则该参数可以作为方法的返回值返回。
如果在 @NamedStoredProcedureQuery 注解中指定了多个输出参数,则这些参数可以以 Map 的形式返回,其中键为 @NamedStoredProcedureQuery 注解中指定的参数名称。
请注意,如果存储过程返回一个ResultSet,那么任何OUT参数都会被省略,因为 Java 方法只能返回单个返回值,除非该方法声明返回类型为Map。 |
以下示例展示了如何获取多个 OUT 参数,前提是存储过程具有多个 OUT 参数,并且已注册为 @NamedStoredProcedureQuery。@NamedStoredProcedureQuery 的注册是必需的,以便提供参数元数据。
@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 {}
@Procedure(name = "User.multiple_out_parameters")
Map<String, Object> returnsMultipleOutParameters(@Param("arg") Integer arg);