GORM实例对象线程安全

时间:2018-10-08 15:11:44

标签: multithreading hibernate grails groovy gorm

说我有以下域类。具有多对一关系的EmployeeCompany

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方法的Hibernate托管saveEmployee对象是否是线程安全的。我的理解是Thread中的每个Executor都有其自己的休眠会话,该会话不是线程安全的。我以为我可能需要在merge对象上调用attachCompany,但是似乎不需要。一切似乎都可以正常工作,但是很难分辨何时涉及多线程。

1 个答案:

答案 0 :(得分:1)

在您提供的示例中,传递的Company对象没有被修改,因此它是否是线程安全的都没有关系。 (不是这样;如果您在多个线程中对其进行更改,则会得到StaleObjectStateExceptions。)

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

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