GORM Instance Object Thread Safety - PullRequest
       43

GORM Instance Object Thread Safety

0 голосов
/ 08 октября 2018

Скажем, у меня есть следующие классы домена.Employee и Company с отношением "многие к одному"

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

Опять же, я не уверен, что управляемый Hibernate объект Companyпереданный методу saveEmployee является потокобезопасным или нет.Насколько я понимаю, каждый Thread в Executor будет иметь свой собственный сеанс Hibernate, который не является потокобезопасным.Я подумал, что мне может понадобиться вызвать merge или attach для объекта Company, но, похоже, я этого не делаю.Кажется, все работает нормально, но бывает трудно сказать, когда дело доходит до многопоточности.

1 Ответ

0 голосов
/ 08 октября 2018

В предоставленном вами примере переданный объект Company не изменяется, поэтому не имеет значения, является ли он потокобезопасным или нет.(Хотя это не так; если вы внесете изменения в несколько потоков, вы получите StaleObjectStateExceptions.)

Ваши Company hasMany сотрудники, и в вашем текущем отображении ссылка фактически сохраняется в Employee (возможно, поле company_id).Поскольку вы технически не изменяете объект Company, когда связываете его с сотрудником, это не вызовет проблем.

Существует множество способов подтвердить это (поскольку действительно сложно проверить всестранные случаи с многопоточностью!) но, на мой взгляд, проще всего, вероятно, подтвердить, что поле version в вашем объекте Company не увеличивается при добавлении новых сотрудников.Если оно не увеличивается, вы можете быть уверены, что оно не изменяется, и поэтому многопоточность здесь не вступает в игру.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...