简体   繁体   中英

Exception java.sql.SQLSyntaxErrorException: Schema 'SA' does not exist, when trying to make a query to Oracle DB



I've been with a mistake for a few weeks now, I wonder if anyone around here can shed some light...

I have a web application, I built it using Spring Boot and it connects to two databases, both Oracle .

In my development environment I deploy in the Spring Boot embedded tomcat and everything works fine. The problem occurs when I deploy in Weblogic (Integration environment) which, when trying to login, returns the following exception at trying to execute a select :

<Dec 27, 2019 1:58:16,335 PM CET> <Warning> <org.hibernate.engine.jdbc.spi.SqlExceptionHelper> <BEA-000000> <SQL Error: 30000, SQLState: 42Y07>
<Dec 27, 2019 1:58:16,336 PM CET> <Error> <org.hibernate.engine.jdbc.spi.SqlExceptionHelper> <BEA-000000> <Schema 'SA' does not exist>
<Dec 27, 2019 1:58:16,343 PM CET> <Error> <org.springframework.boot.web.servlet.support.ErrorPageFilter> <BEA-000000> <Forwarding to error page from request [/login_ldap] due to exception [could not prepare statement; SQL [select userentity0_.id as id1_6_, userentity0_.name as name2_6_, userentity0_.operator as operator3_6_, userentity0_.profile as profile4_6_, userentity0_.roles as roles5_6_, userentity0_.theme as theme6_6_, userentity0_.token as token7_6_ from USERS userentity0_ where userentity0_.name=?]; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement]
org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement; SQL [select userentity0_.id as id1_6_, userentity0_.name as name2_6_, userentity0_.operator as operator3_6_, userentity0_.profile as profile4_6_, userentity0_.roles as roles5_6_, userentity0_.theme as theme6_6_, userentity0_.token as token7_6_ from USERS userentity0_ where userentity0_.name=?]; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:240)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:223)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:527)
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
    ....
    ....
    at weblogic.work.ExecuteThread.execute(ExecuteThread.java:415)
    at weblogic.work.ExecuteThread.run(ExecuteThread.java:355)
Caused By: org.hibernate.exception.SQLGrammarException: could not prepare statement
    at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:63)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
    at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:181)
    ....
    ....
    at weblogic.work.ExecuteThread.execute(ExecuteThread.java:415)
    at weblogic.work.ExecuteThread.run(ExecuteThread.java:355)
Caused By: java.sql.SQLSyntaxErrorException: Schema 'SA' does not exist
    at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
    at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source)
    at org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(Unknown Source)
    at org.apache.derby.impl.jdbc.TransactionResourceImpl.handleException(Unknown Source)
    ....
    ....
    at weblogic.work.ExecuteThread.execute(ExecuteThread.java:415)
    at weblogic.work.ExecuteThread.run(ExecuteThread.java:355)
Caused By: ERROR 42Y07: Schema 'SA' does not exist
    at org.apache.derby.iapi.error.StandardException.newException(Unknown Source)
    at org.apache.derby.iapi.error.StandardException.newException(Unknown Source)
    at org.apache.derby.impl.sql.catalog.DataDictionaryImpl.getSchemaDescriptor(Unknown Source)
    at org.apache.derby.iapi.sql.StatementUtil.getSchemaDescriptor(Unknown Source)
    ....
    ....
    at weblogic.work.ExecuteThread.execute(ExecuteThread.java:415)
    at weblogic.work.ExecuteThread.run(ExecuteThread.java:355)
>

I have been visiting many forums and they all refer to an error that can occur when using Derby DB, and in fact, in the trace of the exception I can see org.apache.derby.iapi.error.StandardException (I can't understand why).

The problem has appeared when I added the second datasource, since the configuration that Spring Boot brought by default was not good for me and, therefore, I had to configure it "by hand".
Maybe, I have some erroneous configuration, but I can't find it.

My application.properties is:

spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@//IP1:PUERTO1/SERVICIO1
spring.datasource.jdbc-url=jdbc:oracle:thin:@//IP1:PUERTO1/SERVICIO1
spring.datasource.username=USERNAME1
spring.datasource.password=PASSWORD1
spring.datasource.hikari.driver-class-name=oracle.jdbc.OracleDriver
spring.datasource.hikari.connection-init-sql=ALTER SESSION SET CURRENT_SCHEMA=USERNAME1

spring.remd-datasource.driver-class-name=oracle.jdbc.OracleDriver
spring.remd-datasource.url=jdbc:oracle:thin:@//IP2:PUERTO2/SERVICIO2
spring.remd-datasource.jdbc-url=jdbc:oracle:thin:@//IP2:PUERTO2/SERVICIO2
spring.remd-datasource.username=USERNAME2
spring.remd-datasource.password=PASSWORD2
spring.remd-datasource.hikari.driver-class-name=oracle.jdbc.OracleDriver
spring.remd-datasource.hikari.connection-init-sql=ALTER SESSION SET CURRENT_SCHEMA=USERNAME2

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect

logging.level.org.springframework.web=ERROR
logging.level.org.springframework.security.access.intercept=debug
logging.level.org.springframework.security=ERROR
logging.level.com.hpe=DEBUG
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n
logging.file=./logs/serverApplication.log

server.error.whitelabel.enabled=false


And the configuration classes that I created for the two datasources:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    entityManagerFactoryRef = "entityManagerFactory",
    basePackages = { "com.project.repository.clar" }
)
public class ClarDataSourceConfiguration {

