首页 > 解决方案 > GORM 实例对象线程安全

问题描述

假设我有以下域类。具有多对一关系的 anEmployee和 aCompany

class Employee {

    String id
    String firstName
    String lastName
    String email
    Company company

    static mapping = {
        table name: "employee"
        id column: "employee_id", generator:"assigned"

        version false
    }
}

class Company {
    String id
    String name

    static hasMany = [employees:Employee]

    static mapping = {
        table name: "company"
        id column: "company_id", generator:"assigned"

        autoImport false
        version false
    }
}

我想做的是Company从数据库中获取一个对象,然后产生多个线程来Employees为公司创建。但是,我不确定该Company对象是否是线程安全的。

例如:

public void createEmployees(companyId, employees){

    // Find the new created company - this is on the main thread
    Company company = Company.findById(companyId) // Is company thread safe?
    def lines = parseEmployees(employeeFile) // parses info about each employee that will later be used to create employee objects
    ExecutorService executor = Executors.newFixedThreadPool(10)

    List futures = new ArrayList()

    lines.each { line ->

        Future future = executor.submit(new Callable() {
            public def call() throws Exception {
                def employee = saveEmployee(line, company) // Is the company object thread safe here?
                return employee
            }
        });
        futures.add(future)
    }

    executor.shutdown()

    for(Future future : futures){
        def employee = future.get()
        println employee
    }
}

public Employee saveEmployee(line, company) {

    Employee employee = new Employee()

    employee.firstName = line.firstName
    employee.lastName = line.lastName
    employee.email = employee.email
    employee.id = line.id
    employee.company = company // thread safe?

    employee.save()
}

同样,我不确定Company传递给该saveEmployee方法的 Hibernate 托管对象是否是线程安全的。我的理解是,每个ThreadExecutor都有自己的 Hibernate Session,它不是线程安全的。我想我可能需要调用mergeattachCompany对象上,但似乎我不需要。一切似乎都很好,但在多线程方面可能很难说。

标签: multithreadinghibernategrailsgroovygrails-orm

解决方案


在您提供的示例中,Company传递的对象没有被修改,因此它是否是线程安全的并不重要。(但不是;如果您在多个线程中对其进行更改,您将获得 StaleObjectStateExceptions。)

您的Company hasMany员工,在您当前的映射中,引用实际上存储在Employee(可能是 company_id 字段)中。由于在将对象与员工关联时,您并没有在技术上修改Company对象,因此这不会导致问题。

有很多方法可以确认这一点(因为很难测试所有奇怪的线程边缘情况!)但在我看来,最简单的方法可能是确认添加新员工时对象上的version字段Company不会增加。如果这没有增加,您可以确信它没有被修改,因此线程在这里不会发挥作用。


推荐阅读