HHH-5419: Modified HQL rendering of COUNT function so that when a non-distinct entity with an ID is specified as a parameter, it renders a star instead of the ID attribute(s). This allows for greater support across DBs, since some do not support the previous rendering of multiple ID attributes when the ID happens to be a composite ID.
This commit is contained in:
parent
9039e4d29e
commit
7d70a909c5
|
@ -23,7 +23,9 @@
|
|||
*/
|
||||
package org.hibernate.ejb.criteria.expression.function;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import javax.persistence.criteria.Expression;
|
||||
import javax.persistence.criteria.Root;
|
||||
import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
|
||||
import org.hibernate.ejb.criteria.CriteriaQueryCompiler;
|
||||
import org.hibernate.ejb.criteria.expression.LiteralExpression;
|
||||
|
@ -92,11 +94,27 @@ public class AggregationFunction<T>
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void renderArguments(StringBuilder buffer, CriteriaQueryCompiler.RenderingContext renderingContext) {
|
||||
if ( isDistinct() ) {
|
||||
buffer.append( "distinct " );
|
||||
protected void renderArguments( StringBuilder buffer,
|
||||
CriteriaQueryCompiler.RenderingContext renderingContext ) {
|
||||
if (isDistinct()) buffer.append("distinct ");
|
||||
else {
|
||||
// If function specifies a single non-distinct entity with ID, its alias would normally be rendered, which ends up
|
||||
// converting to the column(s) associated with the entity's ID in the rendered SQL. However, some DBs don't support
|
||||
// the multiple columns that would end up here for entities with composite IDs. So, since we modify the query to
|
||||
// instead specify star since that's functionally equivalent and supported by all DBs.
|
||||
List<Expression<?>> argExprs = getArgumentExpressions();
|
||||
if (argExprs.size() == 1) {
|
||||
Expression argExpr = argExprs.get(0);
|
||||
if (argExpr instanceof Root<?>) {
|
||||
Root<?> root = (Root<?>)argExpr;
|
||||
if (root.getModel().getIdType() != null) {
|
||||
buffer.append('*');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
super.renderArguments( buffer, renderingContext );
|
||||
super.renderArguments(buffer, renderingContext);
|
||||
}
|
||||
|
||||
public boolean isDistinct() {
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package org.hibernate.ejb.test;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Embeddable
|
||||
public class CompositeId implements Serializable {
|
||||
|
||||
private int id1;
|
||||
private int id2;
|
||||
|
||||
public int getId1() {
|
||||
return id1;
|
||||
}
|
||||
|
||||
public void setId1( int id1 ) {
|
||||
this.id1 = id1;
|
||||
}
|
||||
|
||||
public int getId2() {
|
||||
return id2;
|
||||
}
|
||||
|
||||
public void setId2( int id2 ) {
|
||||
this.id2 = id2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals( Object obj ) {
|
||||
if (obj == null) return false;
|
||||
if (getClass() != obj.getClass()) return false;
|
||||
final CompositeId other = (CompositeId)obj;
|
||||
if (this.id1 != other.id1) return false;
|
||||
if (this.id2 != other.id2) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 5;
|
||||
hash = 73 * hash + this.id1;
|
||||
hash = 73 * hash + this.id2;
|
||||
return hash;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.ejb.test;
|
||||
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Root;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class CountEntityWithCompositeIdTest extends BaseEntityManagerFunctionalTestCase {
|
||||
|
||||
@Test
|
||||
public void shouldCount() {
|
||||
EntityManager em = getOrCreateEntityManager();
|
||||
CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
|
||||
Root<EntityWithCompositeId> r = cq.from(EntityWithCompositeId.class);
|
||||
cq.multiselect(cb.count(r));
|
||||
assertThat(em.createQuery(cq).getSingleResult().intValue(), is(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class[] getAnnotatedClasses() {
|
||||
return new Class[] {EntityWithCompositeId.class, CompositeId.class};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package org.hibernate.ejb.test;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Entity
|
||||
public class EntityWithCompositeId implements Serializable {
|
||||
|
||||
@EmbeddedId
|
||||
private CompositeId id;
|
||||
private String description;
|
||||
|
||||
public CompositeId getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(CompositeId id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue