我有一个有很多孩子的域类。与我的另一篇文章相关:Grails: how to structure transactions when I want to continue validating even after the transaction has already failed我想创建父类的实例(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
}
}
这似乎有效,但还有更好的方法吗?
答案 0 :(得分:1)
它真的需要随机吗?或者只是独特的?获得“随机”数字并不能真正保证它在所有方面都是独一无二的,甚至是跨时间的。
首先想到的是让一个单例类型的对象只是将前一个数字加1(或使用数据库序列)。在真正尝试保存整棵树之前,请不要设置它。你的单身人士可以使用最大的持续工作号+ 1来自我种子。
我还使用了一个时间戳字符串,可以通过添加会话唯一值来确保它是唯一的。 ie .. user_id +“ - ”+ new Date()。time
编辑:
Spring中声明的Bean(grails)默认是Singletons(容器的一个实例,而不是Singleton Pattern。)因此,每次自动装配/注入bean时,它都是整个系统中的相同实例。然后你抛出一个synchronized方法来获取那里的下一个值。当容器启动时,您可以将bean连接起来从数据库中最大的持久(分配)值中获取它的种子(起始值)。
使用数据库序列有点不同,因为它依赖于底层数据库来分配值,但它会做同样的事情。您应该能够在域对象中定义字段以自动分配序列给出的值。
查看http://mycodesnippets.com/2010/03/30/sequence-generation-with-gorm/但是对于您的场景,您需要在jobNumber字段上使用生成器。 (不是100%肯定会工作,但从未尝试过除id之外的任何领域)