[ORA-00942:Spring Boot中的Spring JDBC模板不存在表或视图

问题描述 投票:0回答:1

尝试通过Spring JDBC模板执行数据库代码时,我得到一个奇怪的ORA-00942: table or view does not exist异常:

2019-12-26 22:01:36.863[0;39m [31mERROR[0;39m [35m12232[0;39m [2m---[0;39m [2m[ctor-http-nio-3][0;39m [36ma.w.r.e.AbstractErrorWebExceptionHandler[0;39m [2m:[0;39m [ca8305eb] 500 Server Error for HTTP GET "/exs/acs/accounts-links?limit=20&q=632626&showActive=false&systemName=IMMS"

org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [select a.FACCIN, a.FACCKEY, a.FACCSNAME, b.LNKSYSTEM, b.LNKLOANKEY, a.FACCSTATUS, a.FACCCOND from BNYMACS.ACCOUNT a left outer join BNYMACS.LINKS b on a.FACCIN = b.lnkacc where (upper(a.FACCKEY) like ? or upper(FACCSNAME) like ? or (b.LNKLOANKEY like ? )) and b.LNKSYSTEM =?  and rownum<=? order by 3 ]; nested exception is java.sql.SQLSyntaxErrorException: ORA-00942: table or view does not exist

    at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:235) ~[spring-jdbc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    |_ checkpoint ? org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
    |_ checkpoint ? HTTP GET "/exs/acs/accounts-links?limit=20&q=632626&showActive=false&systemName=IMMS" [ExceptionHandlingWebHandler]
Stack trace:
        at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:235) ~[spring-jdbc-5.2.0.RELEASE.jar:5.2.0.RELEASE]

。 。 。 。 。 。 。

Caused by: java.sql.SQLSyntaxErrorException: ORA-00942: table or view does not exist

    at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:509) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
    at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:461) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
    at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1104) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:550) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:268) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
    at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:655) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
    at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:270) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
    at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:91) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
    at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:807) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
    at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:983) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
    at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1168) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
    at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3666) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
    at oracle.jdbc.driver.T4CPreparedStatement.executeInternal(T4CPreparedStatement.java:1426) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
    at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3713) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1167) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
    at com.p6spy.engine.wrapper.PreparedStatementWrapper.executeQuery(PreparedStatementWrapper.java:78) ~[p6spy-3.8.2.jar:na]
    at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:678) ~[spring-jdbc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:617) ~[spring-jdbc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:669) ~[spring-jdbc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:700) ~[spring-jdbc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:712) ~[spring-jdbc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:763) ~[spring-jdbc-5.2.0.RELEASE.jar:5.2.0.RELEASE]

由于使用了Oracle驱动程序,由于开发人员已关闭oracle.jdbc.driver.OraclePreparedStatementWrapper源代码,因此我无法真正调试ojdbc8中的情况。

奇怪的是,在调试会话期间使用其参数提取并复制到外部SQL客户端时,来自Spring JDBC模板的查询进入Oracle驱动程序,在那儿可以正常工作:

select a.FACCIN, a.FACCKEY, a.FACCSNAME, b.LNKSYSTEM, b.LNKLOANKEY, a.FACCSTATUS, a.FACCCOND from BNYMACS.ACCOUNT a left outer join BNYMACS.LINKS b on a.FACCIN = b.lnkacc where (upper(a.FACCKEY) like '632626%' or upper(FACCSNAME) like '632626%' or (b.LNKLOANKEY like '632626%' )) and b.LNKSYSTEM ='IMMS'  and rownum<=20 order by 3 ;

并产生结果的多条记录。

这是有问题的Spring存储库:

import static cwp.services.adhoc_processor.domain.acs.Account.*;
import static cwp.services.adhoc_processor.domain.acs.Links.*;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import javax.sql.DataSource;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;


import cwp.services.adhoc_processor.domain.acs.AccountLinkDetail;
import cwp.services.adhoc_processor.domain.acs.AccountLinkDetail.AccountLinkDetailBuilder;

