Проблема была решена
Причина в том, что я работаю в тестовой среде и транзакции автоматически откатываются по умолчанию
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {UaaApplication.class})
@Transactional
@Rollback(false) // Turn off automatic rollback
Вот оригинальный вопрос
Моя среда
- Spring Boot
- Spring-Data-Jpa
- Mysql
При сохранении , он добавил данные в таблицу user_roles, что дало ожидаемый эффект.
Hibernate: insert into user_roles (user_id, role_name) values (?, ?)
Однако, когда я попытался добавить новую роль для пользователя, он не добавил данные в таблица user_roles.
Или JPA не может этого сделать? Итак, как я могу достичь своих ожиданий? Спасибо за любые предложения
Пользователь. java
@Entity
@Table(name = "user")
public class User extends AbstractAuditingEntity {
private static final long serialVersionUID = -7682612894107800662L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 50, unique = true, nullable = false)
private String login;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(
name = "user_roles",
joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "role_name", referencedColumnName = "name")})
private Set<Role> roles = new HashSet<>();
public User addRole(Role role) {
this.roles.add(role);
return this;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return login != null ? login.equals(user.login) : user.login == null;
}
@Override
public int hashCode() {
return login != null ? login.hashCode() : 0;
}
}
Роль. java
@Entity
@Table(name = "role")
public class Role extends AbstractAuditingEntity {
private static final long serialVersionUID = -1702863587500414292L;
@Id
@Column(name = "name", unique = true, nullable = false)
private String name;
@Column(name = "description")
private String description;
@ManyToMany
@JoinTable(
name = "user_role",
joinColumns = {@JoinColumn(name = "role_name", referencedColumnName = "name")},
inverseJoinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")})
private Set<User> users = new HashSet<>();
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Role role = (Role) o;
return name != null ? name.equals(role.name) : role.name == null;
}
@Override
public int hashCode() {
return name != null ? name.hashCode() : 0;
}
}
Посмотрите на последнюю строку журнала, он вставляет данные в среднюю таблицу
Hibernate: insert into user_roles (user_id, role_name) values (?, ?)
Set<Role> authorities = new HashSet<>();
authorityRepository.findById(AuthoritiesConstants.USER).ifPresent(authorities::add);
newUser.setRoles(authorities);
userRepository.save(newUser);
log
Hibernate: select user0_.id as id1_7_, user0_.created_by as created_2_7_, user0_.created_date as created_3_7_, user0_.feature as feature4_7_, user0_.last_modified_by as last_mod5_7_, user0_.last_modified_date as last_mod6_7_, user0_.activated as activate7_7_, user0_.activation_key as activati8_7_, user0_.email as email9_7_, user0_.image_url as image_u10_7_, user0_.lang_key as lang_ke11_7_, user0_.login as login12_7_, user0_.nick_name as nick_na13_7_, user0_.password_hash as passwor14_7_, user0_.reset_date as reset_d15_7_, user0_.reset_key as reset_k16_7_ from user user0_ where user0_.login=?
Hibernate: insert into user (created_by, created_date, feature, last_modified_by, last_modified_date, activated, activation_key, email, image_url, lang_key, login, nick_name, password_hash, reset_date, reset_key) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: select users0_.role_name as role_nam1_8_1_, users0_.user_id as user_id2_8_1_, user1_.id as id1_7_0_, user1_.created_by as created_2_7_0_, user1_.created_date as created_3_7_0_, user1_.feature as feature4_7_0_, user1_.last_modified_by as last_mod5_7_0_, user1_.last_modified_date as last_mod6_7_0_, user1_.activated as activate7_7_0_, user1_.activation_key as activati8_7_0_, user1_.email as email9_7_0_, user1_.image_url as image_u10_7_0_, user1_.lang_key as lang_ke11_7_0_, user1_.login as login12_7_0_, user1_.nick_name as nick_na13_7_0_, user1_.password_hash as passwor14_7_0_, user1_.reset_date as reset_d15_7_0_, user1_.reset_key as reset_k16_7_0_ from user_role users0_ inner join user user1_ on users0_.user_id=user1_.id where users0_.role_name=?
2020-01-09 10:13:07.007 DEBUG 5452 --- [ main] m.t.s.c.u.service.impl.UserServiceImpl : Created Information for User: User(id=34, login=user1, password=$2a$10$JTRiBg6Rjblad6hNCUOvBOPbC7zWGHC7/n0uy/Cf7esMWAumvKb56, nickName=user1, email=null, activated=false, langKey=zh, imageUrl=null, activationKey=71667657839259250002, resetKey=null, resetDate=null, roles=[Role(name=ROLE_USER, description=null, users=[], permissions=[])], organizations=[])
Hibernate: insert into user_roles (user_id, role_name) values (?, ?)
Но когда я попытался добавить новую роль пользователю, он не достиг ожидаемого эффекта.
userRepository.findAll().stream().findAny().ifPresent(user -> {
roleRepository.findByName(AuthoritiesConstants.ADMIN).ifPresent(user::addRole);
userRepository.save(user);
});
log
Hibernate: select user0_.id as id1_7_, user0_.created_by as created_2_7_, user0_.created_date as created_3_7_, user0_.feature as feature4_7_, user0_.last_modified_by as last_mod5_7_, user0_.last_modified_date as last_mod6_7_, user0_.activated as activate7_7_, user0_.activation_key as activati8_7_, user0_.email as email9_7_, user0_.image_url as image_u10_7_, user0_.lang_key as lang_ke11_7_, user0_.login as login12_7_, user0_.nick_name as nick_na13_7_, user0_.password_hash as passwor14_7_, user0_.reset_date as reset_d15_7_, user0_.reset_key as reset_k16_7_ from user user0_
Hibernate: select role0_.name as name1_5_, role0_.created_by as created_2_5_, role0_.created_date as created_3_5_, role0_.feature as feature4_5_, role0_.last_modified_by as last_mod5_5_, role0_.last_modified_date as last_mod6_5_, role0_.description as descript7_5_ from role role0_ where role0_.name=?
2020-01-09 10:18:07.376 INFO 15044 --- [ main] o.s.t.c.transaction.TransactionContext : Rolled back transaction for test: [DefaultTestContext@692f203f testClass = UserTests, testInstance = me.talei.spring.cloud.uaa.domain.UserTests@3431cb1f, testMethod = associate@UserTests, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@48f2bd5b testClass = UserTests, locations = '{}', classes = '{class me.talei.spring.cloud.uaa.UaaApplication, class me.talei.spring.cloud.uaa.UaaApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@319b92f3, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@5c18298f, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@71623278, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@17baae6e], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true]]