简体   繁体   中英

Unable to Query Postgres using Hibernate JPA framework in my Java maven project

I have a Java maven project that utilizes Spring framework. I am retrieving data from 2 different Postgres DBs (version 12.8) using Hibernate JPA. The data source configuration is defined in my beans.xml file as shown below

<!--
Configure Spring Data JPA and set the base package of the
repository interfaces
-->
<jpa:repositories base-package="com.aaa.bbb"/>

<!-- Configure the entity manager factory beans -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" primary="true">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="com.aaa.bbb.*" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
    </property>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.hbm2ddl.auto">none</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
        </props>
    </property>
</bean>

<bean id="labelEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="labelDataSource" />
    <property name="packagesToScan" value="com.aaa.bbb.label.*" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
    </property>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.hbm2ddl.auto">none</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
        </props>
    </property>
</bean>

<!-- Configure the data source beans -->
<bean id="dataSource"
  class="org.springframework.jdbc.datasource.DriverManagerDataSource" primary="true">
    <property name="driverClassName" value="org.postgresql.Driver" />
    <property name="url" value="jdbc:postgresql://localhost:9001/fhirdb"/>
    <property name="username" value="fhirserver" />
    <property name="password" value="change-password" />
</bean>

 <bean id="labelDataSource"
  class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="org.postgresql.Driver" />
    <property name="url" value="jdbc:postgresql://localhost:9002/labeldb"/>
    <property name="username" value="postgres" />
    <property name="password" value="labeldbpwd" />
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" primary="true">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<bean id="labelTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="labelEntityManagerFactory" />
</bean>

<!-- Enable annotation driven transaction management -->
<tx:annotation-driven/>

I have queries going against both the primary and the second database (labeldb). The queries written against the primary database runs fine. But I am having issues with the query that is going against the second DB even though they are written in the same way.

Regarding the query that goes against the second DB, here are some details. I have multiple tables in schema "label" inside my "labeldb" DB. I have defined the following Entity class corresponding to the table "establishment" in the labeldb DB

EstablishmentEntity.java

package com.aaa.bbb.label.model;

import java.io.Serializable;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.aaa.bbb.splfhirpoc.common.SplFhirpocDataException;

@Entity (name = "establishmententity")
@Table(name = "establishment", schema = "label")
public class EstablishmentEntity implements Serializable  {

private static final Logger LOGGER = LogManager.getLogger(EstablishmentEntity.class.getName());
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)

@Column(name="id", updatable = false, nullable = false)
private String id;

@Column(name="registrant_id")
private String registrant_id;

I also have a Repository class where I have defined the query to be used as shown below

EstablishmentRepository.java

package com.aaa.bbb.splfhirpoc.establishment;

import java.util.List;
import java.util.Optional;

import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.aaa.bbb.label.model.EstablishmentEntity;

