Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import org.hibernate.metamodel.model.domain.ReturnableType;
import org.hibernate.query.sqm.NodeBuilder;
Expand Down Expand Up @@ -123,4 +124,24 @@ public void appendHqlString(StringBuilder hql, SqmRenderContext context) {
hql.append( ')' );
}
}

@Override
public boolean equals(Object o) {
if ( o == null || getClass() != o.getClass() ) {
return false;
}
if ( !super.equals( o ) ) {
return false;
}

SelfRenderingSqmAggregateFunction<?> that = (SelfRenderingSqmAggregateFunction<?>) o;
return Objects.equals( filter, that.filter );
}

@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + Objects.hashCode( filter );
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;

import org.hibernate.metamodel.mapping.BasicValuedMapping;
Expand Down Expand Up @@ -255,16 +254,4 @@ public MappingModelExpressible<?> get() {
return argumentTypeResolver.resolveFunctionArgumentType( function.getArguments(), argumentIndex, converter );
}
}

@Override
// TODO: override on all subtypes
public boolean equals(Object other) {
return other instanceof SelfRenderingSqmAggregateFunction<?> that
&& Objects.equals( this.toHqlString(), that.toHqlString() );
}

@Override
public int hashCode() {
return toHqlString().hashCode();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import org.hibernate.metamodel.model.domain.ReturnableType;
import org.hibernate.query.sqm.NodeBuilder;
Expand Down Expand Up @@ -173,4 +174,24 @@ public void appendHqlString(StringBuilder hql, SqmRenderContext context) {
hql.append( ')' );
}
}

@Override
public boolean equals(Object o) {
if ( o == null || getClass() != o.getClass() ) {
return false;
}
if ( !super.equals( o ) ) {
return false;
}

SelfRenderingSqmOrderedSetAggregateFunction<?> that = (SelfRenderingSqmOrderedSetAggregateFunction<?>) o;
return Objects.equals( withinGroup, that.withinGroup );
}

@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + Objects.hashCode( withinGroup );
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import org.hibernate.metamodel.model.domain.ReturnableType;
import org.hibernate.query.sqm.NodeBuilder;
Expand Down Expand Up @@ -157,4 +158,28 @@ public void appendHqlString(StringBuilder hql, SqmRenderContext context) {
hql.append( ')' );
}
}

@Override
public boolean equals(Object o) {
if ( o == null || getClass() != o.getClass() ) {
return false;
}
if ( !super.equals( o ) ) {
return false;
}

SelfRenderingSqmWindowFunction<?> that = (SelfRenderingSqmWindowFunction<?>) o;
return Objects.equals( filter, that.filter )
&& Objects.equals( respectNulls, that.respectNulls )
&& Objects.equals( fromFirst, that.fromFirst );
}

