为什么Hibernate与H2不能保持双向关系?

时间:2017-06-23 12:29:53

标签: java mysql hibernate h2 liquibase

问题

为什么Hibernate与H2的行为与使用MySQL的Hibernate不同?

我们使用 Hibernate 作为ORM。在我们的实时系统中,我们使用 MySQL 数据库和 LiquiBase 来维护数据库模式。 在我们的测试系统中,我们直接使用内存 H2数据库(不需要Liquibase)。

在我们的实时系统中,当我们更新关系的一侧(通常是包含外键的那一方)时,实体之间的双向关系会被hibernate自动更新。 在我们的测试环境中,这种魔力已经消失,我们不得不明确双方更新关系。

我们不明白,为什么我们的测试环境表现得如此不同。它只是MySQL + Liquibase与H2之间的区别吗?

我知道,most documentation for hibernate / JPA表示对象之间的关系仍然需要手动维护,即使在使用休眠时也是如此。 但由于它在我们的实时系统中有效,我们希望为我们的测试复制相同的行为。

我们已经尝试添加更多注释,以便为H2 DB提供有关架构及其依赖关系的更多信息,但这并没有帮助。

那么,我们有什么办法可以在H2中强制进行这些自动更新吗?

守则

我们拥有可以拥有CompanyPositions的用户。此关系建模为单独的类:UserCompanyPosition。

以下是我尝试删除相关部分的一些代码。首先是两个实体和关系类。然后是一种更新关系和小测试方法的方法。

请告诉我哪些其他信息有助于回答这个问题。

User.java:

@Entity
@Cacheable
@org.hibernate.annotations.Cache(
    usage = CacheConcurrencyStrategy.READ_WRITE, region = "our_region")
@Table(name = "users")
public class User extends Model {

  @Id
  @Column(name = "id")
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @OneToMany(mappedBy = "user")  // the relevant field
  private List<UserCompanyPosition> userCompanyPositions = new ArrayList<>();

  // ... default getters & setters, simple constructor
}

CompanyPosition.java:

@Entity
@Cacheable
@org.hibernate.annotations.Cache(
    usage = CacheConcurrencyStrategy.READ_WRITE, region = "our_region")
@Table(name = "company_positions")
public class CompanyPosition extends Model {

  @Id
  @Column(name = "id")
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @OneToMany(mappedBy = "companyPosition") // relevant field
  private List<UserCompanyPosition> userCompanyPositions = new ArrayList<>();

  // ... default getters & setters, simple constructor
}

UserCompanyPosition.java:

@Entity
@Cacheable
@org.hibernate.annotations.Cache(
    usage = CacheConcurrencyStrategy.READ_WRITE, region = "our_region")
@Table(
    name = "users_company_positions",
    uniqueConstraints = {
@UniqueConstraint(columnNames = {"company_position_id", "user_id"})})
public class UserCompanyPosition extends Model {

  @Id
  @Column(name = "id")
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "company_position_id", nullable = false)
  private CompanyPosition companyPosition;

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "user_id", nullable = false)
  private User user;

  public UserCompanyPosition(User user, CompanyPosition companyPosition) {
    this.user = user;
    this.companyPosition = companyPosition;
  }

//... default getters & setters
}

UserCompanyPositionController.java中的创建方法:

protected Model createUserCompanyPosition(User user, CompanyPosition companyPosition) {
    UserCompanyPosition userCompanyPosition = new UserCompanyPosition(user, companyPosition);

    hibernateSession.saveOrUpdate(userCompanyPosition);
    userCompanyPosition.notifyClientAboutChange(hibernateSession);

    // These both lines are not necessary in the live system. 
    // But without them, the test below fails:
    user.getUserCompanyPositions().add(userCompanyPosition); 
    companyPosition.getUserCompanyPositions().add(userCompanyPosition);

    return userCompanyPosition;
}

测试:

public void testCreateObject() throws Exception {

    controller.createUserCompanyPosition(existingUser, existingCompanyPosition);

    assertEquals(companyPosition.getUserCompanyPositions().get(0),
        user.getUserCompanyPositions().get(0));
        // the queried collection user.getCompanyPositions() is empty, 
        // when we don't explicitly add the references
}

1 个答案:

答案 0 :(得分:0)

也许尝试在应用程序属性中设置此属性以进行测试evnironment。

spring.jpa.hibernate.ddl-自动=创建降

相关问题