Grails - уникальный и нулевой - PullRequest
       13

Grails - уникальный и нулевой

1 голос
/ 12 апреля 2010

альтернативный текст http://i41.tinypic.com/13ykqvb.png

Здесь DealerID может иметь значение NULL и CarID, TyreID не нужны.

Проблема, которую я заметил: Grails игнорирует нули в уникальных ограничениях.

Ответы [ 4 ]

3 голосов
/ 13 апреля 2010

Я не думаю, что вопрос ясен, но это может быть ошибка в Grails.

2 голосов
/ 30 апреля 2011
static constraints = {<br> dealerID nullable:true;<br> carID unique:'dealerID', blank:false;<br> tyreID unique:'carID';<br>}<br>


Это не будет работать как задумано. Это сделает carID уникальным только в рамках авизо дилера. tyreID будет уникальным в рамках «carID». Это означает, что при вводе этой совершенно правильной строки проверка не будет выполнена:

CarID      TyreID      DealerID
 01           02          NULL        Existing row
 01           02           95         New row is rejected 

Это потому, что TyreID не уникален - он конфликтует с существующим CarID. Мы хотим, чтобы уникальное ограничение применялось к области действия всех указанных полей

Насколько я знаю, эта проблема все еще существует в последней версии Grails (1.3.7)

Это мой обходной путь

В своем доменном классе напишите пользовательский валидатор для поля, которое ищет существующую запись, используя CriteriaBuilder:

class MyClass {
...
static constraints = {
...
carID( validator: { Integer carID,  MyClass thisInstance ->
                def existingRecord = MyClass.withCriteria(uniqueResult:true){
                    ne('id', thisInstance.id)
                    if (thisInstance.tyreID) {
                       eq('tyreID', thisInstance.tyreID)
                    }
                    else {
                       isNull('tyreID')
                    }
                    if (thisInstance.dealerID) {
                       eq('dealerID', thisInstance.dealerID)
                    }
                    else {
                       isNull('dealerID')
                    }
                })
                if (existingRecord) {
                    return ['myClass.duplicate', existingRecord.id]
                }
                else {
                    return true
                }
            }
        )

и в свойствах вашего сообщения вы можете предупредить пользователя, что эта запись конфликтует с определенной записью:

message.properties
...
myClass.duplicate = {0} is identical to existing record {3}

Это хакерское решение, требующее потенциально ненужного попадания в базу данных и выглядит безобразно. Мне это не нравится, но это работает.

0 голосов
/ 06 октября 2015

Это старая тема, но я все равно решил поделиться своим верным решением. Он использует дополнительный столбец, поэтому ему нужно немного больше места для хранения, но он сохраняет производительность так же быстро, как если бы не было обнуляемых. В соответствии с вашим примером, вы добавляете / меняете (при условии, что ваши идентификаторы являются простыми строками из-за пустого ограничения и для простоты):

String dealerID
String dealerIDConstraint
String carID
String tyreID

static constraints = {
    dealerID           nullable: true
    dealerIDConstraint blank: false
    carID              blank: false, unique: ['tyreID','dealerIDConstraint']
    tyreID             blank: false
}

// This will cover updates from web pages.
def beforeValidate() {
    updateDealerIDConstraint()
}

// This will cover direct access.
void setDealerID(String dealerId) {
    this.dealerId = dealerId

    updateDealerIDConstraint()
}

/**
 * Ensure the validation only field is up to date.
 */
private void updateDealerIDConstraint() {
    dealerIDConstraint = dealerID ?: tyreID + "-" + carID
}

Поле ограничения всегда будет иметь значение и не будет мешать вам, когда предполагается, что оно не имеет значения для уникальности.

0 голосов
/ 30 марта 2011

Я знаю, что это слишком поздно в игре, но чтобы сделать комбинации уникальными, я бы представил ограничения следующим образом:

static constraints = {
  dealerID nullable:true;
  carID    unique:'dealerID', blank:false;
  tyreID   unique:'carID';
}

Это должно гарантировать, что даже если Grails игнорирует уникальное ограничение наcarID из-за того, что значением параметраID_ID является нулевое значение, вы не получите комбинацию идентификаторов carID и tyreID, которые конфликтуют.По крайней мере, я так думаю.

...