欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > IT业 > JPA与存储过程的完美结合

JPA与存储过程的完美结合

2025/2/24 14:41:15 来源:https://blog.csdn.net/2501_90323865/article/details/145803684  浏览:    关键词:JPA与存储过程的完美结合

在现代的Java开发中,JPA(Java Persistence API)已经成为ORM(对象关系映射)的主流选择之一。它不仅简化了数据库操作,还提供了强大的功能来与数据库交互。今天,我们将深入探讨如何通过@NamedStoredProcedureQuery注解在JPA中使用数据库存储过程,并通过一个完整的示例来展示其强大的功能。

一、@NamedStoredProcedureQuery简介

@NamedStoredProcedureQuery是JPA提供的一个注解,用于在实体类中声明可复用的数据库存储过程。通过这个注解,我们可以将存储过程与实体类关联起来,并在代码中方便地调用这些存储过程。

以下是@NamedStoredProcedureQuery注解的主要属性:

  • name:用于引用的存储过程名称。
  • procedureName:数据库中存储过程的实际名称。
  • parameters:存储过程的参数信息,包括参数名、类型和模式(如IN、OUT、INOUT、REF_CURSOR)。
  • resultClasses:存储过程返回的结果集对应的Java类。
  • resultSetMappings:存储过程返回的结果集映射。
  • hints:查询的属性和提示。

二、示例:使用Oracle存储过程

为了更好地理解@NamedStoredProcedureQuery的使用,我们将通过一个完整的示例来展示如何在JPA中调用Oracle数据库的存储过程。这个示例包括两个存储过程:一个用于将记录从主表移动到历史表,另一个用于查询历史表中的记录。

1. 数据库准备

首先,我们需要在Oracle数据库中创建表和存储过程。以下是SQL脚本:

DROP TABLE PERSON;
DROP SEQUENCE SQ_PERSON;
CREATE TABLE PERSON (ID NUMBER(19),FIRST_NAME VARCHAR(255),LAST_NAME VARCHAR(255),ADDRESS VARCHAR(255),PRIMARY KEY (ID)
);
CREATE SEQUENCE SQ_PERSON MINVALUE 1 START WITH 1 INCREMENT BY 1 CACHE 10;DROP TABLE PERSON_HISTORY;
CREATE TABLE PERSON_HISTORY AS SELECT * FROM PERSON WHERE 1=0;CREATE OR REPLACE PROCEDURE MOVE_TO_HISTORY(person_id_in IN NUMBER, msg_out OUT VARCHAR2)
IStemp_count NUMBER := -1;
BEGINSELECT COUNT(*) INTO temp_count FROM PERSON WHERE ID = person_id_in;IF temp_count > 0 THENINSERT INTO PERSON_HISTORY SELECT * FROM PERSON WHERE ID = person_id_in;msg_out := 'Person with id: ' || person_id_in || ' moved to History table. Update count: ' || SQL%ROWCOUNT;DELETE FROM PERSON WHERE ID = person_id_in;ELSEmsg_out := 'No Person Exists with id: ' || person_id_in;END IF;
END;
/CREATE OR REPLACE PROCEDURE FETCH_PERSON_HISTORY(history_cursor OUT SYS_REFCURSOR)
IS
BEGINOPEN history_cursor FOR SELECT * FROM PERSON_HISTORY;
END;
/
2. 实体类定义

接下来,我们定义一个Person实体类,并使用@NamedStoredProcedureQuery注解来声明存储过程。

