我有一个域类,它将有很多 child 。与我的其他帖子相关:Grails: how to structure transactions when I want to continue validating even after the transaction has already failed我想创建父类(MikeyJob)的一个实例,但不保存它。然后制作一堆 child ,只有当 child 验证时,才保存 parent 和所有 child 。
这一切都很好,但是MikeyJob
需要一个工作编号,并且这个编号必须是唯一的。这让我很困惑,因为会有很多“也许它会被保存”MikeyJob
在不同的 session 中漂浮。
这是我的想法:
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 为自己播种。
我也只使用了一个时间戳字符串,可以通过添加 session 唯一值来确保它是唯一的。即.. user_id + "-"+ new Date().time
编辑:
在 Spring (grails) 中声明的 Bean 默认是单例(容器的一个实例,而不是单例模式。)因此,每次 Autowiring /注入(inject) bean 时,它都是整个系统中的同一个实例。然后你抛出一个同步方法来获取下一个值。您可以连接 bean 以在容器启动时从数据库中的最大持久(分配)值中获取它的种子(起始值)。
使用数据库序列有点不同,因为它依赖于底层数据库来分配值,但它会做同样的事情。您应该能够在域对象中定义字段以自动分配序列给定的值。
看http://mycodesnippets.com/2010/03/30/sequence-generation-with-gorm/但是对于您的场景,您可能希望在 jobNumber 字段上使用生成器。 (虽然不是 100% 肯定会起作用,但从未尝试过除 id 之外的任何字段)
关于Grails:如何生成对人类友好的、确保唯一的随机数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9298841/