Skip to content

Commit 877b76e

Browse files
tcordelmbellade
authored andcommitted
HHH-19862: fix CriteriaUpdate for converted field
1 parent c22aaee commit 877b76e

File tree

3 files changed

+136
-1
lines changed

3 files changed

+136
-1
lines changed

hibernate-core/src/main/java/org/hibernate/query/sqm/tree/update/SqmUpdateStatement.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,9 @@ public void setSetClause(SqmSetClause setClause) {
173173

174174
@Override
175175
public <Y, X extends Y> SqmUpdateStatement<T> set(SingularAttribute<? super T, Y> attribute, X value) {
176-
applyAssignment( getTarget().get( attribute ), (SqmExpression<? extends Y>) nodeBuilder().value( value ) );
176+
final SqmCriteriaNodeBuilder nodeBuilder = (SqmCriteriaNodeBuilder) nodeBuilder();
177+
SqmPath<Y> sqmAttribute = getTarget().get( attribute );
178+
applyAssignment( sqmAttribute, nodeBuilder.value( value, sqmAttribute) );
177179
return this;
178180
}
179181

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.jpa.criteria.convert;
6+
7+
import jakarta.persistence.criteria.CriteriaBuilder;
8+
import jakarta.persistence.criteria.CriteriaUpdate;
9+
import jakarta.persistence.criteria.Root;
10+
import org.hibernate.testing.orm.junit.DomainModel;
11+
import org.hibernate.testing.orm.junit.JiraKey;
12+
import org.hibernate.testing.orm.junit.SessionFactory;
13+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
14+
import org.hibernate.testing.orm.junit.SessionFactoryScopeAware;
15+
import org.junit.jupiter.params.ParameterizedTest;
16+
import org.junit.jupiter.params.provider.Arguments;
17+
import org.junit.jupiter.params.provider.MethodSource;
18+
19+
import java.util.Date;
20+
import java.util.function.Consumer;
21+
import java.util.stream.Stream;
22+
23+
import static org.junit.jupiter.api.Assertions.assertEquals;
24+
25+
@DomainModel(annotatedClasses = {Log.class})
26+
@SessionFactory
27+
@JiraKey(value = "HHH-19862")
28+
public class ConvertedDateAttributeTest implements SessionFactoryScopeAware {
29+
private SessionFactoryScope scope;
30+
31+
@ParameterizedTest
32+
@MethodSource("criteriaUpdateFieldSetters")
33+
public void testConvertedFieldUpdateUsingPath(Consumer<UpdateContext> criteriaUpdateFieldSetter) {
34+
35+
scope.inTransaction( (session) -> {
36+
Log log = new Log();
37+
session.persist( log );
38+
39+
final CriteriaBuilder cb = session.getCriteriaBuilder();
40+
final CriteriaUpdate<Log> query = cb.createCriteriaUpdate( Log.class );
41+
final Root<Log> root = query.from( Log.class );
42+
query.where( cb.equal( root.get( Log_.id ), log.getId() ) );
43+
Date update = new Date();
44+
criteriaUpdateFieldSetter.accept( new UpdateContext( query, root, update ) );
45+
46+
int updates = session.createMutationQuery( query ).executeUpdate();
47+
session.refresh( log );
48+
49+
assertEquals( 1, updates );
50+
assertEquals( log.getLastUpdate(), update );
51+
52+
} );
53+
}
54+
55+
@Override
56+
public void injectSessionFactoryScope(SessionFactoryScope scope) {
57+
this.scope = scope;
58+
}
59+
60+
static class UpdateContext {
61+
final CriteriaUpdate<Log> query;
62+
final Root<Log> root;
63+
final Date lastUpdate;
64+
65+
public UpdateContext(CriteriaUpdate<Log> query, Root<Log> root, Date lastUpdate) {
66+
this.query = query;
67+
this.root = root;
68+
this.lastUpdate = lastUpdate;
69+
}
70+
}
71+
72+
static Stream<Arguments> criteriaUpdateFieldSetters() {
73+
Consumer<UpdateContext> updateUsingPath = context ->
74+
context.query.set( context.root.get( Log_.lastUpdate ), context.lastUpdate );
75+
Consumer<UpdateContext> updateUsingSingularAttribute = context ->
76+
context.query.set( Log_.lastUpdate, context.lastUpdate );
77+
Consumer<UpdateContext> updateUsingName = context ->
78+
context.query.set( Log_.LAST_UPDATE, context.lastUpdate );
79+
return Stream.of(
80+
Arguments.of( updateUsingPath ),
81+
Arguments.of( updateUsingSingularAttribute ),
82+
Arguments.of( updateUsingName )
83+
);
84+
}
85+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.jpa.criteria.convert;
6+
7+
import jakarta.persistence.AttributeConverter;
8+
import jakarta.persistence.Convert;
9+
import jakarta.persistence.Converter;
10+
import jakarta.persistence.Entity;
11+
import jakarta.persistence.GeneratedValue;
12+
import jakarta.persistence.GenerationType;
13+
import jakarta.persistence.Id;
14+
15+
import java.util.Date;
16+
@Entity
17+
public class Log {
18+
@Id
19+
@GeneratedValue(strategy = GenerationType.IDENTITY)
20+
private Long id;
21+
@Convert(converter = DateConverter.class)
22+
private Date lastUpdate;
23+
@Converter
24+
static class DateConverter implements AttributeConverter<Date, Long> {
25+
@Override
26+
public Long convertToDatabaseColumn(Date date) {
27+
if (null == date) {
28+
return null;
29+
}
30+
return date.getTime();
31+
}
32+
@Override
33+
public Date convertToEntityAttribute(Long dbDate) {
34+
if (null == dbDate) {
35+
return null;
36+
}
37+
return new Date( dbDate );
38+
}
39+
}
40+
41+
public Long getId() {
42+
return id;
43+
}
44+
45+
public Date getLastUpdate() {
46+
return lastUpdate;
47+
}
48+
}

0 commit comments

Comments
 (0)