import javax.persistence.*;
import java.util.Objects;@Entity
@NamedStoredProcedureQuery(name = Person.NamedQuery_MoveToHistory,procedureName = "MOVE_TO_HISTORY",parameters = {@StoredProcedureParameter(name = "person_id_in", type = Long.class, mode = ParameterMode.IN),@StoredProcedureParameter(name = "msg_out", type = String.class, mode = ParameterMode.OUT)}
)
@NamedStoredProcedureQuery(name = Person.NamedQuery_FetchFromHistory,procedureName = "FETCH_PERSON_HISTORY",resultClasses = {Person.class},parameters = {@StoredProcedureParameter(name = "history_cursor", type = void.class, mode = ParameterMode.REF_CURSOR)}
)
public class Person {public static final String NamedQuery_MoveToHistory = "moveToHistory";public static final String NamedQuery_FetchFromHistory = "fetchFromHistory";@Id@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SQ_PERSON")@SequenceGenerator(sequenceName = "SQ_PERSON", allocationSize = 1, name = "SQ_PERSON")private long id;@Column(name = "FIRST_NAME")private String firstName;@Column(name = "LAST_NAME")private String lastName;private String address;// Getters and Setterspublic long getId() {return id;}public void setId(long id) {this.id = id;}public String getFirstName() {return firstName;}public void setFirstName(String firstName) {this.firstName = firstName;}public String getLastName() {return lastName;}public void setLastName(String lastName) {this.lastName = lastName;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}@Overridepublic String toString() {return "Person{" +"id=" + id +", firstName='" + firstName + '\'' +", lastName='" + lastName + '\'' +", address='" + address + '\'' +'}';}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Person person = (Person) o;return id == person.id &&Objects.equals(firstName, person.firstName) &&Objects.equals(lastName, person.lastName) &&Objects.equals(address, person.address);}@Overridepublic int hashCode() {return Objects.hash(id, firstName, lastName, address);}
}
3. 调用存储过程

最后,我们通过EntityManager调用这些存储过程。以下是主类的代码:

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.StoredProcedureQuery;
import java.util.List;public class ExampleMain {private static EntityManagerFactory entityManagerFactory =Persistence.createEntityManagerFactory("example-unit");public static void main(String[] args) {try {reset();persistEntities();findAllEmployeeEntities();movePersonToHistoryByName("Dana");movePersonToHistoryByName("Mike");fetchPersonHistory();} finally {entityManagerFactory.close();}}private static void fetchPersonHistory() {System.out.println("-- Fetching person History --");EntityManager entityManager = entityManagerFactory.createEntityManager();StoredProcedureQuery procedureQuery =entityManager.createNamedStoredProcedureQuery(Person.NamedQuery_FetchFromHistory);procedureQuery.execute();@SuppressWarnings("unchecked")List<Person> resultList = procedureQuery.getResultList();resultList.forEach(System.out::println);}private static void movePersonToHistoryByName(String name) {System.out.printf("-- Moving person to history table name: %s --%n", name);EntityManager entityManager = entityManagerFactory.createEntityManager();// get person idTypedQuery<Long> query = entityManager.createQuery("SELECT p.id FROM Person p WHERE p.firstName = :firstName", Long.class);query.setParameter("firstName", name);Long personId = query.getSingleResult();// stored procedureStoredProcedureQuery procedureQuery = entityManager.createNamedStoredProcedureQuery(Person.NamedQuery_MoveToHistory);entityManager.getTransaction().begin();procedureQuery.setParameter("person_id_in", personId);procedureQuery.execute();Object msg_out = procedureQuery.getOutputParameterValue("msg_out");System.out.println("Out msg= " + msg_out);entityManager.getTransaction().commit();}private static void findAllEmployeeEntities() {System.out.println("-- all Person entities -  --");EntityManager em = entityManagerFactory.createEntityManager();TypedQuery<Person> query = em.createQuery("SELECT p from Person p", Person.class);List<Person> resultList = query.getResultList();resultList.forEach(System.out::println);em.close();}private static void persistEntities() {Person person1 = new Person();person1.setFirstName("Dana");person1.setLastName("Whitley");person1.setAddress("464 Gorsuch Drive");Person person2 = new Person();person2.setFirstName("Robin");person2.setLastName("Cash");person2.setAddress("64 Zella Park");Person person3 = new Person();person3.setFirstName("Chary");person3.setLastName("Mess");person3.setAddress("112 Yellow Hill");Person person4 = new Person();person4.setFirstName("Rose");person4.setLastName("Kantata");person4.setAddress("2736 Kooter Lane");Person person5 = new Person();person5.setFirstName("Mike");person5.setLastName("Togglie");person5.setAddress("111 Cool Dr");EntityManager em = entityManagerFactory.createEntityManager();em.getTransaction().begin();em.persist(person1);em.persist(person2);em.persist(person3);em.persist(person4);em.persist(person5);em.getTransaction().commit();em.close();}private static void reset() {EntityManager em = entityManagerFactory.createEntityManager();em.getTransaction().begin

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词