[英]Hibernate ManyToMany and Transactional annotation
I try to test my @Repository layer using jUnit and integration testing. 我尝试使用jUnit和集成测试来测试我的@Repository层。 In my entity classes I use @ManyToMany bidirectional annotation. 在我的实体类中,我使用@ManyToMany双向注释。 My test class I have annotated with @Transactional. 我用@Transactional注释了我的测试课。 When I executing persist method on the parent side of relationship the User object and Role are inserted to databse but there is no relations in join table. 当我在关系的父级上执行persist方法时,会将用户对象和角色插入到数据库中,但联接表中没有关系。 When I move @Transactional annotation to @Repository class everything works ok. 当我将@Transactional注释移到@Repository类时,一切正常。 Maybe someone can exaplain me what is the reason why it is no working when @Transactional annotation is on test class? 也许有人可以替我解释@Transactional注释在测试类上不起作用的原因是什么?
User entity: 用户实体:
@Table(name = "users")
@Entity
public class User extends BaseEntity {
...
@ManyToMany(fetch = FetchType.EAGER,cascade = CascadeType.ALL)
@JoinTable(
name = "users_roles",
joinColumns = { @JoinColumn(name = "user_id") },
inverseJoinColumns = { @JoinColumn(name = "role_id") }
)
private Set<Role> roles;
.. getters and setters
public void addRole(Role role) {
this.getRoles().add(role);
role.getUsers().add(this);
}
public Set<Role> getRoles() {
if (this.roles == null) {
this.roles = new HashSet<>();
}
return this.roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
Role entity 角色实体
@Table(name = "roles")
@Entity
public class Role extends BaseEntity {
public enum UserRole {
ADMIN, USER
}
@Enumerated(EnumType.STRING)
@Column(name="role")
private UserRole role;
@ManyToMany(mappedBy = "roles", fetch = FetchType.EAGER,cascade = CascadeType.ALL)
private Set<User> users;
... getters and setters
}
Test class: 测试类别:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {MysqlPersistanceConfig.class})
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Transactional
public class UserRepositoryIT {
@Autowired
private UserRepository userRepository;
@Test
public void stage10_saveOneUserAndCheckIfWasSavedTest() {
User user = new User();
user.setName("admin");
user.setPassword("root");
Role role1 = new Role(UserRole.USER);
Role role2 = new Role(UserRole.ADMIN);
user.addRole(role1);
user.addRole(role2);
Assert.assertTrue(role1.getUsers().size() == 1);
Assert.assertTrue(role2.getUsers().size() == 1);
Assert.assertTrue(user.getRoles().size() == 2);
userRepository.save(user);
Assert.assertEquals(user, userRepository.find(1));
Assert.assertEquals(user, userRepository.findByName("admin"));
Assert.assertEquals(2, userRepository.findByName("admin").getRoles().size());
}
}
DAO layer: DAO层:
@Repository
//@Transactional
public class UserRepositoryImpl implements UserRepository {
@PersistenceContext
private EntityManager manager;
@Override
public void save(User user) {
if(user.isNew()) {
manager.persist(user);
} else {
manager.merge(user);
}
}
@Override
public User find(int id) {
return manager.find(User.class, id);
}
@Override
public User findByName(String name) {
String queryString = "SELECT u FROM User u WHERE u.name = :name";
Query query = manager.createQuery(queryString);
query.setParameter("name", name);
return (User) query.getSingleResult();
}
}
Spring's JUnit is rolling back the transaction spanning the test method by default. Spring的JUnit默认情况下回滚跨越测试方法的事务。 If you want to check it use EntityManager manager
in the test and call manager.flush()
or add @Rollback(false)
to test method. 如果要检查它,请在测试中使用EntityManager manager
,然后调用manager.flush()
或将@Rollback(false)
添加到测试方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.