简体   繁体   English

从表中选择特定列,然后使用Spring + hibernate + JPA将结果存储到非实体POJO

[英]select specific columns from the table and store the results to the non-entity POJO with Spring + hibernate + JPA

I am using Spring 3.1.3 + hibernate-entitymanager 5.0.7 (Which contains JPA of version 2.1 ) + ojdbc14-10.2.0.2.jar 我正在使用Spring 3.1.3 + hibernate-entitymanager 5.0.7 (其中包含2.1版的JPA )+ ojdbc14-10.2.0.2.jar

I want to select specific columns from the table and store the results to the non-entity POJO. 我想从表中选择特定的列,并将结果存储到非实体POJO。 I want to implement in the way how it is proposed in below link 我想以以下链接中建议的方式实施

Spring Data JPA map the result to Non-Entity POJO Spring Data JPA将结果映射到非实体POJO

My Entity class: 我的实体类:

   @Entity
    @Data
    @Table(name = "CUSTOMER")
    @SqlResultSetMapping(name="SampleMapping",
    classes = {
     @ConstructorResult(targetClass = com.entity.Sample.class,
       columns = {@ColumnResult(name="customerId"), @ColumnResult(name="name"), @ColumnResult(name="firstName")}
     )}
    )
    public class CustomerEntity {

        @Id
        @Column(name = "CUSTOMER_ID")
        private String customerId;

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

        @Column(name = "FIRST_NAME")
        private String firstName;

       @Column(name = "LAST_NAME")
        private String lastName;

       @Column(name = "AGE")
        private String age;
    }

My Query Part: 我的查询部分:

String q = "select s.customerId, s.name, s.firstName from CustomerEntity s";
Query query = entityManager.createNativeQuery(q,"SampleMapping");
List<Sample> resultsList = query.getResultSet();

Sample class is simple POJO (with parameterized constructor with customerId, name and firstName) where i want to store my results of query. 示例类是简单的POJO(带有带有customerId,name和firstName的参数化构造函数),我要在其中存储查询结果。

Can you please advise me which versions of Spring, Hibernate, JPA, ojdbc jars I need to add in order to achieve my requirement? 您能告诉我我需要添加哪个版本的Spring,Hibernate,JPA,ojdbc jars才能达到我的要求? Many thanks in advance. 提前谢谢了。

Couldn't idendify if the below exception is because of versions of jar or any incorrect declaration of annotations or query format. 如果以下异常是由于jar版本或注释或查询格式的任何不正确声明所致,则无法识别。

