【问题标题】:Grails: getting old instance after persistingGrails:持久化后获取旧实例
【发布时间】:2016-11-15 06:19:11
【问题描述】:

我在 Grails 中遇到了一个奇怪的问题。当我在更改和保存域的值后进行findBy 调用时,即使这些值被持久化到数据库中,我仍然会得到旧值。我可以看到我的表中的值发生了变化。

我的代码是这样的:

Car car = Car.findByCarId(carId)
car.modelName = "some_model_name"
car.save() // Not flushing here
Tire tire = Tire.findByIdAndCarId(tireId,carId)
tire.manufacturer = "some_manufacturer"
tire.save()
Light light = Light.findByIdAndCarId(lightId,carId)
light.manufacturer = "some_manufacturer"
light.save()
Mirror mirror = Mirror.findByIdAndCarId(mirrorId,carId)
mirror.manufacturer = "some_manufacturer"
mirror.save() 

我的域也有一些一对多的关联。让我们这样说:

class Car {
    String modelName
    static hasMany = [tires : Tire, mirrors : Mirror, lights : Light]
}

在这些更改之后,当我对Car 域进行数据库调用时,我仍然会得到旧值:

Car car = Car.findById(carId) 
println car.modelName // This gives older value

我知道这是因为这些值尚未持久化到数据库中。我想知道如果我在上面的代码中使用car.save(flush: true),会不会导致collection was not processed by flush() 错误?但是,即使在将值保存到数据库之后,我也会获得较旧的值。 (例如,当我在很长一段时间后进行上述查询时)我可以看到我的表中的值发生了变化,但是当我进行上述查询时,它给了我旧值。 Hibernate 会自动缓存这个查询吗?我经常使用上述查询。

当我使用withNewSession 时,它会检索新值:

Car car
Car.withNewSession {
    car = Car.findById(carId,[readOnly : true])
}
println car.modelName // Gives new value

我想知道这是如何每次都给出新值的,因为我没有刷新当前会话。相反,我只使用了一个新的 Hibernate 会话。 readOnly 命令是否刷新当前会话?上面的代码对我来说很好。保存时是否应该使用withNewSession 而不是刷新?

谢谢。

【问题讨论】:

  • 您在哪里更改这些对象?控制器 ?服务 ?它是事务性服务吗?
  • 我正在控制器中更改它
  • 你必须把你所有的员工都放到一个服务层中,因为所有的服务都是事务性的,如果你不这样做,你就在以一种糟糕的方式使用 grails
  • 我大部分都是在服务内部完成的。这是我不想为创建新服务的小事

标签: java hibernate session grails


【解决方案1】:

您的所有业务逻辑都必须在事务服务中。默认情况下,grails 中的所有服务都是事务性的。注意@Transactional@NotTransactional 的符号

如果您想在控制器中管理数据(不推荐),您应该将您的代码包含在一个事务中。允许休眠管理事务,而不是通过刷新来破坏它。

在事务完成后提交所有更改。

请记住,您还可以使用 refresh 方法从底层数据库中重新读取给定实例的状态。

domainInstance.refresh()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-13
    • 1970-01-01
    • 1970-01-01
    • 2021-02-10
    • 1970-01-01
    • 2011-06-07
    • 2015-12-18
    相关资源
    最近更新 更多