如何更改生成表中的列顺序(grails 约束不适用于 mongodb 插件)
Posted
技术标签:
【中文标题】如何更改生成表中的列顺序(grails 约束不适用于 mongodb 插件)【英文标题】:How to change columns order in generated table (grails constraints not working with mongodb plugin) 【发布时间】:2012-11-12 02:08:04 【问题描述】:我正在使用带有 mongodb 插件的 Grails 2.1.1。我在更改生成列表中的列顺序时遇到问题。正如grails scaffolding guide 所说,您只需要在约束块中正确排序属性。
我的域名:
class Section
String idName
String visible
String required
String name
String bold
static embedded = ['question']
List<Question> questions
static hasMany = [questions : Question]
static constraints =
idName (blank: false)
name (blank: false)
visible (blank: false)
required (blank: false)
bold (blank: false)
@Override
public String toString()
name
但列仍按字母顺序排列。我正在使用静态脚手架,因此在更改约束后我使用grails generate-all *
命令并覆盖所有文件。
是的,我尝试清理和编译代码,还清理和重新启动服务器(与 STS 集成)并清理浏览器缓存。 mongo数据库有问题(hibernate插件被卸载)?
之后我还安装了 grails 模板。在 list.gsp 中有一行带有排序属性:
Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[]))
知道如何更改它以获得我在约束中设置的工作顺序吗?
【问题讨论】:
我使用相同的环境(但没有更改为 mongodb)启动了新的 grails 项目,并且按约束排序。所以我几乎可以肯定卸载hibernate插件和/或安装mongodb插件有问题。我会检查它并在这里给出答案。 【参考方案1】:应该填写一个 jira 问题。如果一个人看着 https://github.com/grails/grails-core/blob/master/grails-crud/src/main/groovy/org/codehaus/groovy/grails/scaffolding/DefaultGrailsTemplateGenerator.groovy
void generateView(GrailsDomainClass domainClass, String viewName, Writer out)
def templateText = getTemplateText("$viewName.gsp")
if (templateText)
def t = engine.createTemplate(templateText)
def multiPart = domainClass.properties.find it.type == ([] as Byte[]).class || it.type == ([] as byte[]).class
boolean hasHibernate = pluginManager?.hasGrailsPlugin('hibernate')
def packageName = domainClass.packageName ? "<%@ page import=\"$domainClass.fullName\" %>" : ""
def binding = [pluginManager: pluginManager,
packageName: packageName,
domainClass: domainClass,
multiPart: multiPart,
className: domainClass.shortName,
propertyName: getPropertyName(domainClass),
renderEditor: renderEditor,
comparator: hasHibernate ? DomainClassPropertyComparator : SimpleDomainClassPropertyComparator]
t.make(binding).writeTo(out)
很明显,调用生成视图决定使用 SimpleDomainClassPropertyComparator。 Grails 最初是为依赖休眠而构建的。在过去的几年里,世界一直在使用额外的持久性机制。如果看一下 DomainClassPropertyComparator,就会发现对 hibernate 没有依赖。我觉得代码应该测试 domainObject “hasConstraints” 来决定使用哪个比较器,或者默认情况下简单地使用 DomainClassPropertyComparator。如果没有找到约束,它的行为是相同的。 DefaultGrailsTemplateGenerator 不需要调用“hasHibernate”。
作为一种解决方法,您可以安装脚手架模板,编辑 _form.gsp 并将它使用的比较器更改为 DomainClassPropertyComparator 例如我的_form.gsp
<%=packageName%>
<% import grails.persistence.Event %>
<% import org.codehaus.groovy.grails.scaffolding.DomainClassPropertyComparator %>
<% excludedProps = Event.allEvents.toList() << 'version' << 'dateCreated' << 'lastUpdated'
persistentPropNames = domainClass.persistentProperties*.name
boolean hasHibernate = pluginManager?.hasGrailsPlugin('hibernate')
if (hasHibernate && org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder.getMapping(domainClass)?.identity?.generator == 'assigned')
persistentPropNames << domainClass.identifier.name
DomainClassPropertyComparator mattsComparator = new DomainClassPropertyComparator(domainClass)
comparator = mattsComparator
props = domainClass.properties.findAll persistentPropNames.contains(it.name) && !excludedProps.contains(it.name)
Collections.sort(props, comparator)
for (p in props)
if (p.embedded)
def embeddedPropNames = p.component.persistentProperties*.name
def embeddedProps = p.component.properties.findAll embeddedPropNames.contains(it.name) && !excludedProps.contains(it.name)
Collections.sort(embeddedProps, comparator)
%><fieldset class="embedded"><legend><g:message code="$domainClass.propertyName.$p.name.label" default="$p.naturalName" /></legend><%
for (ep in p.component.properties)
renderFieldForProperty(ep, p.component, "$p.name.")
%></fieldset><%
else
renderFieldForProperty(p, domainClass)
private renderFieldForProperty(p, owningClass, prefix = "")
boolean hasHibernate = pluginManager?.hasGrailsPlugin('hibernate')
boolean display = true
boolean required = false
if (hasHibernate)
cp = owningClass.constrainedProperties[p.name]
display = (cp ? cp.display : true)
required = (cp ? !(cp.propertyType in [boolean, Boolean]) && !cp.nullable && (cp.propertyType != String || !cp.blank) : false)
if (display) %>
<div class="fieldcontain \$hasErrors(bean: $propertyName, field: '$prefix$p.name', 'error') $required ? 'required' : ''">
<label for="$prefix$p.name">
<g:message code="$domainClass.propertyName.$prefix$p.name.label" default="$p.naturalName" />
<% if (required) %><span class="required-indicator">*</span><% %>
</label>
$renderEditor(p)
</div>
<% %>
【讨论】:
【参考方案2】:如果您在模板中注释下面的行并重新生成视图,则约束中的顺序将是脚手架中的顺序
//Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[]))
【讨论】:
【参考方案3】:约束应该如您所描述的那样更新视图。尝试运行grails generate-all --stacktrace
脚本可能会在相应地更新视图之前终止。另一种策略是检查问题是否存在于以下陈述中,因此摆脱它们并检查视图是否相应更新可能会让您更接近解决问题。
static embedded = ['question']
List<Question> questions
static hasMany = [questions : Question]
希望这会有所帮助!
【讨论】:
选项--stacktrace
没有提供更多信息,但我确信脚本正确结束,因为在更改域中的字段后,gsp 文件中的视图会更新。对于我的域中的这些“其他语句”,我在我的项目中创建了新的简单域来测试脚手架:class Simple String zzz String kkk String aaa static constraints = kkk() zzz() aaa()
但在生成新视图后,gsp 页面中的列和字段的顺序仍然是字母顺序。我认为这更多的是关于配置或这个 mongodb 插件,而不仅仅是我的域定义。【参考方案4】:
经过一些测试,我确信只使用没有休眠插件的 mongodb 插件会导致禁用一些脚手架功能。例如,在生成视图期间省略了约束子句。要完成这项工作,您需要使用休眠。 因此,如果您想拥有自动生成的代码并仍然使用 mongodb,则有一个技巧: 使用 hibernate 创建、生成和完成项目,然后在生产环境中卸载 hibernate 并安装 mongodb。
【讨论】:
以上是关于如何更改生成表中的列顺序(grails 约束不适用于 mongodb 插件)的主要内容,如果未能解决你的问题,请参考以下文章
Grails数据库迁移-将插入值手动更改日志记录到表中的特定列