Grails: как сгенерировать удобное для человека уникальное случайное число - PullRequest
2 голосов
/ 15 февраля 2012

У меня есть класс домена, в котором будет много детей. Связанный с этим другим моим постом: Grails: как структурировать транзакции, когда я хочу продолжить проверку даже после того, как транзакция уже провалилась Я хочу создать экземпляр родительского класса (MikeyJob), но НЕ сохранять Это. Затем создайте группу детей, и только если дети подтвердят, сохраните родителя и всех детей.

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

Это моя мысль:

import java.util.Random
Class MikeyJob{
  BigInteger jobNumber

  def beforeInsert() = {
    //this is where I think I need help
    Random rand = new Random()
    BigInteger max = 99999999
    BigInteger randomInt = rand.nextInt(max)
    MikeyJob.withSession{
      while(randomInt<9999999 || MikeyJob.findByJobNumber(randomInt)){
       randomInt = rand.nextInt(max)
      }
    }
    this.jobNumber = randomInt
  }

  static hasMany=[jobItems:JobItem]
  static constraints = {
    jobNumber(nullable:true)
  }
}

Class JobItem{
  String importantStuff
}

Итак, у меня есть служба, которая в основном выглядит так:

Class JobMakerService{
  def makeAJob(def bigMessyList){
    def someNewJob = new MikeyJob()  /NOT SAVED
    def validItems = []
    def invalidItems = []
    bigMessyList.each{
      def jobItem = //pseudo code to get a job item out of messy list
      //also not saved
      if(jobItem.validate())validItems.add jobItem
      else invalidItems.add jobItem


    }
    if(invalidItems = []){
      someNewJob.save()
      validItems.each{
        it.save()
      }
    } else def errorHandling  = 1/0


  }
}

Кажется, это работает, но есть ли лучший способ?

1 Ответ

1 голос
/ 16 февраля 2012

Это действительно должно быть случайным? Или просто уникальный? Получение «случайного» числа не может действительно гарантировать его уникальность во всем или даже во времени.

Первая мысль, которая приходит в голову, это иметь объект синглтонного типа, который просто добавляет 1 к предыдущему числу (или использует последовательность базы данных). Не устанавливайте его, пока вы действительно не попытаетесь сохранить все дерево. Ваш синглтон может заполнить себя самым большим постоянным номером задания + 1.

Я также использовал только строку метки времени, могу убедиться, что она уникальна, добавив уникальное значение сеанса. то есть .. user_id + "-" + new Date (). время

EDIT:

Бины, объявленные в Spring (grails), по умолчанию являются синглетонами (один экземпляр для контейнера, а не шаблон Singleton). Таким образом, каждый раз, когда вы автоматически подключаете / внедряете бин, это один и тот же экземпляр во всей системе. Затем вы добавляете синхронизированный метод, чтобы получить следующее значение. Вы можете подключить компонент к началу, чтобы получить его начальное значение (начальное значение) из наибольшего постоянного (назначенного) значения из базы данных при запуске контейнера.

Использование последовательности базы данных немного отличается, так как она полагается на базовую базу данных для присвоения значения, но это будет делать то же самое. Вы должны иметь возможность определить поле в доменном объекте для автоматического назначения значения, заданного последовательностью.

Посмотрите на http://mycodesnippets.com/2010/03/30/sequence-generation-with-gorm/ Но для вашего сценария вы бы хотели, чтобы генератор был в вашем поле jobNumber. (Не уверен на 100%, что это сработает, никогда не пробовал ни в одном поле, кроме id)

...