Skip to content

Commit 0f6dd05

Browse files
committed
HHH-18830 fallout from fix
remove ugly workaround for @MapKey/@MapKeyColumn, and add tests It looks like @beikov had already run into this bug in the context of map keys, and worked around it, not realizing that the problem also affected list indexes. Signed-off-by: Gavin King <[email protected]>
1 parent 4bd5223 commit 0f6dd05

File tree

5 files changed

+176
-12
lines changed

5 files changed

+176
-12
lines changed

hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -428,18 +428,6 @@ public AbstractCollectionPersister(
428428
indexFormulas[i] = indexForm.getFormula();
429429
hasFormula = true;
430430
}
431-
// Treat a mapped-by index like a formula to avoid trying to set it in insert/update
432-
// Previously this was a sub-query formula, but was changed to represent the proper mapping
433-
// which enables optimizations for queries. The old insert/update code wasn't adapted yet though.
434-
// For now, this is good enough, because the formula is never used anymore,
435-
// since all read paths go through the new code that can properly handle this case
436-
else if ( indexedCollection instanceof org.hibernate.mapping.Map map
437-
&& map.getMapKeyPropertyName() != null ) {
438-
final Column indexCol = (Column) selectable;
439-
indexFormulaTemplates[i] = Template.TEMPLATE + indexCol.getQuotedName( dialect );
440-
indexFormulas[i] = indexCol.getQuotedName( dialect );
441-
hasFormula = true;
442-
}
443431
else {
444432
final Column indexCol = (Column) selectable;
445433
indexColumnNames[i] = indexCol.getQuotedName( dialect );
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* SPDX-License-Identifier: LGPL-2.1-or-later
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.collection.mapkey;
6+
7+
import jakarta.persistence.Column;
8+
import jakarta.persistence.Entity;
9+
import jakarta.persistence.Id;
10+
import jakarta.persistence.MapKey;
11+
import jakarta.persistence.OneToMany;
12+
import jakarta.validation.constraints.Size;
13+
14+
import java.util.HashMap;
15+
import java.util.Map;
16+
17+
import static jakarta.persistence.CascadeType.PERSIST;
18+
19+
@Entity
20+
class Book {
21+
@Id
22+
@Size(min=10, max = 13)
23+
String isbn;
24+
25+
@OneToMany(cascade = PERSIST,
26+
mappedBy = "isbn")
27+
@MapKey(name = "name")
28+
Map<String,Chapter> chapters;
29+
30+
Book(String isbn) {
31+
this.isbn = isbn;
32+
chapters = new HashMap<>();
33+
}
34+
35+
Book() {
36+
}
37+
}
38+
39+
@Entity
40+
class Chapter {
41+
@Id String isbn;
42+
@Id @Column(name = "chapter_name") String name;
43+
String text;
44+
45+
Chapter(String isbn, String name, String text) {
46+
this.isbn = isbn;
47+
this.name = name;
48+
this.text = text;
49+
}
50+
51+
Chapter() {
52+
}
53+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* SPDX-License-Identifier: LGPL-2.1-or-later
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.collection.mapkey;
6+
7+
import org.hibernate.testing.jdbc.SQLStatementInspector;
8+
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
9+
import org.hibernate.testing.orm.junit.Jpa;
10+
import org.junit.jupiter.api.Test;
11+
12+
import java.util.List;
13+
14+
import static org.junit.jupiter.api.Assertions.assertEquals;
15+
16+
@Jpa(annotatedClasses = {Chapter.class, Book.class},
17+
useCollectingStatementInspector = true)
18+
public class MapKeyMappedByTest {
19+
@Test void test(EntityManagerFactoryScope scope) {
20+
scope.inTransaction( em -> {
21+
Book book = new Book( "XXX" );
22+
em.persist( book );
23+
book.chapters.put( "one", new Chapter("XXX", "one", "Lorem ipsum") );
24+
} );
25+
scope.inTransaction( em -> {
26+
Book book = em.find( Book.class, "XXX" );
27+
book.chapters.put( "two", new Chapter("XXX", "two", "Lorem ipsum") );
28+
} );
29+
List<String> queries = ((SQLStatementInspector) scope.getStatementInspector()).getSqlQueries();
30+
assertEquals( 5, queries.size() ); // we can't put in a Map without initializing it
31+
scope.inTransaction( em -> {
32+
assertEquals( em.find( Book.class, "XXX" ).chapters.size(), 2 );
33+
} );
34+
}
35+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* SPDX-License-Identifier: LGPL-2.1-or-later
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.collection.mapkeycolumn;
6+
7+
import jakarta.persistence.Column;
8+
import jakarta.persistence.Entity;
9+
import jakarta.persistence.Id;
10+
import jakarta.persistence.MapKeyColumn;
11+
import jakarta.persistence.OneToMany;
12+
import jakarta.validation.constraints.Size;
13+
14+
import java.util.HashMap;
15+
import java.util.Map;
16+
17+
import static jakarta.persistence.CascadeType.PERSIST;
18+
19+
@Entity
20+
class Book {
21+
@Id
22+
@Size(min=10, max = 13)
23+
String isbn;
24+
25+
@OneToMany(cascade = PERSIST,
26+
mappedBy = "isbn")
27+
@MapKeyColumn(name = "chapter_name")
28+
Map<String,Chapter> chapters;
29+
30+
Book(String isbn) {
31+
this.isbn = isbn;
32+
chapters = new HashMap<>();
33+
}
34+
35+
Book() {
36+
}
37+
}
38+
39+
@Entity
40+
class Chapter {
41+
@Id String isbn;
42+
@Id @Column(name = "chapter_name") String name;
43+
String text;
44+
45+
Chapter(String isbn, String name, String text) {
46+
this.isbn = isbn;
47+
this.name = name;
48+
this.text = text;
49+
}
50+
51+
Chapter() {
52+
}
53+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* SPDX-License-Identifier: LGPL-2.1-or-later
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.collection.mapkeycolumn;
6+
7+
import org.hibernate.testing.jdbc.SQLStatementInspector;
8+
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
9+
import org.hibernate.testing.orm.junit.Jpa;
10+
import org.junit.jupiter.api.Test;
11+
12+
import java.util.List;
13+
14+
import static org.junit.jupiter.api.Assertions.assertEquals;
15+
16+
@Jpa(annotatedClasses = {Chapter.class, Book.class},
17+
useCollectingStatementInspector = true)
18+
public class MapKeyColumnMappedByTest {
19+
@Test void test(EntityManagerFactoryScope scope) {
20+
scope.inTransaction( em -> {
21+
Book book = new Book( "XXX" );
22+
em.persist( book );
23+
book.chapters.put( "one", new Chapter("XXX", "one", "Lorem ipsum") );
24+
} );
25+
scope.inTransaction( em -> {
26+
Book book = em.find( Book.class, "XXX" );
27+
book.chapters.put( "two", new Chapter("XXX", "two", "Lorem ipsum") );
28+
} );
29+
List<String> queries = ((SQLStatementInspector) scope.getStatementInspector()).getSqlQueries();
30+
assertEquals( 5, queries.size() ); // we can't put in a Map without initializing it
31+
scope.inTransaction( em -> {
32+
assertEquals( em.find( Book.class, "XXX" ).chapters.size(), 2 );
33+
} );
34+
}
35+
}

0 commit comments

Comments
 (0)