hibernate - 使用 JPA 和 PostgreSQL 9.0 分组

标签 hibernate postgresql jpa group-by

我正在尝试在 JPA 查询中使用分组依据。假设我有一个类 Teacher 和一个类 Student。一个 Teacher 可以有多个 Student,一个 Student 只能有一个 Teacher(一对多)。

以下 JPA 查询:

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 查询:

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

在 PostgreSQL 9.0 上我得到以下错误:

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

同样的错误在PostgreSQL 9.1中没有出现。

谁能解释一下为什么?似乎 JPA 以错误的方式生成组:它应该包括所有 Teacher 属性,而不仅仅是 id。

如果需要,这是我的 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.id, teacher.name 而不是 GROUP BY teacher,但事实并非如此方便的。有更好的解决方案吗?

最佳答案

该查询在 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 下工作,请将选择列表中不使用聚合函数的所有表达式添加到 GROUP BY 子句。

关于hibernate - 使用 JPA 和 PostgreSQL 9.0 分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10091178/

相关文章:

java - 设置对象时保留对象的值

postgresql - 对根元素 postgres 的 CTE 查询

java - JPA/hibernate : Update Parent column value before inserting child column value

java - 如何强制自动生成正向 hibernate 主键

database - 如何使用 hibernate 从数据库中获取系统日期、时间和时间戳

sql - postgres更新加入

sql - `unknown` 和类型推断的规则是什么?

java - 检查 JPQL 查询中集合的 NULL?

java - jpa原生查询控制实体(第3部分)

java - 如何在 hibernate 中添加一对多关系?