Skip to content

Commit 0939a09

Browse files
committed
[hibernate#2006] Add test for UnexpectedAccessToTheDatabase error when merging a detached entity with a ToMany association
1 parent 19d5393 commit 0939a09

File tree

1 file changed

+186
-0
lines changed

1 file changed

+186
-0
lines changed
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
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.ArrayList;
9+
import java.util.Collection;
10+
import java.util.List;
11+
import java.util.Objects;
12+
13+
import org.junit.jupiter.api.BeforeEach;
14+
import org.junit.jupiter.api.Test;
15+
16+
import io.vertx.junit5.Timeout;
17+
import io.vertx.junit5.VertxTestContext;
18+
import jakarta.persistence.Entity;
19+
import jakarta.persistence.FetchType;
20+
import jakarta.persistence.Id;
21+
import jakarta.persistence.OneToMany;
22+
import jakarta.persistence.Table;
23+
24+
import static java.util.concurrent.TimeUnit.MINUTES;
25+
import static org.assertj.core.api.Assertions.assertThat;
26+
import static org.assertj.core.api.Assertions.fail;
27+
28+
@Timeout(value = 2, timeUnit = MINUTES)
29+
public class OneToManyMergeTest 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.getRoles().clear();
64+
user.getRoles().addAll( roles );
65+
user.setFirstname( UPDATED_FIRSTNAME );
66+
user.setLastname( UPDATED_LASTNAME );
67+
return user;
68+
} )
69+
)
70+
.chain( user -> {
71+
assertThat( user.getFirstname() ).isEqualTo( UPDATED_FIRSTNAME );
72+
assertThat( user.getLastname() ).isEqualTo( UPDATED_LASTNAME );
73+
assertThat( user.getRoles() ).hasSize( 2 );
74+
return getMutinySessionFactory()
75+
.withTransaction( s -> s.merge( user ) );
76+
}
77+
)
78+
.onFailure().invoke( throwable -> fail( throwable ) )
79+
.chain( v -> getMutinySessionFactory()
80+
.withTransaction( s -> s.find( User.class, USER_ID ) )
81+
)
82+
.invoke( user -> {
83+
Role adminRole = new Role( ADMIN_ROLE_ID, "admin" );
84+
Role userRole = new Role( USER_ROLE_ID, "user" );
85+
assertThat( user.getFirstname() ).isEqualTo( UPDATED_FIRSTNAME );
86+
assertThat( user.getLastname() ).isEqualTo( UPDATED_LASTNAME );
87+
assertThat( user.getRoles() ).containsExactlyInAnyOrder(
88+
adminRole,
89+
userRole
90+
);
91+
}
92+
)
93+
);
94+
}
95+
96+
@Entity(name = "User")
97+
@Table(name = "USER_TABLE")
98+
public static class User {
99+
100+
@Id
101+
private Long id;
102+
103+
private String firstname;
104+
105+
private String lastname;
106+
107+
@OneToMany(fetch = FetchType.EAGER)
108+
private List<Role> roles = new ArrayList<>();
109+
110+
public User() {
111+
}
112+
113+
public User(Long id, String firstname, String lastname, Role... roles) {
114+
this.id = id;
115+
this.firstname = firstname;
116+
this.lastname = lastname;
117+
for ( Role role : roles ) {
118+
this.roles.add( role );
119+
}
120+
}
121+
122+
public Long getId() {
123+
return id;
124+
}
125+
126+
public String getFirstname() {
127+
return firstname;
128+
}
129+
130+
public void setFirstname(String firstname) {
131+
this.firstname = firstname;
132+
}
133+
134+
public String getLastname() {
135+
return lastname;
136+
}
137+
138+
public void setLastname(String lastname) {
139+
this.lastname = lastname;
140+
}
141+
142+
public List<Role> getRoles() {
143+
return roles;
144+
}
145+
}
146+
147+
@Entity(name = "Role")
148+
@Table(name = "ROLE_TABLE")
149+
public static class Role {
150+
151+
@Id
152+
private Long id;
153+
private String code;
154+
155+
public Role() {
156+
}
157+
158+
public Role(Long id, String code) {
159+
this.id = id;
160+
this.code = code;
161+
}
162+
163+
public Object getId() {
164+
return id;
165+
}
166+
167+
@Override
168+
public boolean equals(Object o) {
169+
if ( o == null || getClass() != o.getClass() ) {
170+
return false;
171+
}
172+
Role role = (Role) o;
173+
return Objects.equals( id, role.id ) && Objects.equals( code, role.code );
174+
}
175+
176+
@Override
177+
public int hashCode() {
178+
return Objects.hash( id, code );
179+
}
180+
181+
@Override
182+
public String toString() {
183+
return "Role{" + code + '}';
184+
}
185+
}
186+
}

0 commit comments

Comments
 (0)