Skip to content

Commit 9f84156

Browse files
dreab8DavideD
authored andcommitted
[#2006] Add test for UnexpectedAccessToTheDatabase error when merging a detached entity with a ToMany association
1 parent 0064771 commit 9f84156

File tree

3 files changed

+616
-0
lines changed

3 files changed

+616
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
/* Hibernate, Relational Persistence for Idiomatic Java
2+
*
3+
* SPDX-License-Identifier: Apache-2.0
4+
* Copyright: Red Hat Inc. and Hibernate Authors
5+
*/
6+
package org.hibernate.reactive;
7+
8+
import java.util.Collection;
9+
import java.util.List;
10+
import java.util.Objects;
11+
12+
import org.junit.jupiter.api.BeforeEach;
13+
import org.junit.jupiter.api.Test;
14+
15+
import io.vertx.junit5.Timeout;
16+
import io.vertx.junit5.VertxTestContext;
17+
import jakarta.persistence.Entity;
18+
import jakarta.persistence.FetchType;
19+
import jakarta.persistence.Id;
20+
import jakarta.persistence.OneToMany;
21+
import jakarta.persistence.Table;
22+
23+
import static java.util.concurrent.TimeUnit.MINUTES;
24+
import static org.assertj.core.api.Assertions.assertThat;
25+
26+
@Timeout(value = 2, timeUnit = MINUTES)
27+
public class OneToManyArrayMergeTest extends BaseReactiveTest {
28+
29+
private final static Long USER_ID = 1L;
30+
private final static Long ADMIN_ROLE_ID = 2L;
31+
private final static Long USER_ROLE_ID = 3L;
32+
private final static String UPDATED_FIRSTNAME = "UPDATED FIRSTNAME";
33+
private final static String UPDATED_LASTNAME = "UPDATED LASTNAME";
34+
35+
@Override
36+
protected Collection<Class<?>> annotatedEntities() {
37+
return List.of( User.class, Role.class );
38+
}
39+
40+
@BeforeEach
41+
public void populateDb(VertxTestContext context) {
42+
Role adminRole = new Role( ADMIN_ROLE_ID, "admin" );
43+
Role userRole = new Role( USER_ROLE_ID, "user" );
44+
User user = new User( USER_ID, "first", "last", adminRole );
45+
test(
46+
context, getMutinySessionFactory()
47+
.withTransaction( s -> s.persistAll( user, adminRole, userRole ) )
48+
);
49+
}
50+
51+
@Test
52+
public void testMerge(VertxTestContext context) {
53+
test(
54+
context, getMutinySessionFactory()
55+
.withTransaction( s -> s.find( User.class, USER_ID ) )
56+
.chain( user -> getMutinySessionFactory()
57+
.withTransaction( s -> s
58+
.createQuery( "FROM Role", Role.class )
59+
.getResultList() )
60+
.map( roles -> {
61+
user.addAll( roles );
62+
user.setFirstname( UPDATED_FIRSTNAME );
63+
user.setLastname( UPDATED_LASTNAME );
64+
return user;
65+
} )
66+
)
67+
.chain( user -> {
68+
assertThat( user.getFirstname() ).isEqualTo( UPDATED_FIRSTNAME );
69+
assertThat( user.getLastname() ).isEqualTo( UPDATED_LASTNAME );
70+
assertThat( user.getRoles() ).hasSize( 2 );
71+
return getMutinySessionFactory()
72+
.withTransaction( s -> s.merge( user ) );
73+
}
74+
)
75+
.chain( v -> getMutinySessionFactory()
76+
.withTransaction( s -> s.find( User.class, USER_ID ) )
77+
)
78+
.invoke( user -> {
79+
Role adminRole = new Role( ADMIN_ROLE_ID, "admin" );
80+
Role userRole = new Role( USER_ROLE_ID, "user" );
81+
assertThat( user.getFirstname() ).isEqualTo( UPDATED_FIRSTNAME );
82+
assertThat( user.getLastname() ).isEqualTo( UPDATED_LASTNAME );
83+
assertThat( user.getRoles() ).containsExactlyInAnyOrder(
84+
adminRole,
85+
userRole
86+
);
87+
}
88+
)
89+
);
90+
}
91+
92+
@Entity(name = "User")
93+
@Table(name = "USER_TABLE")
94+
public static class User {
95+
96+
@Id
97+
private Long id;
98+
99+
private String firstname;
100+
101+
private String lastname;
102+
103+
@OneToMany(fetch = FetchType.EAGER)
104+
private Role[] roles;
105+
106+
public User() {
107+
}
108+
109+
public User(Long id, String firstname, String lastname, Role... roles) {
110+
this.id = id;
111+
this.firstname = firstname;
112+
this.lastname = lastname;
113+
this.roles = new Role[roles.length];
114+
for ( int i = 0; i < roles.length; i++ ) {
115+
this.roles[i] = roles[i];
116+
}
117+
}
118+
119+
public Long getId() {
120+
return id;
121+
}
122+
123+
public String getFirstname() {
124+
return firstname;
125+
}
126+
127+
public void setFirstname(String firstname) {
128+
this.firstname = firstname;
129+
}
130+
131+
public String getLastname() {
132+
return lastname;
133+
}
134+
135+
public void setLastname(String lastname) {
136+
this.lastname = lastname;
137+
}
138+
139+
public Role[] getRoles() {
140+
return roles;
141+
}
142+
143+
public void addAll(List<Role> roles) {
144+
this.roles = new Role[roles.size()];
145+
for ( int i = 0; i < roles.size(); i++ ) {
146+
this.roles[i] = roles.get( i );
147+
}
148+
}
149+
}
150+
151+
@Entity(name = "Role")
152+
@Table(name = "ROLE_TABLE")
153+
public static class Role {
154+
155+
@Id
156+
private Long id;
157+
private String code;
158+
159+
public Role() {
160+
}
161+
162+
public Role(Long id, String code) {
163+
this.id = id;
164+
this.code = code;
165+
}
166+
167+
public Object getId() {
168+
return id;
169+
}
170+
171+
@Override
172+
public boolean equals(Object o) {
173+
if ( o == null || getClass() != o.getClass() ) {
174+
return false;
175+
}
176+
Role role = (Role) o;
177+
return Objects.equals( id, role.id ) && Objects.equals( code, role.code );
178+
}
179+
180+
@Override
181+
public int hashCode() {
182+
return Objects.hash( id, code );
183+
}
184+
185+
@Override
186+
public String toString() {
187+
return "Role{" + code + '}';
188+
}
189+
}
190+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
/* Hibernate, Relational Persistence for Idiomatic Java
2+
*
3+
* SPDX-License-Identifier: Apache-2.0
4+
* Copyright: Red Hat Inc. and Hibernate Authors
5+
*/
6+
package org.hibernate.reactive;
7+
8+
import java.util.Collection;
9+
import java.util.HashMap;
10+
import java.util.List;
11+
import java.util.Map;
12+
import java.util.Objects;
13+
14+
import org.junit.jupiter.api.BeforeEach;
15+
import org.junit.jupiter.api.Test;
16+
17+
import io.vertx.junit5.Timeout;
18+
import io.vertx.junit5.VertxTestContext;
19+
import jakarta.persistence.Entity;
20+
import jakarta.persistence.FetchType;
21+
import jakarta.persistence.Id;
22+
import jakarta.persistence.OneToMany;
23+
import jakarta.persistence.Table;
24+
25+
import static java.util.concurrent.TimeUnit.MINUTES;
26+
import static org.assertj.core.api.Assertions.assertThat;
27+
28+
@Timeout(value = 2, timeUnit = MINUTES)
29+
public class OneToManyMapMergeTest extends BaseReactiveTest {
30+
31+
private final static Long USER_ID = 1L;
32+
private final static Long ADMIN_ROLE_ID = 2L;
33+
private final static Long USER_ROLE_ID = 3L;
34+
private final static String UPDATED_FIRSTNAME = "UPDATED FIRSTNAME";
35+
private final static String UPDATED_LASTNAME = "UPDATED LASTNAME";
36+
37+
@Override
38+
protected Collection<Class<?>> annotatedEntities() {
39+
return List.of( User.class, Role.class );
40+
}
41+
42+
@BeforeEach
43+
public void populateDb(VertxTestContext context) {
44+
Role adminRole = new Role( ADMIN_ROLE_ID, "admin" );
45+
Role userRole = new Role( USER_ROLE_ID, "user" );
46+
User user = new User( USER_ID, "first", "last", adminRole );
47+
test(
48+
context, getMutinySessionFactory()
49+
.withTransaction( s -> s.persistAll( user, adminRole, userRole ) )
50+
);
51+
}
52+
53+
@Test
54+
public void testMerge(VertxTestContext context) {
55+
test(
56+
context, getMutinySessionFactory()
57+
.withTransaction( s -> s.find( User.class, USER_ID ) )
58+
.chain( user -> getMutinySessionFactory()
59+
.withTransaction( s -> s
60+
.createQuery( "FROM Role", Role.class )
61+
.getResultList() )
62+
.map( roles -> {
63+
user.addAll( roles );
64+
user.setFirstname( UPDATED_FIRSTNAME );
65+
user.setLastname( UPDATED_LASTNAME );
66+
return user;
67+
} )
68+
)
69+
.chain( user -> {
70+
assertThat( user.getFirstname() ).isEqualTo( UPDATED_FIRSTNAME );
71+
assertThat( user.getLastname() ).isEqualTo( UPDATED_LASTNAME );
72+
assertThat( user.getRoles() ).hasSize( 2 );
73+
return getMutinySessionFactory()
74+
.withTransaction( s -> s.merge( user ) );
75+
}
76+
)
77+
.chain( v -> getMutinySessionFactory()
78+
.withTransaction( s -> s.find( User.class, USER_ID ) )
79+
)
80+
.invoke( user -> {
81+
Role adminRole = new Role( ADMIN_ROLE_ID, "admin" );
82+
Role userRole = new Role( USER_ROLE_ID, "user" );
83+
assertThat( user.getFirstname() ).isEqualTo( UPDATED_FIRSTNAME );
84+
assertThat( user.getLastname() ).isEqualTo( UPDATED_LASTNAME );
85+
assertThat( user.getRoles() ).containsEntry(
86+
adminRole.getCode(),
87+
adminRole
88+
);
89+
assertThat( user.getRoles() ).containsEntry(
90+
userRole.getCode(),
91+
userRole
92+
);
93+
}
94+
)
95+
);
96+
}
97+
98+
@Entity(name = "User")
99+
@Table(name = "USER_TABLE")
100+
public static class User {
101+
102+
@Id
103+
private Long id;
104+
105+
private String firstname;
106+
107+
private String lastname;
108+
109+
@OneToMany(fetch = FetchType.EAGER)
110+
private Map<String, Role> roles = new HashMap();
111+
112+
public User() {
113+
}
114+
115+
public User(Long id, String firstname, String lastname, Role... roles) {
116+
this.id = id;
117+
this.firstname = firstname;
118+
this.lastname = lastname;
119+
for ( Role role : roles ) {
120+
this.roles.put( role.getCode(), role );
121+
}
122+
}
123+
124+
public Long getId() {
125+
return id;
126+
}
127+
128+
public String getFirstname() {
129+
return firstname;
130+
}
131+
132+
public void setFirstname(String firstname) {
133+
this.firstname = firstname;
134+
}
135+
136+
public String getLastname() {
137+
return lastname;
138+
}
139+
140+
public void setLastname(String lastname) {
141+
this.lastname = lastname;
142+
}
143+
144+
public Map<String, Role> getRoles() {
145+
return roles;
146+
}
147+
148+
public void addAll(List<Role> roles) {
149+
this.roles.clear();
150+
for ( Role role : roles ) {
151+
this.roles.put( role.getCode(), role );
152+
}
153+
}
154+
}
155+
156+
@Entity(name = "Role")
157+
@Table(name = "ROLE_TABLE")
158+
public static class Role {
159+
160+
@Id
161+
private Long id;
162+
private String code;
163+
164+
public Role() {
165+
}
166+
167+
public Role(Long id, String code) {
168+
this.id = id;
169+
this.code = code;
170+
}
171+
172+
public Object getId() {
173+
return id;
174+
}
175+
176+
public String getCode() {
177+
return code;
178+
}
179+
180+
@Override
181+
public boolean equals(Object o) {
182+
if ( o == null || getClass() != o.getClass() ) {
183+
return false;
184+
}
185+
Role role = (Role) o;
186+
return Objects.equals( id, role.id ) && Objects.equals( code, role.code );
187+
}
188+
189+
@Override
190+
public int hashCode() {
191+
return Objects.hash( id, code );
192+
}
193+
194+
@Override
195+
public String toString() {
196+
return "Role{" + code + '}';
197+
}
198+
}
199+
}

0 commit comments

Comments
 (0)