Hibernate ManyToMany和Transactional注释

时间:2018-03-13 20:40:51

标签: java spring hibernate many-to-many transactional

我尝试使用jUnit和集成测试来测试我的@Repository层。在我的实体类中,我使用@ManyToMany双向注释。我的测试类我用@Transactional注释。当我在关系的父端执行persist方法时,User对象和Role被插入数据库但是在连接表中没有关系。当我将@Transactional注释移动到@Repository类时,一切正常。也许有人可以告诉我,当@Transactional注释在测试类上时,为什么它不起作用的原因是什么?

用户实体:

@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;
    }
}

角色实体

@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
}

测试类:

@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层:

@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();
    }
}

1 个答案:

答案 0 :(得分:0)

Spring的JUnit默认回滚跨越测试方法的事务。如果要检查它,请在测试中使用EntityManager manager并致电manager.flush()或将@Rollback(false)添加到测试方法。