我们在数据库中进行复杂的操作时会用到存储过程,在数据库中存储过程是可被外部调用的一种数据对象,可以用来封装复杂的sql逻辑,那么我们在Spring Data JPA中是如何调用存储过程的呢?这就需要我们今天要讲的@Procedure注解了
1、首先我们来看一下@Procedure注解的源码,通过源码可以学习JPA对存储过程的支持。下图中value表示数据库里面存储过程的名称,procedureName也是数据库里面存储过程的名称。
2、接下来我们在数据库中创建一个存储过程,这个存储过程有两个参数,分别是输入和输出。
CREATE PROCEDURE `procinout`(IN arg int, OUT res int) BEGIN SELECT(arg + 10) into res; END
我们还可以创建有一个只有输入的存储过程,如下所示:
CREATE PROCEDURE `procin`(IN arg int) BEGIN SELECT(arg + 10) into arg; END
3、存储过程的调用,在UserRepository中,使用@Procedure(name="procinout")和@Procedure(name="procin")去调用存储过程。
package cn.zh.dao; import cn.zh.domain.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.query.Procedure; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; @Repository public interface UserRepository extends JpaRepository<User,Long> ,JpaSpecificationExecutor<User> { @Procedure(name = "procinout") int procInOut(@Param("arg") Integer arg); @Procedure(procedureName = "procin") void procIn(@Param("arg") Integer arg); }
4、在User实体类中存储过程需要使用@NamedStoredProcedureQueries注解,将存储过程绑定到JPA的数据库表中,procedureName是存储过程的名字,name是JPA中存储过程的名字,写成一致即可。@StoredProcedureParameter注解指定存储过程中使用的IN、/OUT参数。
package cn.zh.domain; import javax.persistence.*; @Entity @NamedStoredProcedureQueries( {@NamedStoredProcedureQuery(name = "procinout", procedureName = "procinout", parameters={ @StoredProcedureParameter(mode=ParameterMode.IN,name="arg",type=Integer.class), @StoredProcedureParameter(mode=ParameterMode.OUT,name="res",type=Integer.class) }) ,@NamedStoredProcedureQuery(name="procin", procedureName="procin", parameters = { @StoredProcedureParameter(mode=ParameterMode.IN,type=Integer.class,name="arg")})}) public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY)//自动增递 private Long id; private String name; private String email; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", email='" + email + '\'' + '}'; } }
controller类:
package cn.zh.controller; import cn.zh.dao.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RequestMapping("/user") @RestController public class UserController { @Autowired private UserRepository userRepository; @RequestMapping("/procInOut") public Integer proceInOut(Integer arg){ return userRepository.procInOut(arg); } @RequestMapping("/procIn") public void proceIn(Integer arg){ userRepository.procIn(arg); } }