@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + Objects.hashCode( filter );
result = 31 * result + Objects.hashCode( respectNulls );
result = 31 * result + Objects.hashCode( fromFirst );
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,15 @@ public SqmPath<?> resolveIndexedAccess(

@Override
public boolean equals(Object other) {
return other instanceof SqmFunction<?> that
&& Objects.equals( this.functionName, that.functionName )
if ( this == other ) {
return true;
}
if ( other == null || getClass() != other.getClass() ) {
return false;
}

final SqmFunction<?> that = (SqmFunction<?>) other;
return Objects.equals( this.functionName, that.functionName )
&& Objects.equals( this.arguments, that.arguments );
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.SqmRenderContext;

import java.util.Objects;


/**
Expand Down Expand Up @@ -55,33 +54,17 @@ public void appendHqlString(StringBuilder hql, SqmRenderContext context) {
}

@Override
// TODO: fix this
public int compareTo(SqmParameter<T> parameter) {
return this == parameter ? 0 : 1;
return Integer.compare( hashCode(), parameter.hashCode() );
}

// this is not really a parameter, it's really a literal value
// so use value equality based on its value

@Override
public boolean equals(Object object) {
return object instanceof ValueBindJpaCriteriaParameter<?> that
&& Objects.equals( this.value, that.value );
// && getJavaTypeDescriptor().areEqual( this.value, (T) that.value );
return this == object;
}

@Override
public int hashCode() {
return value == null ? 0 : value.hashCode(); // getJavaTypeDescriptor().extractHashCode( value );
return super.hashCode();
}

// @Override
// public boolean equals(Object object) {
// return this == object;
// }
//
// @Override
// public int hashCode() {
// return System.identityHashCode( this );
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,81 +4,113 @@
*/
package org.hibernate.orm.test.jpa.query;

import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.Jpa;
import org.junit.jupiter.api.Test;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Lob;
import jakarta.persistence.Query;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaUpdate;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.ParameterExpression;
import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Root;
import jakarta.persistence.metamodel.EntityType;
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.Jpa;
import org.junit.jupiter.api.Test;

@Jpa(
annotatedClasses = CriteriaUpdateWithParametersTest.Person.class
)

@Jpa(annotatedClasses = {
CriteriaUpdateWithParametersTest.Person.class,
CriteriaUpdateWithParametersTest.Process.class
})
public class CriteriaUpdateWithParametersTest {

@Test
public void testCriteriaUpdate(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
final CriteriaUpdate<Person> criteriaUpdate = criteriaBuilder.createCriteriaUpdate( Person.class );
final Root<Person> root = criteriaUpdate.from( Person.class );

final ParameterExpression<Integer> intValueParameter = criteriaBuilder.parameter( Integer.class );
final ParameterExpression<String> stringValueParameter = criteriaBuilder.parameter( String.class );

final EntityType<Person> personEntityType = entityManager.getMetamodel().entity( Person.class );

criteriaUpdate.set(
root.get( personEntityType.getSingularAttribute( "age", Integer.class ) ),
intValueParameter
);
criteriaUpdate.where( criteriaBuilder.equal(
root.get( personEntityType.getSingularAttribute( "name", String.class ) ),
stringValueParameter
) );

final Query query = entityManager.createQuery( criteriaUpdate );
query.setParameter( intValueParameter, 9 );
query.setParameter( stringValueParameter, "Luigi" );

query.executeUpdate();
}
);
scope.inTransaction( entityManager -> {
final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
final CriteriaUpdate<Person> criteriaUpdate = criteriaBuilder.createCriteriaUpdate( Person.class );
final Root<Person> root = criteriaUpdate.from( Person.class );

final ParameterExpression<Integer> intValueParameter = criteriaBuilder.parameter( Integer.class );
final ParameterExpression<String> stringValueParameter = criteriaBuilder.parameter( String.class );

final EntityType<Person> personEntityType = entityManager.getMetamodel().entity( Person.class );

criteriaUpdate.set( root.get( personEntityType.getSingularAttribute( "age", Integer.class ) ),
intValueParameter );
criteriaUpdate.where(
criteriaBuilder.equal( root.get( personEntityType.getSingularAttribute( "name", String.class ) ),
stringValueParameter ) );

final Query query = entityManager.createQuery( criteriaUpdate );
query.setParameter( intValueParameter, 9 );
query.setParameter( stringValueParameter, "Luigi" );

query.executeUpdate();
} );
}

@Test
public void testCriteriaUpdate2(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
final CriteriaUpdate<Person> criteriaUpdate = criteriaBuilder.createCriteriaUpdate( Person.class );
final Root<Person> root = criteriaUpdate.from( Person.class );
scope.inTransaction( entityManager -> {
final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
final CriteriaUpdate<Person> criteriaUpdate = criteriaBuilder.createCriteriaUpdate( Person.class );
final Root<Person> root = criteriaUpdate.from( Person.class );

final ParameterExpression<Integer> intValueParameter = criteriaBuilder.parameter( Integer.class );
final ParameterExpression<String> stringValueParameter = criteriaBuilder.parameter( String.class );
final ParameterExpression<Integer> intValueParameter = criteriaBuilder.parameter( Integer.class );
final ParameterExpression<String> stringValueParameter = criteriaBuilder.parameter( String.class );

criteriaUpdate.set( "age", intValueParameter );
criteriaUpdate.where( criteriaBuilder.equal( root.get( "name" ), stringValueParameter ) );
criteriaUpdate.set( "age", intValueParameter );
criteriaUpdate.where( criteriaBuilder.equal( root.get( "name" ), stringValueParameter ) );

final Query query = entityManager.createQuery( criteriaUpdate );
query.setParameter( intValueParameter, 9 );
query.setParameter( stringValueParameter, "Luigi" );
final Query query = entityManager.createQuery( criteriaUpdate );
query.setParameter( intValueParameter, 9 );
query.setParameter( stringValueParameter, "Luigi" );

query.executeUpdate();
}
);
query.executeUpdate();
} );
}

@Test
public void testCriteriaUpdate3(EntityManagerFactoryScope scope) {
scope.inTransaction( em -> {
// test separate value-bind parameters
final CriteriaBuilder cb = em.getCriteriaBuilder();
final CriteriaUpdate<Process> cu = cb.createCriteriaUpdate( Process.class );
final Root<Process> root = cu.from( Process.class );
cu.set( root.get( "name" ), (Object) null );
cu.set( root.get( "payload" ), (Object) null );
em.createQuery( cu ).executeUpdate();
} );

scope.inTransaction( em -> {
// test with the same cb.value( null ) parameter instance
final HibernateCriteriaBuilder cb = (HibernateCriteriaBuilder) em.getCriteriaBuilder();
final CriteriaUpdate<Process> cu = cb.createCriteriaUpdate( Process.class );
final Root<Process> root = cu.from( Process.class );
final Expression<Object> nullValue = cb.value( null );
// a bit unfortunate, but we need to cast here to prevent ambiguous method references
final Path<String> name = root.get( "name" );
final Path<byte[]> payload = root.get( "payload" );
final Expression<? extends String> nullString = cast( nullValue );
final Expression<? extends byte[]> nullBytes = cast( nullValue );
cu.set( name, nullString );
cu.set( payload, nullBytes );
em.createQuery( cu ).executeUpdate();
} );
}

private static <X> Expression<? extends X> cast(Expression<?> expression) {
//noinspection unchecked
return (Expression<? extends X>) expression;
}

@Entity(name = "Person")
public static class Person {

@Id
private String id;

Expand All @@ -101,4 +133,18 @@ public Integer getAge() {
return age;
}
}

@Entity
public static class Process {
@Id
@GeneratedValue
private Long id;

// All attributes below are necessary to reproduce the issue

private String name;

@Lob
private byte[] payload;
}
}