2012-04-19 45 views
1

我想实现基本的用户/角色JPA @ElementCollection @Enumerated不插入

用户可以有0到多个角色。

public enum Role { 
    ROLE_USER, 
    ROLE_ADMIN; 
} 

@Entity 
@Table(name = "USERS") 
public class User implements Serializable { 

    private static final long serialVersionUID = 2936736450886451500L; 
    private Long id; 
    private Individual individual; 
    private Set<Role> roles = new HashSet<Role>(); 

    @Id 
    @Column(name = "ID") 
    @GeneratedValue 
    public Long getId() { 
    return id; 
    } 

    @SuppressWarnings("unused") 
    private void setId(Long id) { 
    this.id = id; 
    } 

    @ElementCollection(targetClass=Role.class) 
    @JoinTable(name = "USER_ROLES", joinColumns = @JoinColumn(name = "USER_ID")) 
    @Enumerated(EnumType.STRING) 
    @Column(name = "role", nullable = false) 
    public Set<Role> getRoles() { 
    return roles; 
    } 

    public void setRoles(Set<Role> roles) { 
    this.roles = roles; 
    } 

    public void addRole(Role role) { 
    roles.add(role); 
    } 

} 

我的单元测试

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration({"classpath:/META-INF/spring/resources/resource-context.xml", "classpath:/META-INF/spring/services/persistence-context.xml"}) 
public class UserDaoJpaImplTest { 

@Autowired 
UserDao userDao; 

@Transactional 
@Test 
public void testCreate() { 
    User user = new User(); 
    user.setIndividual(new Individual()); 
    user.addRole(Role.ROLE_USER); 
    user.addRole(Role.ROLE_ADMIN); 
    userDao.create(user); 

    Assert.assertNotSame(user.getId(), 0); 
} 

的问题是,JPA(由Hibernate支持),是不是做对USER_ROLES表插入(它是正确创建它,用正确的复合PK (角色,USER_ID)和FK用户。

我可以在控制台中看到,只有单个插入正在做,用户

Hibernate: insert into USERS (INDIVIDUAL_ID) values (?) 
Hibernate: insert into INDIVIDUALS values () 

我假设我只是缺少一些简单的东西。

+0

你用'@RunWith(SpringJUnit4ClassRunner.class)'运行测试吗? – axtavt 2012-04-19 12:33:14

+0

@axtavt是的,我喜欢。更新超过 – kabal 2012-04-19 12:42:35

回答

3

集合的元素在持久化上下文刷新期间插入到数据库中。默认SpringJUnit4ClassRunner@Transactional测试后触发回滚,因此事务提交时自动刷新不会发生。

您需要用@Rollback(false)@TransactionConfiguraton(defaultRollback = false)覆盖此行为,或者仅使用flush()方法触发显式刷新。

此外,如果您需要覆盖收集表的默认属性,则应使用@CollectionTable而不是@JoinTable

+0

非常感谢,我以为我疯了。我认为这在做这种TDD(我使用这个术语松散地)方面略有缺点,因为测试不是“准确的”,也就是说,我不想在事后继续测试。至少我知道发生了什么/为什么发生 – kabal 2012-04-19 12:58:01

+1

明确调用flush是不够的,你必须设置事务配置来实际提交数据。否则,事务将回滚并且flush不会持久化任何事情。 – Leonel 2012-06-14 19:45:19