【问题标题】:JPA @ElementCollection @Enumerated not insertingJPA @ElementCollection @Enumerated 不插入
【发布时间】:2012-04-19 12:09:56
【问题描述】:

我正在尝试实现基本用户/角色

一个用户可以有零到多个角色。

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(ROLE、USER_ID)和对用户的 FK。

我可以在控制台中看到,用户只完成了一次插入

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

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

【问题讨论】:

  • 您是否使用@RunWith(SpringJUnit4ClassRunner.class) 运行测试?
  • @axtavt 是的,我愿意。以上更新

标签: java hibernate jpa


【解决方案1】:

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

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

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

【讨论】:

  • 非常感谢,我以为我要疯了。我想这表明了做这种 TDD 的一个小缺点(我松散地使用这个术语),因为测试不是“准确的”,即,我不希望事后的测试持续存在。至少我知道这是什么/为什么会发生
  • 显式调用flush是不够的,必须设置事务配置才能真正提交数据。否则,事务将被回滚,flush 不会持久化任何东西。
猜你喜欢
  • 2013-01-21
  • 2011-06-25
  • 2020-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-10
  • 2015-06-16
相关资源
最近更新 更多