2012-04-10 11 views
3

JPAクエリでグループを使用しようとしています。クラスTeacherとクラスStudentがあるとします。 Teacherは、さらにStudentsを有することができ、Studentは、1つだけTeacher(1対多)を有することができる。JPAとPostgreSQL 9.0でグループ化

Query q = this.em.createQuery( "SELECT teacher, COUNT(student)" + 
           " FROM StudentJpa student" + 
           " JOIN student.teacher teacher" + 
           " GROUP BY teacher" + 
           " ORDER BY COUNT(student) DESC"); 

次のSQLクエリを生成します:

次JPAクエリが

はPostgreSQL 9.0で

select 
     teacherjpa1_.teacher_id as col_0_0_, 
     count(studentjpa0_.id) as col_1_0_, 
     teacherjpa1_.teacher_id as teacher1_0_, 
     teacherjpa1_.name as name0_ 
    from 
     student studentjpa0_ 
    inner join 
     teacher teacherjpa1_ 
      on studentjpa0_.teacher_id=teacherjpa1_.teacher_id 
    group by 
     teacherjpa1_.teacher_id 
    order by 
     count(studentjpa0_.id) DESC 

I次のエラーを取得する:

org.postgresql.util.PSQLException: ERROR: column "teacherjpa1_.name" must appear in the GROUP BY clause or be used in an aggregate function

同じエラーがdoesnの」 PostgreSQL 9.1に登場しました。

誰が、なぜ私を説明できますか? JPAが間違った方法でグループを生成しているようです.IDだけでなく、Teacherのすべての属性を含める必要があります。必要に応じて

これは、私のJPA/Hibernateは/ DBの構成です:

<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:context="http://www.springframework.org/schema/context" 
     xmlns:tx="http://www.springframework.org/schema/tx" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> 
    <context:property-placeholder location="/WEB-INF/jdbc.properties" /> 

    <bean id="dataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy"> 
     <constructor-arg> 
      <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
       <property name="driverClassName" value="org.postgresql.Driver" /> 
       <property name="url" value="${db.url}" /> 
       <property name="username" value="${db.username}" /> 
       <property name="password" value="${db.password}" /> 
      </bean> 
     </constructor-arg> 
    </bean> 

    <bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
     <property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" /> 
     <property name="showSql" value="${db.showSql}" /> 
     <property name="generateDdl" value="${db.generateDdl}" /> 
    </bean> 

    <!-- enabling annotation driven configuration /--> 
    <context:annotation-config /> 
    <context:component-scan base-package="my.package" /> 

    <!-- Instructs the container to look for beans with @Transactional and decorate them --> 
    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" /> 

    <!-- FactoryBean that creates the EntityManagerFactory --> 
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="jpaVendorAdapter" ref="jpaAdapter" /> 
     <property name="jpaProperties"> 
      <props> 
       <prop key="hibernate.format_sql">true</prop> 
       <prop key="hibernate.hbm2ddl.auto">update</prop> 
      </props> 
     </property> 
     <property name="dataSource" ref="dataSource" /> 
    </bean> 

    <!-- A transaction manager for working with JPA EntityManagerFactories --> 
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
     <property name="entityManagerFactory" ref="entityManagerFactory" /> 
    </bean> 
</beans> 

ありがとう!

更新 - 解決策はGROUP BY teacherの代わりにGROUP BY teacher.id, teacher.nameを指定することですが、それは実際には便利ではありません。より良い解決策はありますか?

+0

これはPostgreSQL 9.0で最も簡単なソリューションです。また、CTEを使用してGROUP BYを処理し、SELECT内のCTEを参照して他の列を参照することもできますが、単純ではありません。たぶんあなたはHerokuとして、最新のプロダクションリリースを提供することができました。 – kgrittn

+0

CTEは解決策ですが、まだそれは理想的ではありません。専用のデータベースを使用する場合、Heroku上で9.1にアップグレードすることができます。現時点では共有のものを使用しているので、9.1にアップグレードすることは問題になるかもしれないと思います...とにかく連絡します!おかげで – satoshi

答えて

5

このクエリはPostgreSQLリリース9.1で有効になりました。 PostgreSQLバージョン9.1をローカルで使用しているようで、Herokuは以前のものを使用しています。

は9.1のリリースノートを参照してください:このページで

http://www.postgresql.org/docs/9.1/interactive/release-9-1.html

を、クエリ]セクションの下に、それは言う:

Allow non-GROUP BY columns in the query target list when the primary key is specified in the GROUP BY clause (Peter Eisentraut)

The SQL standard allows this behavior, and because of the primary key, the result is unambiguous.

これは、PostgreSQLの以前のバージョンで動作するように取得するにはを追加ALL GROUP BY句に集約関数を使用しない選択リストの式。

+0

ありがとう、これは完全にHerokuで動作していない理由を説明します。実際、Herokuはまだバージョン9.0を使用しています。 JPAはなぜTeacher属性をすべて指定するのではなく、IDだけを指定してグループを生成するのですか?または、PostgreSQL 9.0で動作させるためにコードを変更するにはどうすればよいですか?ありがとう。 – satoshi

+0

答えを編集して、非集計式をすべてGROUP BY句に追加することでこれを修正できると説明しました。 – kgrittn

+0

ありがとう、@ kgrittn。明らかにこのソリューションは理想的ではありませんが、唯一のものであれば、私はこの答えを受け入れたものとしてマークします!もしあれば、別の解決策を待ってみましょう...ありがとう – satoshi

関連する問題