【问题标题】:how to reload an instance of a domain class from a database grails?如何从数据库 grails 重新加载域类的实例?
【发布时间】:2014-03-31 04:33:10
【问题描述】:

我有 4 个对象(域类的实例)称为出租车,放置在属性allocatedTaxi 下的一个名为moveRequest 的对象中。

类如下所示:

class MoveRequest{

Taxi allocatedTaxi
Zone destinationZone
Integer destination
String microDestination
String targetType = ""
String targetName = ""
Zone currentTaxiZone
Taxi obstructingTaxi
Taxi boardedTaxi

String state = "pending"
Boolean requestedSpecific
Date dateCreated

static constraints = {
    currentTaxiZone(nullable: true)
    obstructingTaxi(nullable: true)
    boardedTaxi(nullable: true)
}

static mapping = {
    version false
}

}

class Taxi {

String name
Integer position
Double voltage
Boolean busy
Integer orderNumber

static belongsTo = [rail: Rail]

static mapping = {
    version false
}

static constraints = {
    name blank: false
}

}

现在,在迭代 moveRequests 时,我使用如下函数中的 sql 语句更新出租车对象的位置属性:

def updateTaxiPosition(def taxiName, def millimeters){
    def config = grailsApplication.config
    def sql = Sql.newInstance(config.grails.databaseURL, config.grails.databaseUsername, config.grails.databasePassword, config.grails.databaseDriverClassName)

    sql.getConnection().setAutoCommit(true)
    sql.execute("UPDATE taxi SET position= ? WHERE name = ?", [millimeters, taxiName])
    sql.close()
}

现在,另一种方法是使用这行代码:

moveRequest.allocatedTaxi.position = millimeters

但是,由于我需要使用直接 sql 快速更新它,因为它会自动更新出租车位置。现在,当我尝试访问更改的位置时,问题就出现了。我只能访问旧位置,即使数据库中的位置已更改,当我尝试这样做时:

println("taxi position: " + moveRequest.allocatedTaxi.position)

我在更新位置属性之前获取旧值。现在我尝试像这样刷新 moveRequest 实例:

def refreshMoveRequestInformation(def moveRequest){
    def config = grailsApplication.config
    def sql = Sql.newInstance(config.grails.databaseURL, config.grails.databaseUsername, config.grails.databasePassword, config.grails.databaseDriverClassName)

    sql.getConnection().setAutoCommit(true)
    def row = sql.rows("SELECT * FROM taxi WHERE id=?", [moveRequest.allocatedTaxi.id])
    println("row -> taxi name: " + row.name + ", taxi position: " + row.position)
    sql.close()

    def newPosition = null
    row.each{
        newPosition = it.position
    }
    moveRequest.allocatedTaxi.position = newPosition
}

还有这样的:

def refreshMoveRequestInformation(def moveRequest){
    def taxi = Taxi.get(moveRequest.allocatedTaxi.id)
    println("1 - new taxi name: " + taxi.name + ", taxi position: " + taxi.position)
    taxi.refresh()
    println("2 - new taxi name: " + taxi.name + ", taxi position: " + taxi.position)

    println("move request -> taxi name: " + moveRequest.allocatedTaxi.name + ", taxi position: " + moveRequest.allocatedTaxi.position)

    return moveRequest
}

但似乎都不起作用。即使行实例显示新值,我也会不断获得旧值。如何更新 moveRequest 实例(我的意思是从数据库重新加载)它的分配出租车属性(或更准确地说,位置属性)??

【问题讨论】:

    标签: sql grails refresh reload


    【解决方案1】:

    你可以做两件事。

    首先,在您的域实例上调用 .refresh() 将确保它从 SOR(记录系统)加载,在这种情况下是您的数据库。

    其次,您可能希望从 Hibernates 二级 cache 中删除此域类。

    class SomeClass {
      static mapping = {
        cache false
      }
    }
    

    【讨论】:

    • 但问题是我认为 refresh() 不起作用,因为在出​​租车实例上调用它时,它只是在执行更新之前返回相同的值。我不明白为什么,就像它在输入事务时记住它的值,然后无论数据库中发生什么都简单地使用相同的值。
    • 尝试从 Hibernates 缓存中删除它。如果您处于隔离更新的事务中,则完全有可能。交易范围是什么?
    • 所以我应该尝试将缓存 false 添加到出租车类?我不确定这会有什么帮助,你介意解释一下吗?我相信事务的范围将针对管理 moveRequests 的整个函数,因为所有函数都放置在服务中,因此在数据库中可以看到使用另一行 (moveRequest.allocatedTaxi.position = mm) 所做的更改只有在使用该行更新了所有 4 个实例之后,才能完成对 4 个 moveRequests 的迭代。对不起,如果我比我应该的更复杂xD
    • 发生了两件事。将缓存设置为 false 将确保 Hibernate 不会尝试缓存实例。其次,Grails 服务的事务隔离级别可能会影响您的情况。你用的是什么数据库?我/您需要研究默认情况下该数据库的隔离级别是什么。由于事务仍处于活动状态(例如未提交)并且隔离级别不允许脏读,因此可能看不到您的更新。
    • 不应该解决未提交的问题吗? sql.getConnection().setAutoCommit(true)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-16
    • 1970-01-01
    相关资源
    最近更新 更多