spring data spa 和 oracle 包

Posted

技术标签:

【中文标题】spring data spa 和 oracle 包【英文标题】:spring data spa and oracle package 【发布时间】:2017-05-28 00:55:53 【问题描述】:

我正在尝试构建一个 Spring Boot Rest 端点,该端点调用一个具有 2 个 in 参数和 45 个约束参数的 Oracle 存储过程。我创建了一个实体:

package com.me.data.userservice.models;

import javax.persistence.*;
import java.util.Date;

/**
 * Created by me on 5/27/17.
 */
@Entity
@NamedStoredProcedureQueries(
        @NamedStoredProcedureQuery(name = "getUserDetailsSp",
                procedureName = "user_pkg.get_user_details",
                parameters = 
                        @StoredProcedureParameter(mode = ParameterMode.IN, name = "p_in_user_id", type = Long.class),
                        @StoredProcedureParameter(mode = ParameterMode.IN, name = "p_in_region", type = String.class)
                ,
                resultClasses = UserDetails.class)
)
public class UserDetails 
    //region Private members
    @Id
    private Long user_id;
    private String first_name;
    private String last_name;
    private String email;
    @Column(name = "p_in_user_id", nullable = false)
    private String userId;
    private String user_id;
    @Column(name = "p_in_region", nullable = false)
    private String region;
    private Long scnd_user_id;
    ...

还有一个存储库:

package com.me.data.userservice.repositories;

import com.me.data.userservice.models.UserDetails;
import org.springframework.data.jpa.repository.query.Procedure;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;

/**
 * Created by me on 5/27/17.
 */
public interface UserDetailsRepository extends CrudRepository<UserDetails, Long> 
    @Procedure(name="getUserDetailsSp")
    public UserDetails findByUserIdAndRegion(@Param("p_in_user_id") String userId, @Param("p_in_region") String region);

所有这些代码都可以正常编译,但是当我调用存储库时出现以下错误:

2017-05-27 18:41:27 错误 o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() 用于 servlet [dispatcherServlet] 在上下文中的路径 [] 抛出异常 [请求处理失败;嵌套异常是 org.springframework.dao.InvalidDataAccessApiUsageException:对象 类 [org.springframework.data.jpa.repository.query.PartTreeJpaQuery] 必须是类的实例 org.springframework.data.jpa.repository.query.StoredProcedureJpaQuery; 嵌套异常是 java.lang.IllegalArgumentException: Object of 类 [org.springframework.data.jpa.repository.query.PartTreeJpaQuery] 必须是类的实例 org.springframework.data.jpa.repository.query.StoredProcedureJpaQuery] 根本原因 java.lang.IllegalArgumentException:类的对象 [org.springframework.data.jpa.repository.query.PartTreeJpaQuery] 必须 成为类的一个实例 org.springframework.data.jpa.repository.query.StoredProcedureJpaQuery 在 org.springframework.util.Assert.instanceCheckFailed(Assert.java:389) 在 org.springframework.util.Assert.isInstanceOf(Assert.java:327) 在 org.springframework.util.Assert.isInstanceOf(Assert.java:339) 在 org.springframework.data.jpa.repository.query.JpaQueryExecution$ProcedureExecution.doExecute(JpaQueryExecution.java:300) 在 org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:82) 在...

由于某种原因,我无法解码此错误,并且在 google 上找不到任何帮助。

这一定是可能的,但我没有找到任何具有多个返回值或仅输入参数的示例。

添加细节

其实我才意识到我user_pkg.get_user_details其实是一个查询函数。这对我的应用有何改变?

【问题讨论】:

@Procedure 注释也有同样的问题。 【参考方案1】:

我的解决方案或者我应该说我的解决方法有点不同,因为在尝试了很多事情之后 我放弃了@NamedStoredProcedureQueries。所以,我是通过@Query 注释做到的

@Repository 
public interface MyObjectRepository extends CrudRepository<MyObject, String>  
    @Query(value = "EXECUTE [dbo].[myProc] :fieldName, :pages", nativeQuery = true)
    Set<MyObject> findAllByFieldName(@Param("fieldName") String fieldName, @Param("pages") int pages);

此链接可能会有所帮助DATA REPOSITORIES IN SPRING DATA JPA

【讨论】:

这是最好的方法,我在命名查询方面遇到了很多问题,但这个解决了所有问题。 如何传递 List 而不是 String 或 Integer?【参考方案2】:

好的,所以我找到了解决方案。我不确定它是 best 解决方案,但它是 a 解决方案。

首先,我将存储库更改为标准组件,并选择使用 NamedParameterJdbcTemplate 和自定义行映射器。

@Component
public class UserDetailsRepository 

    @Autowired
    private NamedParameterJdbcTemplate jdbcTemplate;

    public UserDetails findByUserIdAndDomain(@Param("p_in_user_id") String userId, @Param("p_in_region") String region) 

        String sql = "select * from TABLE(user_pkg.get_user_details(:p_in_user_id,:p_in_region))";
        MapSqlParameterSource namedParameters = new MapSqlParameterSource("p_in_user_id", userId)
                .addValue("p_in_region", region);
        UserDetails result = (UserDetails)jdbcTemplate.queryForObject(
                sql, namedParameters, new UserDetailsMapper());

        return result;

    

行映射器:

import com.me.data.userservice.models.UserDetails;
import org.springframework.jdbc.core.RowMapper;

import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * Created by me on 5/27/17.
 */
public class UserDetailsMapper implements RowMapper 
    @Override
    public Object mapRow(ResultSet resultSet, int i) throws SQLException 
        UserDetails userDetails = new UserDetails();
               userDetails.setAccount_number(resultSet.getString("account_number"));
        userDetails.setCompany_name(resultSet.getString("company_name"));
        ...
        return userDetails;
    

【讨论】:

以上是关于spring data spa 和 oracle 包的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot + 调度程序 + Spring Data JPA + Oracle 中的异常处理

微服务 第六章 springboot 通过Spring-data-jpa 配置Oracle数据源(Spring-data-jpa详细介绍)

ORACLE SPA(SQL Performance Analyzer)讲解

如何使用Spring Data JPA在实体中映射Oracle Object类型?

『ORACLE』SPA性能分析器

Oracle 中的 Spring Data JPA + EclipseLink