StoredProcedureQuery getResultList () не возвращает ключи данных (заголовки столбцов) - PullRequest
0 голосов
/ 25 марта 2019

Я пытаюсь получить результаты от хранимых процедур в базе данных Oracle. Эти процедуры являются частью пакетов в базе данных, поэтому у меня нет видимости для реализации этих процедур. Поэтому, если я не выполню процедуры с действительными входными данными, у меня не будет видимости возвращаемых заголовков столбцов. Я использую StoredProcedureQuery для выполнения этих процедур в моем коде. Проблема заключается в том, что при отображении результата в POJO мне приходится полагаться на порядок столбцов, возвращаемых для отображения полей POJO.
Я знаю, что одним из решений является определение SQLResultSetMappings. Но так как я не знаю, какие таблицы запрашиваются для результатов, я не могу сопоставить его с сущностями. Есть ли другой метод, который возвращает результат с заголовками столбцов? Вот мое объявление процедуры:

@NamedStoredProcedureQuery(
   name = "myStoredProcedure",
   procedureName = "MYUSER.PKG_MY_PACKAGE.MY_STORED_PROCEDURE",
   parameters = {
      @StoredProcedureParameter(mode = ParameterMode.IN, type = Long.class, name = "iMyNumber"),
      @StoredProcedureParameter(mode = ParameterMode.OUT, type = Long.class, name = "oRetVal"),
      @StoredProcedureParameter(mode = ParameterMode.OUT, type = String.class, name = "oRetTxt"),
      @StoredProcedureParameter(mode = ParameterMode.REF_CURSOR, type = void.class, name = "oRetCsr"),
   }
)

А вот мой код DAO:

public List<MyQueryResultModel> getMyQueryResults(Long myNum) {
  StoredProcedureQuery query = this.entityManager.createNamedStoredProcedureQuery("myStoredProcedure");
  query.setParameter("iMyNumber", myNum);
  try {
    List<Object[]> results = query.getResultList();
    List<MyQueryResultModel> myQueryResults = new ArrayList<>();
    for (Object[] result : results) {
      MyQueryResultModel myQueryResult = new MyQueryResultModel();
      myQueryResult.setId(objectToString(result[0]));
      myQueryResult.setName(objectToString(result[1]));
      myQueryResult.setDetails(objectToString(result[2]));
      myQueryResult.setAlias(objectToString(result[3]));
      myQueryResult.setDescription(objectToString(result[4]));
      myQueryResult.setAbbreviation(objectToString(result[6]));

      myQueryResults.add(myQueryResult);
    }
    return myQueryResults;
  } catch (Exception e) {
    return null;
  } finally {
    query.unwrap(ProcedureOutputs.class).release();
  }
}

Ответы [ 2 ]

0 голосов
/ 05 апреля 2019

@ StoredProcedureParameter (mode = ParameterMode.REF_CURSOR, type = void.class, name = "oRetCsr"),

Это хранимая процедура Oracle. Таким образом, вы можете запустить это в Toad или PL / SQL-запросе и просмотреть все выходные столбцы в результирующем наборе. Затем использовать имена этих столбцов в результирующем наборе Пример имеет System.out.println (rset.getString ("ENAME")); получить ENAME от курсора ТАК сопоставьте ваш тип параметра типа Out и проверьте refcursor для данных, и из столбцаameame вы можете получить данные.

Как передать параметры в процедуры и функции в PL / SQL? В PL / SQL мы можем передавать параметры в процедуры и функции тремя способами.

1) Параметр типа IN: эти типы параметров используются для отправки значений в хранимые процедуры. 2) Параметр типа OUT: эти типы параметров используются для получения значений из хранимых процедур. Это похоже на тип возвращаемого значения в функциях. 3) Параметр IN OUT: эти типы параметров используются для отправки значений и получения значений из хранимых процедур.

Когда вы запускаете в жабе, вы должны иметь возможность создать выходной класс пакет демо;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedStoredProcedureQueries;
import javax.persistence.NamedStoredProcedureQuery;
import javax.persistence.ParameterMode;
import javax.persistence.StoredProcedureParameter;

@NamedStoredProcedureQueries({ //
@NamedStoredProcedureQuery(name = "Role.findRolesViaProcedure", procedureName = "collect_roles",
        resultClasses = Role.class, parameters = { //
        @StoredProcedureParameter(name = "role_list_o", mode = ParameterMode.REF_CURSOR, type = void.class) }) //
})
@Entity
public class Role {

    @Id @GeneratedValue//
    private Long id;

    private String name;

    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;
    }
}


 RoleRepository.java
package demo;

import java.io.Serializable;
import java.util.List;

import org.springframework.data.jpa.repository.query.Procedure;
import org.springframework.data.repository.CrudRepository;

interface RoleRepository extends CrudRepository<Role, Serializable> {

    @Procedure
    List<Role> findRolesViaProcedure();
}
 schema.sql
CREATE TABLE "ROLE" 
   (    "ID" NUMBER(10,0), 
    "NAME" VARCHAR2(255 CHAR)
   );

Insert into TRAINING.ROLE (ID,NAME) values ('1','A');
Insert into TRAINING.ROLE (ID,NAME) values ('2','B');
Insert into TRAINING.ROLE (ID,NAME) values ('3','C');


CREATE or replace PROCEDURE collect_roles (role_list_o OUT SYS_REFCURSOR) AS
     BEGIN 
       OPEN role_list_o FOR SELECT id, name FROM role; 
     END;

 SpringDataJpaBugDatajpa652Application.java
package demo;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter;

@SpringBootApplication
public class SpringDataJpaBugDatajpa652Application {

    public static void main(String[] args) {
        SpringApplication.run(SpringDataJpaBugDatajpa652Application.class, args);
    }

    @Bean
    public EntityManagerFactory entityManagerFactory(LocalContainerEntityManagerFactoryBean bean) {
        return bean.getObject();
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean(DataSource dataSource) {

        LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();

        bean.setLoadTimeWeaver(new org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver());
        bean.setDataSource(dataSource);
        EclipseLinkJpaVendorAdapter jva = new EclipseLinkJpaVendorAdapter();
        jva.setDatabase(Database.ORACLE);
        jva.setShowSql(true);
        bean.setJpaVendorAdapter(jva);

        return bean;
    }
}
 SpringDataJpaBugDatajpa652ApplicationTests.java
package demo;

import java.util.List;

import javax.sql.DataSource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SpringDataJpaBugDatajpa652Application.class)
public class SpringDataJpaBugDatajpa652ApplicationTests {

    @Autowired DataSource dataSource;

    @Autowired RoleRepository roleRepository;

    @Test
    public void contextLoads() {

        System.out.println(dataSource);

        List<Role> roles = roleRepository.findRolesViaProcedure();

        System.out.println(roles);
    }
}

https://gist.github.com/thomasdarimont/129bc15d0ccc459610c2

0 голосов
/ 29 марта 2019

Вы можете использовать resultClasses = { MyQueryResultModel.class },, который будет обрабатывать сопоставление объектов самостоятельно, если ваш класс является @Entity, примером .

Если вы не можете использовать resultSetMapping, передавая SQLResultMapping, вот пример использования , я не верю, что вам нужно знать таблицы, по которым запрос попадет заранее, вы просто нужно знать имена столбцов, которые могут быть определены в вашем запросе SQL. если нет, вы можете использовать псевдоним в своем последнем утверждении, чтобы определить их.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...