@Repository
@Transactional(timeout = 600, value = "labelTransactionManager")
@EntityScan("com.aaa.bbb.label.*")
public interface EstablishmentRepository extends JpaRepository<EstablishmentEntity, String> {


@Query(nativeQuery = true, value = "select a.*, d.date "
        + "from label.establishment a, label.submission_establishment b, label.submission_status d "
        + "where a.id = b.establishment_id "
        + "and b.submission_id = d.submission_id "
        + "and d.code =  'Received' "
        + "and a.duns_number = :duns_number "
        + "and d.date = (select max(e.date) FROM label.submission_status e, label.submission_establishment f "
        + "WHERE e.submission_id = f.submission_id "
        + "AND f.establishment_id = a.id "
        + "AND e.code = 'Received' )" 
       )
List<EstablishmentEntity> getAllEstablishmentsByDuns(@Param("duns_number") String duns_number);

Now when I invoke my REST API defined in my Service class, it triggers the above SQL and the log appears to generate the Hibernate SQL correctly (see below the debug statements). But I get an error indicating that the query that gets executed using Hibernate refers to an invalid table name

Debug statements before the error

09:40:01.735 [http-nio-8080-exec-6] DEBUG org.apache.cxf.jaxrs.utils.JAXRSUtils - Resource operation getAllEstablishmentsByDuns may get selected
09:40:01.743 [http-nio-8080-exec-6] DEBUG org.apache.cxf.jaxrs.utils.JAXRSUtils - Resource operation getAllEstablishmentsByDuns on the resource class com.ibm.fda.splfhirpoc.establishment.EstablishmentController has been selected
09:40:01.759 [http-nio-8080-exec-6] DEBUG org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor - Request path is: /establishment/getAllEstablishments/duns_number/991098882
09:40:01.764 [http-nio-8080-exec-6] DEBUG org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor - Request HTTP method is: GET
09:40:01.772 [http-nio-8080-exec-6] DEBUG org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor - Request contentType is: application/json
09:40:01.773 [http-nio-8080-exec-6] DEBUG org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor - Accept contentType is: */*
09:40:01.773 [http-nio-8080-exec-6] DEBUG org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor - Found operation: getAllEstablishmentsByDuns
09:40:01.800 [http-nio-8080-exec-6] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.interceptor.OneWayProcessorInterceptor@a9f8e161
09:40:01.800 [http-nio-8080-exec-6] DEBUG org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.interceptor.ServiceInvokerInterceptor@84d2b123
09:40:01.804 [http-nio-8080-exec-6] DEBUG org.apache.cxf.service.invoker.AbstractInvoker - Invoking method public javax.ws.rs.core.Response com.ibm.fda.splfhirpoc.establishment.EstablishmentController.getAllEstablishmentsByDuns(java.lang.String,java.lang.String,java.lang.String,java.lang.String) throws com.ibm.fda.splfhirpoc.audit.ResourceNotFoundException on object com.ibm.fda.splfhirpoc.establishment.EstablishmentController@24636ebd with params [vsinha, IBM, platform_9_and_3_quarters, 991098882].
09:40:02.106 [http-nio-8080-exec-6] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.getAllEstablishmentsByDuns]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,timeout_600; 'labelTransactionManager'
09:40:02.107 [http-nio-8080-exec-6] DEBUG org.hibernate.stat.internal.StatisticsInitiator - Statistics initialized [enabled=false]
09:40:02.108 [http-nio-8080-exec-6] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Opened new EntityManager [SessionImpl(1697515019<open>)] for JPA transaction
09:40:02.133 [http-nio-8080-exec-6] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == false
09:40:02.133 [http-nio-8080-exec-6] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - begin
09:40:02.133 [http-nio-8080-exec-6] DEBUG org.springframework.jdbc.datasource.DriverManagerDataSource - Creating new JDBC DriverManager Connection to [jdbc:postgresql://localhost:9002/labeldb]
09:40:02.371 [http-nio-8080-exec-6] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@fbcc8a42]
09:40:02.394 [http-nio-8080-exec-6] DEBUG org.springframework.orm.jpa.EntityManagerFactoryUtils - Opening JPA EntityManager
09:40:02.625 [http-nio-8080-exec-6] DEBUG org.hibernate.SQL - select a.*, d.date from label.establishment a, label.submission_establishment b, label.submission_status d where a.id = b.establishment_id and b.submission_id = d.submission_id and d.code =  'Received' and a.duns_number = ? and d.date = (select max(e.date) FROM label.submission_status e, label.submission_establishment f WHERE e.submission_id = f.submission_id AND f.establishment_id = a.id AND e.code = 'Received' )
09:40:02.626 [http-nio-8080-exec-6] DEBUG org.springframework.jdbc.datasource.DriverManagerDataSource - Creating new JDBC DriverManager Connection to [jdbc:postgresql://localhost:9001/fhirdb]
09:40:02.921 [http-nio-8080-exec-6] DEBUG org.hibernate.engine.jdbc.spi.SqlExceptionHelper - could not extract ResultSet [n/a]

   ** Exception log **

 org.postgresql.util.PSQLException: ERROR: relation "label.establishment" does not exist

Position: 25 at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2553) at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2285) at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:323) at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:473) at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:393) at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:164) at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:114) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:57) at org.hibernate.loader.Loader.getResultSet(Loader.java:2287) at org.hibernate.loader.Loader.executeQueryStatement(Loader.882132469458 88:2045) at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2007) at org.hibernate.loader.Loader.doQuery(Loader.java:953) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354) at org.hibernate.loader.Loader.doList(Loader.java:2810) at org.hibernate.loader.Loader.doList(Loader.java:2792) at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2624) at org.hibernate.loader.Loader.list(Loader.java:2619) at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:338) at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:2137) at org.hibernate.internal.AbstractSharedSessionContract.list(AbstractSharedSessionContract.java:1134) at org.hibernate.query.internal.NativeQueryImpl.doList(NativeQueryImpl.java:173) at org.hibernate.query.internal.Abstrac tProducedQuery.list(AbstractProducedQuery.java:1526) at org.hibernate.query.Query.getResultList(Query.java:165) at org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution.doExecute(JpaQueryExecution.java:126) at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:88) at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:155) at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:143) at.invoke(Unknown Source) at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137) at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121) at org.springframework.data.repository.core.support.QueryExecutorM ethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:152) at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:131) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at.proceedWithInvocation(Unknown Source) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation. java:186) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:145) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) at com.sun.proxy.$Proxy48.getAllEstablishm entsByDuns(Unknown Source) at com.ibm.fda.splfhirpoc.establishment.EstablishmentService.getAllEstablishmentsByDuns(EstablishmentService.java:34) at com.ibm.fda.splfhirpoc.establishment.EstablishmentController.getAllEstablishmentsByDuns(EstablishmentController.java:137) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:179) at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96) at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JA XRSInvoker.java:201) at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:104) at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:59) at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:96) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308) at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:265) at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:234) at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:208) at org.apache.cxf.transport.servlet.ServletController.invoke(Serv letController.java:160) at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:225) at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:298) at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doGet(AbstractHTTPServlet.java:222) at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:273) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterCha in.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:346) at org.apache.coyote.http11.Http11 Processor.service(Http11Processor.java:374) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:887) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1684) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.base/java.lang.Thread.run(Thread.java:866) 09:40:02.923 [http-nio-8080-exec-6] WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 0, SQLState: 42P01 09:40:02.923 [http-nio-8080-exec-6] ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper - ERROR: relation "label.establishment" does not exist Position: 25 09:40:02.964 [http-nio-8080-exec-6] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == false 09:40:02.970 [http-nio-8080-exec-6] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Initiating transaction rollback 09:40:02.970 [http-nio-8080-exec-6] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Rolling back JPA transaction on EntityManager [SessionImpl(1697515019)] 09:40:02.970 [http-nio-8080-exec-6] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - rolling back 09:40:02.977 [http-nio-8080-exec-6] DEBUG org.springframework.orm.jpa.JpaTransactionManager - C losing JPA EntityManager [SessionImpl(1697515019)] after transaction

Why does the hibernate embed the table name in my query between double quotes ("label.establishment") during execution even though the query in the debug log does not have it? Is there a way to ensure that the double quotes does not get embedded during execution? As mentioned earlier, I have multiple queries that get executed against my primary database where I do not see this issue even though it is written in the same way as the one that fails. But this is happening only for query defined against my second database. Any help will be greatly appreciated.

Thanks Vikas

As I mentioned in my comment to Chris's input, the query fails because it is connecting to the first DB instead of the second DB (labeldb). Looking at my beans.xml / Entity and Repository classes, how do we ensure that my query runs against the right DB? Are there annotations to be defined in the Java classes to use the correct dataSource? If you look at the debug log I shared, there is a connection being made to labeldb, then the Hibernate query statement appears followed by connection to the first DB which is where the issue is.

In short this is a case of JPA implementation where we are accessing multiple DB and we need a way to manage how queries need to be directed to the right database when the JPA / Hibernate configuration is done to the beans.xml file. Appreciate any help in advance.

Thanks

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