在引导程序中填充 List 的奇怪 Grails 行为
Posted
技术标签:
【中文标题】在引导程序中填充 List 的奇怪 Grails 行为【英文标题】:Strange Grails behaviour populating List at bootstrap 【发布时间】:2013-07-25 18:12:34 【问题描述】:我对一种奇怪的 Grails 行为感到疯狂。
我得到一个域类用户:
class User
String firstName
String token
List roles = [] as List
static constraints =
我像这样修改我的 BootStrap.groovy 以填充 5 个用户实例:
class BootStrap
def init = servletContext ->
switch (Environment.getCurrent())
case 'DEVELOPMENT':
def user1 = new User(
id: 1,
firstName: 'Enricot',
token: 'L\'abricot'
)
user1.roles.add('ROLE_USER')
user1.save(failOnError: true)
def user2 = new User(
id: 2,
firstName: 'Arnaud',
token: 'Dauphin')
user2.roles.add('ROLE_USER')
user2.roles.add('PERM_WRITE')
user2.save(failOnError: true)
def user3 = new User(
id: 3,
firstName: 'Magalie',
token: 'La banane')
user3.roles.add('ROLE_USER')
user3.roles.add('PERM_READ')
user3.save(failOnError: true)
def user4 = new User(
id: 4,
firstName: 'Jeremy',
token: 'Wistiti')
user4.roles.add('ROLE_USER')
user4.roles.add('ROLE_ADMIN')
user4.save(failOnError: true)
def user5 = new User(
id: 5,
firstName: 'Jimini',
token: 'Criquet')
user5.roles.add('ROLE_USER')
user5.roles.add('ROLE_INTERACTIONS')
user5.save(failOnError: true)
break
case "test":
DataBuilder.init()
break
def destroy =
在我的控制器中,当我获得一个用户时,所有字段都是正确的,除了列表。
如果我这样做:
def user = User.get(1)
println user.firstName // Output is "Enricot"
println user.token // Output is "L'abricot"
println user.roles // Output is "[]" and not "[ROLE_USER]"
尝试像这样填充对象并没有解决我的问题:
def user1 = new User(
id: 1,
firstName: 'Enricot',
token: 'L\'abricot',
roles: ['ROLE_USER']).save(failOnError: true)
我试过双引号,单引号。
最有趣的部分是当我将“user.roles”制作成 BootStrap.groovy 时,我得到了正确的列表。
这对我来说毫无意义,欢迎任何帮助,
【问题讨论】:
作为仅供参考,您不必那样做环境。只做环境开发测试生产 【参考方案1】:这不是奇怪的行为,你做错了:)
当您添加一个想要持久化的字段时,您需要向 Grails 提供有关如何存储它的信息。只是一个简单的List
是不够的信息。如果它是其他域类的列表,它将创建一个外键并存储 id。如果它是一个字符串列表,它会将它们存储为 varchars。如图in the documentation,你需要做这样的事情:
class User
String firstName
String token
static hasMany = [roles: String]
这会将支持集合更改为Set
,但这对于角色来说可能是正确的,因为您不关心排序并且想要唯一性。如果您确实需要订购,请添加一个未初始化的 List
字段以向 Grails 发出您不想要 Set
的信号:
class User
String firstName
String token
List roles
static hasMany = [roles: String]
这会改变您填充数据的方式。不要直接添加到集合中,而是使用为您添加的动态 addToRoles
方法:
class BootStrap
def init = ctx ->
environments
development
def user1 = new User(firstName: 'Enricot', token: 'L\'abricot')
user1.addToRoles('ROLE_USER')
user1.save(failOnError: true)
def user2 = new User(firstName: 'Arnaud', token: 'Dauphin')
user2.addToRoles('ROLE_USER')
user2.addToRoles('PERM_WRITE')
user2.save(failOnError: true)
def user3 = new User(firstName: 'Magalie', token: 'La banane')
user3.addToRoles('ROLE_USER')
user3.addToRoles('PERM_READ')
user3.save(failOnError: true)
def user4 = new User(firstName: 'Jeremy', token: 'Wistiti')
user4.addToRoles('ROLE_USER')
user4.addToRoles('ROLE_ADMIN')
user4.save(failOnError: true)
def user5 = new User(firstName: 'Jimini', token: 'Criquet')
user5.addToRoles('ROLE_USER')
user5.addToRoles('ROLE_INTERACTIONS')
user5.save(failOnError: true)
test
DataBuilder.init()
有关 BootStrap.groovy 中环境块支持的信息,请参阅 http://grails.org/doc/latest/guide/conf.html#environments。
另外请注意,我删除了您的显式 id 值,因为您没有使用分配的 id,因此这些值被忽略。
最后,您似乎正在推出自己的安全措施。不要这样做。使用经过验证的框架。 Spring Security Core 和 Shiro 功能强大且易于上手。
【讨论】:
【参考方案2】:这是 grails 的正常行为。下面的代码只是将项目添加到当前对象的列表中(重要!不是数据库引用):
user1.roles.add('ROLE_USER')
要将数据库映射添加到角色,请使用如下动态方法:
user1.addToRoles('ROLE_USER')
假设:你的意思是你的域
List<Strings> roles
static hasMany = [roles:String]
【讨论】:
以上是关于在引导程序中填充 List 的奇怪 Grails 行为的主要内容,如果未能解决你的问题,请参考以下文章
类 [] 上的方法在 Grails 应用程序之外使用。如果在使用模拟 API 或引导 Grails 的测试上下文中正确运行
如何在引导程序中获取 grails 数据源 createdb 属性
为啥 stacktrace.log 没有在 grails 3 中填充 logback?