Spark323
Spark323

Reputation: 1585

GORM Instance Object Thread Safety

Say I have the following domain classes. An Employee and a Company with a many to one relationship

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
    }
}

What I want to do, is grab a Company object from the database, and then spawn off multiple threads to create Employees for the Company. However, I'm unsure if the Company object will be thread safe.

For instance:

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()
}

Again, I'm not sure if the Hibernate managed Company object passed to the saveEmployee method is thread safe or not. My understanding is that each Thread in the Executor will have its own Hibernate Session which is not thread safe. I thought I might need to call merge or attach on the Company object, but it appears that I don't. Everything seems to work fine, but it can be hard to tell when it comes to multi threading.

Upvotes: 2

Views: 795

Answers (1)

Daniel
Daniel

Reputation: 3370

In your provided example, the Company object passed is not modified, so it doesn't matter if it's thread-safe or not. (It's not though; if you make changes to it in multiple threads you're going to get StaleObjectStateExceptions.)

Your Company hasMany employees, and in your current mapping the reference is actually stored in Employee (probably a company_id field). Since you are not technically modifying the Company object when you are associating it with an employee, this will not cause problems.

There are a lot of ways to confirm this (since it is really hard to test all weird threading edge cases!) but in my opinion the easiest is probably by confirming that the version field on your Company object does not increase when you add new employees. If that is not increasing, you can be confident that it is not being modified, and so threading does not come into play here.

Upvotes: 1

Related Questions