    @ConfigurationProperties(prefix = "spring.datasource")
    @Primary
    @Bean(name = "dataSource")
    public DataSource dataSource(DataSourceProperties properties) {
        return DataSourceBuilder.create(properties.getClassLoader())
                .type(HikariDataSource.class)
                .driverClassName(properties.determineDriverClassName())
                .url(properties.determineUrl())
                .username(properties.determineUsername())
                .password(properties.determinePassword())
                .build();
    }

    @Primary
    @Bean(name = "entityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(
            EntityManagerFactoryBuilder builder, @Qualifier("dataSource") DataSource dataSource) {
        return builder.dataSource(dataSource).packages("com.project.model.clar").persistenceUnit("clar").build();
    }

    @Primary
    @Bean(name = "transactionManager")
    public PlatformTransactionManager transactionManager(@Qualifier("entityManagerFactory") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}

and

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    entityManagerFactoryRef = "remdEntityManagerFactory", 
    transactionManagerRef = "remdTransactionManager", 
    basePackages = { "com.project.repository.remd" }
)
public class RemdDataSourceConfiguration {

    @ConfigurationProperties(prefix = "spring.remd-datasource")
    @Bean(name = "remdDataSource")
    public DataSource dataSource(DataSourceProperties properties) {
        return DataSourceBuilder.create(properties.getClassLoader())
                .type(HikariDataSource.class)
                .driverClassName(properties.determineDriverClassName())
                .url(properties.determineUrl())
                .username(properties.determineUsername())
                .password(properties.determinePassword())
                .build();
    }

    @Bean(name = "remdEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean remdEntityManagerFactory(
            EntityManagerFactoryBuilder builder, @Qualifier("remdDataSource") DataSource remdDataSource) {
        return builder.dataSource(remdDataSource).packages("com.project.model.remd").persistenceUnit("remd").build();
    }

    @Bean(name = "remdTransactionManager")
    public PlatformTransactionManager remdTransactionManager(@Qualifier("remdEntityManagerFactory") EntityManagerFactory remdEntityManagerFactory) {
        return new JpaTransactionManager(remdEntityManagerFactory);
    }

}

Thanks to everyone in advance and regards!!

I'm aware this may not answer your question, but I ran into the same issue (defining multiple datasources) a while back; this is my solution:

@Configuration
@EnableTransactionManagement
class PersistenceConfig {
  @Bean(name = "oneDS")
  @ConfigurationProperties(prefix = "custom-namespace.datasource.one")
  public DataSource oneDataSource() {
    return DataSourceBuilder.create().build();
  }

  @Primary
  @Bean(name = "mainDS")
  @ConfigurationProperties(prefix = "custom-namespace.datasource.main")
  public DataSource mainDataSource() {
    return DataSourceBuilder.create().build();
  }

  @Bean(name = "twoDS")
  @ConfigurationProperties(prefix = "custom-namespace.datasource.two")
  public DataSource twoDataSource() {
    return DataSourceBuilder.create().build();
  }

  @Bean
  public JdbcTemplate jdbcTemplate() {
    return new JdbcTemplate(mainDataSource());
  }

  // ...other beans using the other datasources
}

...and this is how the application.yml looks like for those settings:

Notice there is NO built-in configuration for the data-sources in application.yml .

custom-namespace:
  datasource:
    one:
      driver-class-name: oracle.jdbc.OracleDriver
      jdbc-url: jdbc:oracle:thin:/@oneDS
    main:
      driver-class-name: oracle.jdbc.OracleDriver
      jdbc-url: jdbc:oracle:thin:/@mainDS
    two:
      driver-class-name: oracle.jdbc.OracleDriver
      jdbc-url: jdbc:oracle:thin:/@twoDS
server:
  compression:
    enabled: true
  port: "${SERVER_PORT:8080}"
  ssl:
    enabled: true
spring:
  application:
    name: "spring-core"
  banner:
    charset: UTF-8
  http:
    encoding:
      charset: UTF-8
      enabled: true
      force: true
  main:
    banner-mode: "off"
  output:
    ansi:
      enabled: detect
  profiles:
    active: default
---
spring:
  profiles: development
---
spring:
  profiles: production
---
server:
  ssl:
    enabled: false
spring:
  main:
    banner-mode: console
  profiles: sandbox
---
spring:
  profiles: test

Since I'm using Spring profiles they must be "activated"; eg: --spring.profiles.active=sandbox .

I've found the mistake. For a reason that I can't understand, Spring is not charging the properties defined in application.properties file that I'm trying to read from my configuration class (properties.determineDriverClassName(), properties.determineUrl(), etc). Instead, if I hardcode the values all works perfectly.

As a workaround I've defined these properties in another properties file and works fine, but I'll continue investigating why properties from my application.properties aren't being charging.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM