【问题标题】:Hibernate collection caching problemsHibernate 集合缓存问题
【发布时间】:2011-06-23 09:54:33
【问题描述】:

我有以下 2 个 Hibernate 实体:

@Entity
@Table(name = "VEHICLE_BRAND")
public class VehicleBrand implements java.io.Serializable {

  ...

  @Column(name = "NAME", nullable = false, length = 1000)
  public String getName() {
    return name;
  }

  @OneToMany(fetch = FetchType.LAZY, mappedBy = "vehiclebrand")
  public Set<VehicleModel> getVehicleModels() {
    return vehicleModels;
  }

  ...

}

@Entity
@Table(name = "VEHICLE_MODEL")
public class VehicleModel implements java.io.Serializable {

  ...

  @Column(name = "NAME", nullable = false, length = 1000)
  public String getName() {
    return name;
  }

  @ManyToOne(fetch=FetchType.LAZY)
  @JoinColumn(name="VECHILE_BRAND_ID")
  public VehicleBrand getVehicleBrand() {
    return this.vehicleBrand;
  }

  ...

}

我有以下测试 VehicleBrand 和 VehicleModel 的单元测试:

DefaultTransactionDefinition txDef = new DefaultTransactionDefinition();
txDef.setName("test1");
txDef.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus txStatus = txManager.getTransaction(txDef);

// Load brand "1" object.
VehicleBrand brand = (VehicleBrand) factory.getVehicleBrandDAO().findFirstByName("1");
assertNotNull(brand);

// Check if model "X" exists for brand "1" through collection.
Set<VehicleModel> models = brand.getVehicleModels();
for (final VehicleModel model : models) {
  assertFalse(model.getName().equals("X"));
}

// Add model "X" to brand "1".
VehicleModel model = new VehicleModel();
model.setName("X");
model.setValidFrom(new Date());
model.setVehicleBrand(brand);
factory.getVehicleModelDAO().create(model);

txManager.commit(txStatus);

txDef = new DefaultTransactionDefinition();
txDef.setName("test2");
txDef.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
txStatus = txManager.getTransaction(txDef);

// Check that model is added to database.
model = (VehicleModel) factory.getVehicleModelDAO().findFirstByName("X");
assertNotNull(model);
assertEquals(model.getVehicleBrandId().longValue(), 1L);

// Check if model X exists for brand "1" through collection.
brand = (VehicleBrand) factory.getVehicleBrandDAO().findFirstByName("1");
models = brand.getVehicleModels();
boolean found = false;
for (final VehicleModel model2 : models) {
  if (model2.getName().equals("X")) {
    found = true;
  }
}
assertTrue(found);

txManager.commit(txStatus);

谁能解释一下为什么最后一行失败了?

【问题讨论】:

  • 您能否使用getNavn 的sn-ps 或将存储在数据库中的相关成员更新代码?
  • 对不起,这是一个错字,它被称为 getName,我已经为问题中的实体添加了 getter/annotation 定义
  • 我已经更新了测试用例以确保在请求之间启动新事务
  • 这现在变成了一场大乱斗:p 你是否为 VehicleModel 模型类实现了 equals()hashcode() 方法?这也很有用。
  • 是的,实现了equals和hashcode

标签: java hibernate collections


【解决方案1】:

它肯定会失败,因为您在同一个事务中执行所有这些,因此总是从会话缓存中返回同一个 VehicleBrand 实例。

由于您在创建 VehicleModel 时忘记维护关联的双方(即,您将品牌分配给新模型,但忘记将创建的模型添加到品牌的模型集合中),因此同一组模型是总是返回,并且不包含新创建的模型。

【讨论】:

  • 1) 查找请求在不同的休眠会话中执行,2) 我还可以从日志中看到,在每个 findFirstByName 上都有一个针对数据库执行的 SQL 查询
  • 你有没有检查过模型确实在你第一次交易结束时写入数据库,并且它的名字和品牌ID是正确的(既然交易已经提交,你应该可以看到它在数据库中)?
猜你喜欢
  • 2011-07-22
  • 2017-05-12
  • 2017-05-11
  • 2011-02-11
  • 1970-01-01
  • 1970-01-01
  • 2011-01-27
  • 2018-05-21
  • 2014-10-18
相关资源
最近更新 更多