import cwp.services.adhoc_processor.domain.acs.AccountLinksList;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class AccountLinksRepositoryCustomImpl implements AccountLinksRepositoryCustom {

    private static final String TERMINATED = "TERMINATED";
    private static final String STOPPED = "STOPPED";

    private final static String STATIC_QUERY_PART = "select a.FACCIN, a.FACCKEY, a.FACCSNAME, b.LNKSYSTEM, b.LNKLOANKEY, a.FACCSTATUS, a.FACCCOND "
            + "from BNYMACS.ACCOUNT a left outer join BNYMACS.LINKS b "
            + "on a.FACCIN = b.lnkacc where (upper(a.FACCKEY) like ? or upper(FACCSNAME) like ? "
            + "or (b.LNKLOANKEY like ? )) and b.LNKSYSTEM =? ";

    private final static String activeSuffix = "and upper(a.FACCSTATUS) <> 'TERMINATED' and upper(a.FACCCOND) <> 'STOPPED' ";

    private final static String orderbyClause = " and rownum<=? order by 3 ";

    @Autowired
    @Qualifier("acsJdbcTemplate")
    private JdbcTemplate template;

    @Autowired
    public void setDataSource(DataSource dataSource) {
        this.template = new JdbcTemplate(dataSource);
    }

    @Override
    public AccountLinksList searchByAccountOrLinks(String searchTerm, int limit, boolean isActive, String systemName) {
        AccountLinksList accountLinksList = new AccountLinksList();

        try {
            String dynQuery = STATIC_QUERY_PART;

            if (isActive)
                dynQuery += activeSuffix;

            dynQuery += orderbyClause;

            List<AccountLinkDetail>  accountDetailsList = template.<AccountLinkDetail>query(
                    dynQuery,
                    new Object[] { searchTerm, searchTerm, searchTerm, systemName, limit }, 
                    new RowMapper<AccountLinkDetail>() {
                        @Override
                        public AccountLinkDetail mapRow(ResultSet rs, int currentRow) throws SQLException {
                            AccountLinkDetailBuilder accountDetails = AccountLinkDetail.builder();
                            accountDetails
                                    .accountId(rs.getLong(ID_COLUMN_NAME))
                                    .accountKey(rs.getString(ACCOUNT_KEY_COLUMN_NAME))
                                    .accountName(rs.getString(ACCOUNT_SHORT_NAME_COLUMN_NAME))
                                    .loanKey(rs.getString(LOAN_KEY_COLUMN_NAME))
                                    .systemName(rs.getString(LINK_SYSTEM_COLUMN_NAME));
                            if (rs.getString(CONDITION_COLUMN_NAME) != null
                                    && !rs.getString(CONDITION_COLUMN_NAME).equalsIgnoreCase(STOPPED)
                                    && rs.getString(STATUS_COLUMN_NAME) != null
                                    && !rs.getString(STATUS_COLUMN_NAME).equalsIgnoreCase(TERMINATED)) {
                                accountDetails.isActive(true);
                            }
                            return accountDetails.build();
                        }



                    });
            accountLinksList.setAccountLinkDetail(accountDetailsList);
        } catch (Exception e) {
            log.error("Technical Exception", e);
            throw e;
        }
        return accountLinksList;
    }

}

这是数据库的配置方式:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        basePackages = {"cwp.services.adhoc_processor.repository.acs" }, 
        entityManagerFactoryRef = "acsEntityManagerFactory", 
        transactionManagerRef = "acsTransactionManager")

public class AcsDatasourceConfiguration {

    @Autowired
    private AcsDbProperties properties;

    @Validated
    @Component
    @ConfigurationProperties(prefix = "acs.read.datasource")
    public class AcsDbProperties extends HikariDBProperties {
    }

    @ConditionalOnBean(value = AcsDbProperties.class)
    @Bean(name = "acsDataSource", destroyMethod = "")
    public DataSource acsDataSource() {
        return new HikariDataSource(new HikariConfig(properties.getProperties()));
    }

    @Bean("acsJdbcTemplate")
    public JdbcTemplate pmtTemplate () throws Exception {
        return new JdbcTemplate(acsDataSource());
    }

    @Bean(name = "acsEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean acsEntityManagerFactory(EntityManagerFactoryBuilder builder) {
        return builder.dataSource(acsDataSource())
                .packages("cwp.services.adhoc_processor.domain.acs" )
                .persistenceUnit("acs")
                .build();
    }

    /*
     * Leaky requirement for the unsatisfied transaction manager bean stemming from nxn-workflow-services#NWFProcessEngineConfiguration.java dependency.
     * 
     * N.B. MUST BE CALLED THIS EXACT NAME, else will get 
     * org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.transaction.PlatformTransactionManager' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=transactionManager)}
     * 
     */
    @Bean("transactionManager") // <-- must be called `transactionManager`.
    public PlatformTransactionManager acsTransactionManager
            (
            @Qualifier("acsEntityManagerFactory")
            final  LocalContainerEntityManagerFactoryBean acsEntityManagerFactory
            ) {

                return new JpaTransactionManager(acsEntityManagerFactory.getObject());
    }


}

这是用例的调用:

curl --location --request GET 'http://localhost:7010/exs/acs/accounts-links?limit=20&q=632626&showActive=false&systemName=IMMS' \
--header 'Content-Type: application/json'

该表似乎是同义词:

enter image description here

enter image description here

并且运行时用户为WEBSVC_READ

enter image description here

直接查询数据库时,我使用的是相同的WEBSVC_READ模式,并且可以正常工作:

enter image description here

N.B。:该行为似乎仅与JDBC模板有关。以下JPA查询运行良好:

"select  a from Account a, Links l where l.accountId = a.id and l.loanKey = :loanKey and l.linkSystem = :systemName and(upper(a.status) <> 'TERMINATED' or upper(a.condition) <>'STOPPED' )";

application.properties中包含以下内容:

spring.jpa.properties.hibernate.default_schema=BNYMACS

和这样配置的实体(无显式模式):

@Entity(name="Account")
@Table(name="ACCOUNT")
public class Account implements Serializable{...}


@Entity
@Table(name="LINKS")
@Data
public class Links implements Serializable{...}

这里可能有什么问题?这ORA-00942是有意义的错误,还是只是其他内容的占位符?也许有人可以给我一些有用的指导,以帮助您深入了解本教程。

提前感谢。

oracle jdbc spring-data spring-jdbc ojdbc
1个回答
0
投票

罪魁祸首是我的存储库中以下错误和不必要的定义:

@Autowired
public void setDataSource(DataSource dataSource) {
        this.template = new JdbcTemplate(dataSource);
    }

它已经在Configuration类中定义,并且重新定义引起了所有破坏。

© www.soinside.com 2019 - 2024. All rights reserved.