Because I face few exceptions when I add the below jars: 因为添加以下罐子时几乎没有例外:

    +- com.commons:commons-dao:jar:1.0## Heading ##-SNAPSHOT:compile
    |  +- oracle:ojdbc14:jar:10.2.0.2:compile
    |  +- org.springframework:spring-tx:jar:3.1.3.RELEASE:compile
    |  |  +- aopalliance:aopalliance:jar:1.0:compile
    |  |  \- org.springframework:spring-core:jar:3.1.3.RELEASE:compile
    |  +- org.springframework:spring-orm:jar:3.1.3.RELEASE:compile
    |  |  \- org.springframework:spring-jdbc:jar:3.1.3.RELEASE:compile
    |  +- org.hibernate:hibernate-entitymanager:jar:5.0.7.Final:compile
    |  |  +- org.hibernate:hibernate-core:jar:5.0.7.Final:compile
    |  |  |  +- antlr:antlr:jar:2.7.7:compile
    |  |  |  \- org.jboss:jandex:jar:2.0.0.Final:compile
    |  |  +- dom4j:dom4j:jar:1.6.1:compile
    |  |  +- org.hibernate.common:hibernate-commons-annotations:jar:5.0.1.Final:compile
    |  |  +- org.hibernate.javax.persistence:hibernate-jpa-2.1-api:jar:1.0.0.Final:compile
    |  |  \- org.apache.geronimo.specs:geronimo-jta_1.1_spec:jar:1.1.1:compile
    |  +- org.javassist:javassist:jar:3.14.0-GA:compile
    |  +- javax.resource:connector:jar:1.0:compile
    |  |  +- org.springframework:spring-oxm:jar:3.1.3.RELEASE:compile
    |  |     \- org.apache.httpcomponents:httpclient-cache:jar:4.2.4:compile
    |  +- org.springframework:spring-beans:jar:3.1.3.RELEASE:compile (version managed from 3.1.2.RELEASE)
    |  +- org.springframework:spring-context:jar:3.1.3.RELEASE:compile (version managed from 3.1.2.RELEASE)
    |  |  +- org.springframework:spring-expression:jar:3.1.3.RELEASE:compile
    |  |  \- org.springframework:spring-asm:jar:3.1.3.RELEASE:compile
    |  +- org.slf4j:jcl-over-slf4j:jar:1.6.4:runtime
    |  \- org.slf4j:log4j-over-slf4j:jar:1.6.4:runtime
    |  +- org.springframework:spring-webmvc:jar:3.1.3.RELEASE:compile
    |  |  \- org.springframework:spring-context-support:jar:3.1.3.RELEASE:compile
    |  +- org.springframework:spring-web:jar:3.1.3.RELEASE:compile
    |  +- org.springframework:spring-aop:jar:3.1.3.RELEASE:compile
    |  +- org.springframework.integration:spring-integration-core:jar:2.2.6.RELEASE:compile
    |  |  \- org.springframework.retry:spring-retry:jar:1.0.2.RELEASE:compile
    |  +- org.springframework.integration:spring-integration-event:jar:2.2.6.RELEASE:runtime
    |  +- org.springframework.integration:spring-integration-file:jar:2.2.6.RELEASE:runtime
    |  +- org.springframework.integration:spring-integration-http:jar:2.2.6.RELEASE:compile
    |  +- org.springframework.integration:spring-integration-xml:jar:2.2.6.RELEASE:compile
    |  |  \- org.springframework.ws:spring-xml:jar:2.1.1.RELEASE:compile
    |  +- org.springframework.integration:spring-integration-jms:jar:2.2.6.RELEASE:compile
    |  |  \- org.springframework:spring-jms:jar:3.1.3.RELEASE:compile
    |  +- org.springframework.integration:spring-integration-ws:jar:2.2.6.RELEASE:compile
    |  |  \- org.springframework.ws:spring-ws-core:jar:2.1.1.RELEASE:compile
    +- org.hibernate:hibernate-validator:jar:4.3.0.Final:compile
    +- log4j:log4j:jar:1.2.17:provided
    +- org.slf4j:slf4j-api:jar:1.7.12:compile
    +- org.jboss.logging:jboss-logging:jar:3.3.0.Final:compile
    \- org.slf4j:slf4j-simple:jar:1.7.12:compile

But I got resulted in below exception in the below line 但是我在以下行中导致以下异常

List<Sample> resultsList = query.getResultSet();

