Skip to content

Commit 61d5ab4

Browse files
committed
HHH-17170 Add test for issue
1 parent 5635a33 commit 61d5ab4

File tree

3 files changed

+505
-0
lines changed

3 files changed

+505
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
5+
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
6+
*/
7+
package org.hibernate.orm.test.mapping.collections;
8+
9+
import java.util.ArrayList;
10+
import java.util.Comparator;
11+
import java.util.HashSet;
12+
import java.util.List;
13+
import java.util.Set;
14+
15+
import org.hibernate.annotations.SQLDeleteAll;
16+
import org.hibernate.annotations.SQLUpdate;
17+
18+
import org.hibernate.testing.jdbc.SQLStatementInspector;
19+
import org.hibernate.testing.orm.junit.DomainModel;
20+
import org.hibernate.testing.orm.junit.Jira;
21+
import org.hibernate.testing.orm.junit.SessionFactory;
22+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
23+
import org.junit.jupiter.api.BeforeAll;
24+
import org.junit.jupiter.api.Test;
25+
26+
import jakarta.persistence.CollectionTable;
27+
import jakarta.persistence.ElementCollection;
28+
import jakarta.persistence.Embeddable;
29+
import jakarta.persistence.Entity;
30+
import jakarta.persistence.Id;
31+
import jakarta.persistence.JoinColumn;
32+
import jakarta.persistence.OrderColumn;
33+
import jakarta.persistence.Table;
34+
35+
import static org.assertj.core.api.Assertions.assertThat;
36+
37+
/**
38+
* @author Marco Belladelli
39+
*/
40+
@DomainModel( annotatedClasses = {
41+
ElementCollectionCustomSqlMutationsTest.Project.class,
42+
ElementCollectionCustomSqlMutationsTest.User.class,
43+
} )
44+
@SessionFactory
45+
@Jira( "https://hibernate.atlassian.net/browse/HHH-17170" )
46+
public class ElementCollectionCustomSqlMutationsTest {
47+
@BeforeAll
48+
public void setUp(SessionFactoryScope scope) {
49+
scope.inTransaction( session -> {
50+
final User u1 = new User( "user1" );
51+
final User u2 = new User( "user2" );
52+
final Project p1 = new Project( "p1" );
53+
p1.getMembers().add( u1 );
54+
p1.getMembers().add( u2 );
55+
final Project p2 = new Project( "p2" );
56+
p2.getMembers().add( u1 );
57+
p2.getOrderedUsers().add( u2 );
58+
p2.getOrderedUsers().add( u1 );
59+
session.persist( p1 );
60+
session.persist( p2 );
61+
} );
62+
}
63+
64+
@Test
65+
public void testSQLDelete(SessionFactoryScope scope) {
66+
final SQLStatementInspector inspector = scope.getCollectingStatementInspector();
67+
scope.inTransaction( session -> {
68+
final Project project = session.find( Project.class, "p1" );
69+
project.getMembers().remove( project.getMembers().iterator().next() );
70+
inspector.clear();
71+
} );
72+
// element collection always deletes all records and re-inserts the ones remaining
73+
// the @SQLDelete annotation is ignored
74+
assertThat( inspector.getSqlQueries() ).hasSize( 2 );
75+
assertThat( inspector.getSqlQueries().get( 0 ) ).contains( "1=1" );
76+
scope.inTransaction( session -> assertThat(
77+
session.find( Project.class, "p1" ).getMembers()
78+
).hasSize( 1 ) );
79+
}
80+
81+
@Test
82+
public void testSQLDeleteAll(SessionFactoryScope scope) {
83+
final SQLStatementInspector inspector = scope.getCollectingStatementInspector();
84+
scope.inTransaction( session -> {
85+
final Project project = session.find( Project.class, "p2" );
86+
project.getMembers().remove( project.getMembers().iterator().next() );
87+
inspector.clear();
88+
} );
89+
assertThat( inspector.getSqlQueries() ).hasSize( 1 );
90+
assertThat( inspector.getSqlQueries().get( 0 ) ).contains( "1=1" );
91+
scope.inTransaction( session -> assertThat(
92+
session.find( Project.class, "p2" ).getMembers()
93+
).isEmpty() );
94+
}
95+
96+
@Test
97+
public void testSQLUpdate(SessionFactoryScope scope) {
98+
final SQLStatementInspector inspector = scope.getCollectingStatementInspector();
99+
scope.inTransaction( session -> {
100+
final Project project = session.find( Project.class, "p2" );
101+
assertThat( project.getOrderedUsers().stream().map( User::getName ) ).containsExactly( "user2", "user1" );
102+
project.getOrderedUsers().sort( Comparator.comparing( User::getName ) );
103+
inspector.clear();
104+
} );
105+
assertThat( inspector.getSqlQueries() ).hasSize( 2 );
106+
assertThat( inspector.getSqlQueries().get( 0 ) ).contains( "3=3" );
107+
assertThat( inspector.getSqlQueries().get( 1 ) ).contains( "3=3" );
108+
scope.inTransaction( session -> {
109+
final Project project = session.find( Project.class, "p2" );
110+
assertThat( project.getOrderedUsers().stream().map( User::getName ) ).containsExactly( "user1", "user2" );
111+
} );
112+
}
113+
114+
@Entity( name = "Project" )
115+
@Table( name = "t_project" )
116+
public static class Project {
117+
@Id
118+
private String name;
119+
120+
@ElementCollection
121+
@CollectionTable( name = "project_users", joinColumns = { @JoinColumn( name = "project_id" ) } )
122+
@SQLDeleteAll( sql = "delete from project_users where project_id = ? and 1=1" )
123+
private Set<User> members = new HashSet<>();
124+
125+
@ElementCollection
126+
@CollectionTable( name = "ordered_users", joinColumns = { @JoinColumn( name = "project_id" ) } )
127+
@OrderColumn( name = "order_col" )
128+
@SQLUpdate( sql = "update ordered_users set name = ? where project_id = ? and order_col = ? and 3=3" )
129+
private List<User> orderedUsers = new ArrayList<>();
130+
131+
public Project() {
132+
}
133+
134+
public Project(String name) {
135+
this.name = name;
136+
}
137+
138+
public Set<User> getMembers() {
139+
return members;
140+
}
141+
142+
public List<User> getOrderedUsers() {
143+
return orderedUsers;
144+
}
145+
}
146+
147+
@Embeddable
148+
public static class User {
149+
private String name;
150+
151+
public User() {
152+
}
153+
154+
public User(String name) {
155+
this.name = name;
156+
}
157+
158+
public String getName() {
159+
return name;
160+
}
161+
}
162+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
5+
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
6+
*/
7+
package org.hibernate.orm.test.mapping.manytomany;
8+
9+
import java.util.ArrayList;
10+
import java.util.Comparator;
11+
import java.util.HashSet;
12+
import java.util.List;
13+
import java.util.Set;
14+
15+
import org.hibernate.annotations.SQLDelete;
16+
import org.hibernate.annotations.SQLDeleteAll;
17+
import org.hibernate.annotations.SQLUpdate;
18+
19+
import org.hibernate.testing.jdbc.SQLStatementInspector;
20+
import org.hibernate.testing.orm.junit.DomainModel;
21+
import org.hibernate.testing.orm.junit.Jira;
22+
import org.hibernate.testing.orm.junit.SessionFactory;
23+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
24+
import org.junit.jupiter.api.BeforeAll;
25+
import org.junit.jupiter.api.Test;
26+
27+
import jakarta.persistence.Entity;
28+
import jakarta.persistence.Id;
29+
import jakarta.persistence.JoinColumn;
30+
import jakarta.persistence.JoinTable;
31+
import jakarta.persistence.ManyToMany;
32+
import jakarta.persistence.OrderColumn;
33+
import jakarta.persistence.Table;
34+
35+
import static org.assertj.core.api.Assertions.assertThat;
36+
37+
/**
38+
* Same as {@link org.hibernate.orm.test.mapping.onetomany.OneToManyCustomSqlMutationsTest OneToManyCustomSqlMutationsTest}
39+
* but with {@link ManyToMany}
40+
*
41+
* @author Marco Belladelli
42+
*/
43+
@DomainModel( annotatedClasses = {
44+
ManyToManyCustomSqlMutationsTest.Project.class,
45+
ManyToManyCustomSqlMutationsTest.User.class,
46+
} )
47+
@SessionFactory( useCollectingStatementInspector = true )
48+
@Jira( "https://hibernate.atlassian.net/browse/HHH-17170" )
49+
public class ManyToManyCustomSqlMutationsTest {
50+
@BeforeAll
51+
public void setUp(SessionFactoryScope scope) {
52+
scope.inTransaction( session -> {
53+
final User u1 = new User( "user1" );
54+
final User u2 = new User( "user2" );
55+
final Project p1 = new Project( "p1" );
56+
p1.getMembers().add( u1 );
57+
p1.getMembers().add( u2 );
58+
final Project p2 = new Project( "p2" );
59+
p2.getMembers().add( u1 );
60+
p2.getOrderedUsers().add( u2 );
61+
p2.getOrderedUsers().add( u1 );
62+
session.persist( u1 );
63+
session.persist( u2 );
64+
session.persist( p1 );
65+
session.persist( p2 );
66+
} );
67+
}
68+
69+
@Test
70+
public void testSQLDelete(SessionFactoryScope scope) {
71+
final SQLStatementInspector inspector = scope.getCollectingStatementInspector();
72+
scope.inTransaction( session -> {
73+
final Project project = session.find( Project.class, "p1" );
74+
project.getMembers().remove( project.getMembers().iterator().next() );
75+
inspector.clear();
76+
} );
77+
assertThat( inspector.getSqlQueries() ).hasSize( 1 );
78+
assertThat( inspector.getSqlQueries().get( 0 ) ).contains( "1=1" );
79+
scope.inTransaction( session -> assertThat(
80+
session.find( Project.class, "p1" ).getMembers()
81+
).hasSize( 1 ) );
82+
}
83+
84+
@Test
85+
public void testSQLDeleteAll(SessionFactoryScope scope) {
86+
final SQLStatementInspector inspector = scope.getCollectingStatementInspector();
87+
scope.inTransaction( session -> {
88+
final Project project = session.find( Project.class, "p2" );
89+
project.getMembers().remove( project.getMembers().iterator().next() );
90+
inspector.clear();
91+
} );
92+
assertThat( inspector.getSqlQueries() ).hasSize( 1 );
93+
assertThat( inspector.getSqlQueries().get( 0 ) ).contains( "2=2" );
94+
scope.inTransaction( session -> assertThat(
95+
session.find( Project.class, "p2" ).getMembers()
96+
).isEmpty() );
97+
}
98+
99+
@Test
100+
public void testSQLUpdate(SessionFactoryScope scope) {
101+
final SQLStatementInspector inspector = scope.getCollectingStatementInspector();
102+
scope.inTransaction( session -> {
103+
final Project project = session.find( Project.class, "p2" );
104+
assertThat( project.getOrderedUsers().stream().map( User::getName ) ).containsExactly( "user2", "user1" );
105+
project.getOrderedUsers().sort( Comparator.comparing( User::getName ) );
106+
inspector.clear();
107+
} );
108+
assertThat( inspector.getSqlQueries() ).hasSize( 2 );
109+
assertThat( inspector.getSqlQueries().get( 0 ) ).contains( "3=3" );
110+
assertThat( inspector.getSqlQueries().get( 1 ) ).contains( "3=3" );
111+
scope.inTransaction( session -> {
112+
final Project project = session.find( Project.class, "p2" );
113+
assertThat( project.getOrderedUsers().stream().map( User::getName ) ).containsExactly( "user1", "user2" );
114+
} );
115+
}
116+
117+
@Entity( name = "Project" )
118+
@Table( name = "t_project" )
119+
public static class Project {
120+
@Id
121+
private String name;
122+
123+
@ManyToMany
124+
@JoinTable(
125+
name = "project_users",
126+
joinColumns = { @JoinColumn( name = "project_id" ) },
127+
inverseJoinColumns = { @JoinColumn( name = "user_id" ) }
128+
)
129+
@SQLDelete( sql = "delete from project_users where project_id = ? and user_id = ? and 1=1" )
130+
@SQLDeleteAll( sql = "delete from project_users where project_id = ? and 2=2" )
131+
private Set<User> members = new HashSet<>();
132+
133+
@ManyToMany
134+
@JoinTable(
135+
name = "ordered_users",
136+
joinColumns = { @JoinColumn( name = "project_id" ) },
137+
inverseJoinColumns = { @JoinColumn( name = "user_id" ) }
138+
)
139+
@OrderColumn( name = "order_col" )
140+
@SQLUpdate( sql = "update ordered_users set user_id = ? where project_id = ? and order_col = ? and 3=3" )
141+
private List<User> orderedUsers = new ArrayList<>();
142+
143+
public Project() {
144+
}
145+
146+
public Project(String name) {
147+
this.name = name;
148+
}
149+
150+
public Set<User> getMembers() {
151+
return members;
152+
}
153+
154+
public List<User> getOrderedUsers() {
155+
return orderedUsers;
156+
}
157+
}
158+
159+
@Entity( name = "User" )
160+
@Table( name = "t_user" )
161+
public static class User {
162+
@Id
163+
private String name;
164+
165+
public User() {
166+
}
167+
168+
public User(String name) {
169+
this.name = name;
170+
}
171+
172+
public String getName() {
173+
return name;
174+
}
175+
}
176+
}

0 commit comments

Comments
 (0)