метод сохранения gorm, вызывающий запуск запроса select

#hibernate #grails #grails-orm

#переход в спящий режим #grails #grails-orm

Вопрос:

Я использую grails 1.3.7 и zkoss, и моя модель домена такая, как показано ниже, я загружаю объект Person в сеансе 1 и вношу в него изменения через пользовательский интерфейс.

При нажатии кнопки save в сеансе 2 я хочу сохранить объект.

Итак, из моего композитора / контроллера я вызываю сервисный метод (транзакционный), а затем выполняю person.save(), когда я вижу, что запускаются sql-запросы, я вижу запрос, который пытается извлечь объект employee.

После чего выполняется сохранение и генерируется исключение nonuniqueobjectexception

org.переход в спящий режим.Исключение NonUniqueObjectException: другой объект с тем же значением идентификатора уже был связан с сеансом: [com.nthdimenzion.domain.Employee#2]

Запрос

 Hibernate: select this_.id as id7_0_, this_.version as version7_0_, this_.emp_id as emp4_7_0_, this_.person_id as person5_7_0_ from person_role this_ where this_.class='com.nthdimenzion.domain.Employee' and this_.emp_id=?

class PersonService {
static transactional = true
def savePerson(Person person) {
    person = person.save();
}
  

}

 class Person extends Party{

String firstName;
String middleName;  
static hasMany = [ personRoles : PersonRole ] -- lazy loaded
  

….
}

 class PersonRole {
public static enum ROLETYPES{
    EMPLOYEE,AUTHOR
};
public boolean hasRoleType (ROLETYPES roleType){
    return false;
}
static transients = ['ROLETYPES']
static constraints = {
}
 }



class Employee extends PersonRole{
def empRoleType = [ROLETYPES.EMPLOYEE]
String empId
    static belongsTo = [person:Person]
 static transients = ['empRoleType', 'uid']
static constraints = {
    books(nullable:true)
    empId(unique:true)
}
static hasMany = [books:Book]
static mapping = { books cascade:"all" }
static belongsTo = [person:Person]
  ......
}
  

Правильно ли это поведение?

Ответ №1:

Вы, должно быть, указали в Employee сопоставлении, который empId является первичным ключом — вероятно, это единственная причина для NonUniqueObjectException .

SQL-запрос должен исходить из уникального ограничения на empId поле.

Почему бы не использовать Grails / Hibernate неявно id , вы используете устаревшую базу данных с определенным отображением?

редактировать Я не понимаю, почему это может вызвать ограничение уникальности NonUniqueObjectException — не могли бы вы, пожалуйста, попробовать это без ограничения?

Если проблема остается, вы, должно быть, дважды сохранили объект из одного и того же сеанса — понятия не имею, как это может произойти, возможно, merge() вставив Employee из предыдущего сеанса.

SQL-запрос вызван ограничением уникальности, и это правильно.

Комментарии:

1. Нет, я этого не делал, я дважды проверял это! Таблица создания моего сотрудника выглядит так, как показано ниже Create TABLE employee ( id АВТО_ИНКРЕМЕНТ BIGINT(20) НЕ РАВЕН НУЛЮ, version BIGINT(20) НЕ РАВЕН НУЛЮ, emp_id VARCHAR (255) НЕ РАВЕН НУЛЮ,

2. Есть ли у Employee класса static mapping поле или static constraints ? Или вы используете аннотации Hibernate или XML config?

3. он имеет как статическое отображение, так и статические ограничения, обновил мой вопрос, чтобы показать статические сопоставления и ограничения

4. Я очень удивлен, если я удалю ограничение уникальности, оно будет работать отлично!! почему ограничение уникальности приводит к запуску запросов select?

5. просто потому, что его нужно проверить. Перед выдачей INSERT вам необходимо проверить, не нарушаете ли вы какие-либо ограничения. Интересно, почему бы вместо этого не перевести процесс Hibernate в режим гибернации SqlException / NonUniqueObjectException , если существует ограничение уникальности базы данных — но так оно и работает.