Exception: 例外:

 org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
           at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:635) ~[spring-orm-3.1.3.RELEASE.jar:3.1.3.RELEASE]
           at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:104) ~[spring-orm-3.1.3.RELEASE.jar:3.1.3.RELEASE]
           at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:403) ~[spring-orm-3.1.3.RELEASE.jar:3.1.3.RELEASE]
           at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:58) ~[spring-tx-3.1.3.RELEASE.jar:3.1.3.RELEASE]
           at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213) ~[spring-tx-3.1.3.RELEASE.jar:3.1.3.RELEASE]
           at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:163) ~[spring-tx-3.1.3.RELEASE.jar:3.1.3.RELEASE]
           at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) ~[spring-aop-3.1.3.RELEASE.jar:3.1.3.RELEASE]
           at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) ~[spring-aop-3.1.3.RELEASE.jar:3.1.3.RELEASE]
           at com.common.dao.SampleServiceImpl.sampleMethod(SrvImplemet.java:123) ~[commons-dao-1.0-SNAPSHOT.jar:na]

      Caused by: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
           at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:106) ~[hibernate-core-5.0.7.Final.jar:5.0.7.Final]
           at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) ~[hibernate-core-5.0.7.Final.jar:5.0.7.Final]
           at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109) ~[hibernate-core-5.0.7.Final.jar:5.0.7.Final]
           at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95) ~[hibernate-core-5.0.7.Final.jar:5.0.7.Final]
           at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:79) ~[hibernate-core-5.0.7.Final.jar:5.0.7.Final]
           at org.hibernate.loader.Loader.getResultSet(Loader.java:2116) ~[hibernate-core-5.0.7.Final.jar:5.0.7.Final]
           at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1899) ~[hibernate-core-5.0.7.Final.jar:5.0.7.Final]
           at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1875) ~[hibernate-core-5.0.7.Final.jar:5.0.7.Final]
           at org.hibernate.loader.Loader.doQuery(Loader.java:919) ~[hibernate-core-5.0.7.Final.jar:5.0.7.Final]
           at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:336) ~[hibernate-core-5.0.7.Final.jar:5.0.7.Final]
           at org.hibernate.loader.Loader.doList(Loader.java:2611) ~[hibernate-core-5.0.7.Final.jar:5.0.7.Final]
           at org.hibernate.loader.Loader.doList(Loader.java:2594) ~[hibernate-core-5.0.7.Final.jar:5.0.7.Final]
           at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2423) ~[hibernate-core-5.0.7.Final.jar:5.0.7.Final]
           at org.hibernate.loader.Loader.list(Loader.java:2418) ~[hibernate-core-5.0.7.Final.jar:5.0.7.Final]
           at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:336) ~[hibernate-core-5.0.7.Final.jar:5.0.7.Final]
           at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:1967) ~[hibernate-core-5.0.7.Final.jar:5.0.7.Final]
           at org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:322) ~[hibernate-core-5.0.7.Final.jar:5.0.7.Final]
           at org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:125) ~[hibernate-core-5.0.7.Final.jar:5.0.7.Final]
           at org.hibernate.jpa.internal.QueryImpl.list(QueryImpl.java:606) ~[hibernate-entitymanager-5.0.7.Final.jar:5.0.7.Final]
           at org.hibernate.jpa.internal.QueryImpl.getResultList(QueryImpl.java:483) ~[hibernate-entitymanager-5.0.7.Final.jar:5.0.7.Final]
           at com.common.dao.SampleDaompl.sampleMethod.SampleDaoImpl.getData(SampleDaoImpl.java:16) ~[commons-dao-1.0-SNAPSHOT.jar:na]
           at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_51]
           at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.7.0_51]
           at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_51]
           at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_51]
           at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:319) ~[spring-aop-3.1.3.RELEASE.jar:3.1.3.RELEASE]
           at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) ~[spring-aop-3.1.3.RELEASE.jar:3.1.3.RELEASE]
           at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) ~[spring-aop-3.1.3.RELEASE.jar:3.1.3.RELEASE]
           at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155) ~[spring-tx-3.1.3.RELEASE.jar:3.1.3.RELEASE]
           ... 191 common frames omitted
    Caused by: java.sql.SQLException: ORA-00942: table or view does not exist

           at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112) ~[ojdbc14-10.2.0.2.jar:Oracle JDBC Driver version - "10.2.0.1.0"]
           at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331) ~[ojdbc14-10.2.0.2.jar:Oracle JDBC Driver version - "10.2.0.1.0"]
           at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288) ~[ojdbc14-10.2.0.2.jar:Oracle JDBC Driver version - "10.2.0.1.0"]
           at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:743) ~[ojdbc14-10.2.0.2.jar:Oracle JDBC Driver version - "10.2.0.1.0"]
           at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:216) ~[ojdbc14-10.2.0.2.jar:Oracle JDBC Driver version - "10.2.0.1.0"]
           at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:799) ~[ojdbc14-10.2.0.2.jar:Oracle JDBC Driver version - "10.2.0.1.0"]
           at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1039) ~[ojdbc14-10.2.0.2.jar:Oracle JDBC Driver version - "10.2.0.1.0"]
           at oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPreparedStatement.java:839) ~[ojdbc14-10.2.0.2.jar:Oracle JDBC Driver version - "10.2.0.1.0"]
           at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1132) ~[ojdbc14-10.2.0.2.jar:Oracle JDBC Driver version - "10.2.0.1.0"]
           at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3285) ~[ojdbc14-10.2.0.2.jar:Oracle JDBC Driver version - "10.2.0.1.0"]
           at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3329) ~[ojdbc14-10.2.0.2.jar:Oracle JDBC Driver version - "10.2.0.1.0"]
           at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:93) ~[commons-dbcp-1.2.2.jar:1.2.2]
           at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:70) ~[hibernate-core-5.0.7.Final.jar:5.0.7.Final]
           ... 215 common frames omitted

Note: previously when I had tried to select all rows and storing the results to Entity class with the dependencies Spring 3.1.3 + hibernate-entitymanager 3.5.3 + JPA 2.0 + ojdbc14-10.2.0.2.jar, I was able to fetch the results succesfully without any exception. 注意:以前,当我尝试选择所有行并将结果存储到具有依赖项Spring 3.1.3 + hibernate-entitymanager 3.5.3 + JPA 2.0 + ojdbc14-10.2.0.2.jar的实体类中时,我能够获取结果成功,没有任何异常。

Differences : 差异:

  1. jar version hibernate-entitymanager 3.5.3 & JPA of version 2.0 jar版本的hibernate-entitymanager 3.5.3和JPA的2.0版
  2. Query was select * .. 查询被选中* ..
  3. Entity class without the @SqlResultSetMapping annotation 没有 @SqlResultSetMapping批注的实体类

