2

I am trying to execute an Oracle stored procedure using JPA. I am able to retrieve results if I build the query and call the stored procedure through the query.getResultList() as shown below:

    @Autowired
    EntityManager em;
    public List<MyEntity> callStoredProcedure(String paramOneValue, String paramTwoValue)
   {
        StoredProcedureQuery query = em.createStoredProcedureQuery("storedProcedureName");
        query.registerStoredProcedureParameter("paramOneName", String.class, ParameterMode.IN);
        query.registerStoredProcedureParameter("paramTwoName", String.class, ParameterMode.IN);
        query.registerStoredProcedureParameter("results", Void.class, ParameterMode.REF_CURSOR);
        query.setParameter("paramOneName", paramOneValue);
        query.setParameter("paramTwoName", paramTwoValue);

        query.execute();

        List<MyEntity> result = new ArrayList<MyEntity>();  

        for(Object item: query.getResultList())
        {
            /* mapping my object to the entity and adding to the collection
            result.add(new MyEntity(item));
        }

        return result;
    }

However, this is not very elegant.

If I try to use the entity mapping as in the code below, I get an errpr

org.springframework.orm.jpa.JpaSystemException: Error extracting results from CallableStatement"

and

java.sql.SQLException: Invalid column name

after the procedure is called and when is trying to map to the entity

     @NamedStoredProcedureQueries({
 @NamedStoredProcedureQuery(name = "MyStoredProcedure", 
        procedureName = "storedProcedureName",
        resultClasses = {MyEntity.class}, 
        parameters = { 
            @StoredProcedureParameter(name = "paramOneName", mode = ParameterMode.IN, type = String.class),
            @StoredProcedureParameter(name = "paramTwoName", mode = ParameterMode.IN, type = String.class),
            @StoredProcedureParameter(name = "results", mode = ParameterMode.REF_CURSOR, type = void.class)
        })
 })
 @Entity
 public class MyEntity implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue
    private long id;
    @Column(name="MY_FIRST_COLUMN")
    private String myFirstColumn;
    // Related Properties
 }
 // And declaring as repository
 @Repository
 public interface IMyRepository extends JpaRepository<MyEntity, Long  {
    @Procedure
    List<MyEntity  callMyStoredProcedure(@Param("paramOneName") String paramOneName, 
                                        @Param("paramTwoName") String paramTwoName);    
 }

I tried to solve this issue in several ways, using entity custom mapping @SqlResultSetMapping and also trying cast the query.getResultList to the List<MyEntity>. However the exception is always the same.

It looks like JPA is unable to get the column information from the stored procedure.

I double checked the column names and they match the columns retrieved by the stored procedure, however it must be added that there isn't a real table with such columns in the database.

From the pom...

    <dependency>
        <groupId>org.hibernate.javax.persistence</groupId>
        <artifactId>hibernate-jpa-2.1-api</artifactId>
        <version>1.0.0.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>5.2.2.Final</version>
    </dependency>

Does the stored procedure need to be written in a specific way in order for the mapping to work (PS unfortunately I don't have access to the stored procedure definition)?

Do I need a physical table or view in the database with the same column as the one retrieved by the stored procedure, in order to be able to map the resultset to an entity?

Thanks a lot for your help

4

0 回答 0