If I understand you question correctly you have an existing table with the following columns 如果我理解您的问题正确,那么您已有一个包含以下各列的表

  • name, firstName, lastName, age (possible more columns) 名称,名字,姓氏,年龄(可能还有更多列)

And you want to create an entity so you can get data from that table. 您想要创建一个实体,以便可以从该表中获取数据。

The first thing to note is that all JPA Entities MUST have a primary key (@ID column). 首先要注意的是,所有JPA实体必须具有主键(@ID列)。 Second, I have never had to use @SqlResultSetMapping for this to work. 其次,我从来不需要使用@SqlResultSetMapping来工作。

In our system we have a View that is mappe directly to an entity, there is no difference between this entity and any other entities in our system, if you didn't look in the database you would not know that there is no table (but a view) for this entity. 在我们的系统中,我们有一个直接映射到一个实体的View,该实体与我们系统中的任何其他实体之间没有区别,如果您不查看数据库,您将不会知道没有表(但是一个视图)。

Edit I can see I missed part of the question. 编辑我可以看到我错过了部分问题。 So here is what I thik you asked for. 因此,这就是您所要求的。

You need to look a JPQL Constructor Expression it basically allows you to select the columns you want into a POJO of your choice, but the constructor of the POJO must be able to the exact list of arguments. 您需要查看一个JPQL构造函数表达式,它基本上允许您将所需的列选择到您选择的POJO中,但是POJO的构造函数必须能够精确列出参数。

you can use criteria and projections 您可以使用条件和预测

Criteria query = session.createCriteria(CustomerEntity.class)
    .setProjection(Projections.projectionList()
                .add(Projections.property("customerId"), "customerId")
                .add(Projections.property("name"), "name")
                .add(Projections.property("firstName"), "firstName"));

query.setResultTransformer(new AliasToBeanResultTransformer(Sample.class));

List<Sample> list = query.list();

the Sample class 样本类

public class Sample {

    private String customerId;
    private String name;
    private String firstName;

    public Sample(){
    }

    public String getCustomerId() {
        return customerId;
    }
    public void setCustomerId(String customerId) {
        this.customerId = customerId;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }


}

Here is how you can do it: 这是您可以执行的操作:

List<Sample> resultList = new ArrayList<>();
ResultSet rs = query.getResultSet();

while (rs.next()) {
    ResultSetMetaData metadata = rs.getMetaData();

    for (int i = 1; i <= metadata.getColumnCount(); i++) {
        System.out.println("Column Name: " + metadata.getColumnName(i)
                + " | Value: " + rs.getObject(i));
    }

    Sample sample = new Sample();
    sample.setSomeValue(rs.getObject(1));
    sample.setSomeOtherValue(rs.getObject(2));

    resultList.add(sample);
}

Please note that here the use of ResultSetMetaData is optional. 请注意,这里使用ResultSetMetaData是可选的。 I have used it just to show how you can extract the Column Names if you want. 我用它来说明如何根据需要提取列名。

Here's one way to do it. 这是一种方法。

@Entity
@Table(name = "CUSTOMER")
@NamedNativeQuery(name = "findSampleMapping", 
    query = "SELECT CUSTOMER_ID, NAME, FIRST_NAME FROM CUSTOMER where CUSTOMER_ID = ?1", resultSetMapping = "SampleMapping")
@SqlResultSetMapping(name="SampleMapping",
classes = {
 @ConstructorResult(targetClass = com.entity.Sample.class,
   columns = {@ColumnResult(name="customerId"), @ColumnResult(name="name"), @ColumnResult(name="firstName")}
 )}
)
public class CustomerEntity {

    @Id
    @Column(name = "CUSTOMER_ID")
    private String customerId;

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

    @Column(name = "FIRST_NAME")
    private String firstName;

   @Column(name = "LAST_NAME")
    private String lastName;

   @Column(name = "AGE")
    private String age;
}



public class Sample {


    private String customerId;
    private String name;
    private String firstName;

    public Sample(String customerId, String name, String firstName){
        this.customerId = customerId;
        this.name = name;
        this.firstName = firstName;
    }

    public String getCustomerId() {
        return customerId;
    }
    public void setCustomerId(String customerId) {
        this.customerId = customerId;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }


}



Query q = em.createNamedQuery("findSampleMapping");
q.setParameter(1, "1");
@SuppressWarnings("unchecked")
List<Sample> list = q.getResultList();
for (Sample row : list) {
    System.out.println(row.getCustomerId());
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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