grails 4没有枚举常量?
Posted
技术标签:
【中文标题】grails 4没有枚举常量?【英文标题】:grails 4 no enum constant? 【发布时间】:2022-01-11 11:46:06 【问题描述】:我正在将我的 grails 2 应用程序升级到 grails 4。我已经能够更正所有编译时错误,现在应用程序可以运行。它会在点击控制器操作时引发此错误。
No enum constant com.company.compositeEvent.ResultsStatus.2
在控制器的这一行
if (idList)
result = RaceGroup.createCriteria().list([sort: 'startDateTime', order: 'asc', offset: offset, max: max])
inList('id', idList)
join 'address'
RaceGroup 有 resultsstatus 属性
ResultsStatus resultsStatus
ResultStatus 是一个枚举,定义为
enum ResultsStatus
NO_RESULTS(1),
RACE_RESULTS(2),
EXTERNAL_RESULTS(3)
int id
private ResultsStatus(int id)
this.id = id
它在 grails 2 中运行良好。我怀疑 grails 4 中发生了一些变化,也许定义枚举的方式是错误的。我感谢任何指导。
更新:
RaceGroup 域定义为
class RaceGroup extends CompositeEvent implements Serializable
List<Race> races
static hasMany = [races: Race]
static mappedBy = [races: 'raceGroup']
static mapping =
discriminator RaceGroup.getSimpleName()
races cascade: 'all-delete-orphan'
static constraints =
List<SubEvent> getSubEvents()
this.races
CompositeEvent 定义为
abstract class CompositeEvent extends BaseEntity implements Serializable, Named, Addressable
EventGroup eventGroup
/**
* Currency to use for this Event. Defaults to 'USD'
*/
final Currency currency = Currency.getInstance('USD')
/**
* User that created this event.
*/
User user
/**
* Name of this overall event.
* <p>
* 'compositeEventName' is used instead of just 'name' because when sorting
* by name, billingPerson.name is used by grails.
*/
String compositeEventName
/**
* General Information that is entered by the director and displayed on
* the registration page.
*/
String displayMessage
/**
* Location name of the address of this event
*/
String locationName
/**
* Address of this event.
* <p>
* Address is stored as one of its sub-classes: USAddress, CanadaAddress,
* etc.
*/
Address address
/**
* Start date and time of this event.
*/
Date startDateTime
/**
* Time zone to display the formatted date in.
*/
TimeZone timeZone
/**
* End date of this event.
*/
SqlDate endDate
/**
* The total number of possible participants, number reserved spots,
* and the number of allocated spots.
*/
Capacity capacity = new Capacity(reference: this)
String token = UUID.randomUUID().toString().replaceAll('-', '').take(12)
Boolean autoTransferToV6Active
Boolean showMaxParticipantsLimitInRegistrationPage = false
Integer showMaxParticipantsLimitBelowThreshold
/**
* Director on the registration page listed as being in charge of
* this event.
*/
Director director
/**
* Person or organization responsible for handling billing and payment
* in association with this event.
*/
BillingPerson billingPerson
String displayLiveRegistrationsPassword
Boolean displayLiveRegistrations
/**
* Whether the list of individuals registered for this event or any of
* its sub-events will be displayed on the registration page.
*/
Boolean displayParticipants
/**
* Whether the number of individuals registered for this event or any
* sub-events will be displayed on the registration page.
*/
Boolean displayEventRegNum
/**
* Whether the teams registered for this event or any sub-events will
* be displayed on the registration page
*/
Boolean displayTeams
/**
* Whether the number of people in each team will displayed on the
* registration page.
*/
Boolean displayTeamRegNum
/**
* Whether seed marks will be displayed in the list of participants
*/
Boolean displaySeedMarks
/**
* Whether to display the product photos in the public event page
*/
Boolean displayProductImages = true
/**
* Whether this event is listed among active events and can the
* registration page can be accessed.
*/
Boolean published = false // whether this composite event can be viewed
Boolean unlisted = false // whether this composite event is listed on the website
Boolean emailReceipts = true // email a receipt each time someone registers
/**
* The date from which age will be calculated for participants.
*
* The date must be:
* <p><i>
* this.startDateTime - 1 year <= this.ageAsOf <= this.startDateTime
* </i>
*/
SqlDate ageAsOf
/**
* External web-site with information regarding this event
*/
String homePage
/**
* Required fields of each participant that are set by the director.
*/
RequiredParticipantFields requiredFields
/**
* Logo for this event
*/
Image logo
/**
* Taxes applied to this event
*/
Tax tax
/**
* Access code to be access registration for all subEvents. An access code
* set in an order template would be used instead of this if both are set.
*/
String accessCode
/**
* Disclaimer that must be accepted by all participants before registering.
*/
Disclaimer disclaimer
/**
* TimingDetails contains data in regards to requesting and providing
* timing services from RunnerCard
*/
TimingDetails timingDetails
//Status of Referral. Whether or not to show the referral or share on facebook button
ReferralStatus referralStatus
String bibsRange
Boolean assignBibNumbers
//in registration form whether to allow user to select more than 1 shirt
Boolean allowMultiProductSelectionInRegistration
//in event registration page show products only purchase
Boolean enableProductsOnlyPurchase = true
Boolean enableVirtualRace
/**
* Ids of past events all separated by a delimiter comma (,)
* eg 51243, 51234, 64345, 43454
*/
String eventHistory
Set<Product> products
String resultsLink
ResultsStatus resultsStatus
// automatically updated by GORM
Date dateCreated
Date lastUpdated
abstract List<SubEvent> getSubEvents()
static transients = ['name', 'nameIdAndParticipants']
static hasMany = [products: Product]
//static belongsTo = [eventGroup: EventGroup]
static mapping =
address cascade: 'all'
director cascade: 'save-update,merge,refresh,evict,lock'
displayMessage type: 'text'
requiredFields unique: true
capacity cascade: 'refresh,delete'
bibsRange type: 'text'
static namedQueries =
withAddress
join 'address'
withBilling
join 'billingPerson'
withRequiredFields
join 'requiredFields'
static constraints =
compositeEventName blank: false
showMaxParticipantsLimitInRegistrationPage nullable: true
showMaxParticipantsLimitBelowThreshold nullable: true
autoTransferToV6Active nullable: true
enableVirtualRace nullable: true
eventGroup nullable: true
eventHistory blank:true, nullable: true
displayMessage blank: false, nullable: true
locationName blank: false
referralStatus nullable: true
bibsRange nullable:true
assignBibNumbers nullable: true
allowMultiProductSelectionInRegistration nullable: true
enableProductsOnlyPurchase nullable: true
address()
timeZone bindable: true, inList: TimeService.TIME_ZONES
endDate validator: SqlDate endDate, CompositeEvent obj ->
if (obj.startDateTime == null) return
Calendar start = Calendar.getInstance()
start.setTime(obj.startDateTime)
start.set(Calendar.HOUR_OF_DAY, 0)
start.set(Calendar.MINUTE, 0)
start.set(Calendar.SECOND, 0)
start.set(Calendar.MILLISECOND, 0)
Date startDay = start.getTime()
DateFormat formatter = DateFormat.getDateInstance(DateFormat.SHORT, LCH.getLocale())
if (startDay.compareTo(endDate) > 0)
return ["default.invalid.min.message", formatter.format(startDay)]
director validator: Director person, CompositeEvent compositeEvent, Errors errors ->
UtilityService.cascadeValidation(person, 'director', errors)
billingPerson validator: BillingPerson person, CompositeEvent compositeEvent, Errors errors ->
UtilityService.cascadeValidation(person, 'billingPerson', errors)
displayParticipants()
displayEventRegNum()
displayTeams()
displayTeamRegNum validator: Boolean val, CompositeEvent obj, Errors errors ->
if (obj.displayTeams != null && val && !obj.displayTeams)
errors.rejectValue("displayTeamRegNum", "compositeEvent.invalid.displayTeamRegNum")
displaySeedMarks()
displayProductImages()
published()
homePage blank: false, nullable: true, validator: String homePage, CompositeEvent compositeEvent ->
// If it is a url that isn't http:// or https://
if (compositeEvent.homePage != null
&& !compositeEvent.homePage.matches('^http(s)?://.*')
&& compositeEvent.errors.getFieldErrors('homePage').size() == 0)
return "default.invalid.url.message"
ageAsOf nullable: true // if null my.calculateAge() will calculate age based on the current Date
requiredFields nullable: true
logo nullable: true
tax nullable: true, validator: Tax tax, obj, Errors errors ->
UtilityService.cascadeValidation(tax, 'tax', errors)
accessCode blank: false, nullable: true
displayLiveRegistrationsPassword nullable: true
displayLiveRegistrations nullable: true
resultsLink nullable: true
resultsStatus nullable: true
disclaimer()
timingDetails nullable: true
/**
* Saves capacity of this event at initial save
*/
void beforeInsert()
this.capacity.save()
void afterInsert()
CompositeEvent.withNewSession
def productOwnerSettingService = this.getBean("productOwnerSettingService")
productOwnerSettingService.createSetting(this)
/**
* Checks that the logged in user has delete or admin privileges on
* this object and then deletes all AutoUpdateJob instances and acl
* objects that reference this object.
*/
void beforeDelete()
CompositeEvent.withNewSession
def posc = ProductOwnerSettingCompositeEvent.createCriteria().get()
eq('event', this)
def setting = posc?.productOwnerSetting
if(posc)
posc.delete(flush: true)
if(setting)
setting.delete(flush: true)
super.beforeDelete()
private Object getBean(String beanName)
try
return this.domainClass.grailsApplication.mainContext.getBean(beanName)
catch(NoSuchBeanDefinitionException e)
return null
catch(MissingPropertyException e)
return null
/* (non-Javadoc)
* @see com.runnercard.Named#getName()
*/
String getName() this.compositeEventName
void setName(String name) this.compositeEventName = name
地址域定义为
abstract class Address extends BaseEntity implements Serializable
String address1
String address2
String city
String area
String postalCode
// automatically updated by GORM
Date dateCreated
Date lastUpdated
static belongsTo = [User, BillingPerson, CompositeEvent, RaceParticipant,
EmbeddedRaceParticipant]
static mapping =
discriminator value: Address.getSimpleName(), column: 'country'
static constraints =
address1 nullable: true
address2 nullable: true
city nullable: true
area nullable: true
postalCode nullable: true
static List getCountries()
return ['usa', 'can', 'other']
boolean equals(Object obj)
if (!Address.isInstance(obj)) return false
Address other = (Address) obj
if (this.address1 == other.address1
&& this.address2 == other.address2
&& this.city == other.city
&& this.area == other.area
&& this.postalCode == other.postalCode)
return true
else
return false
int hashCode()
HashCodeBuilder builder = new HashCodeBuilder(1333, 1353)
if (this.address1) builder.append(this.address1)
if (this.address2) builder.append(this.address2)
if (this.city) builder.append(this.city)
if (this.area) builder.append(this.area)
if (this.postalCode) builder.append(this.postalCode)
builder.toHashCode()
【问题讨论】:
我无法重现该问题。您能否展示RaceGroup
的完整源代码以及address
指向的内容?
杰夫,我添加了缺少的域类。 racegroup 实际上是抽象 CompositeEvent 类的子类,地址是 CompositeEvent 的属性。感谢您的帮助。
感谢 jeff 找到了解决方案,但现在遇到了另一个问题。由于某种原因 RaceRegistration.createCriteria().list() eq('compositeEvent', raceGroup) 抛出数组越界异常。
"RaceRegistration.createCriteria().list() eq('compositeEvent', raceGroup) 抛出数组越界异常" - 你能展示RaceRegistration
类中的内容吗? compositeEvent
指向?
如果您可以分享一个简单的小示例项目来演示该问题,那就更好了。通常只是创建它就会发现问题所在。
【参考方案1】:
问题是我必须把它放在映射中
resultsStatus enumType: 'ordinal'
【讨论】:
以上是关于grails 4没有枚举常量?的主要内容,如果未能解决你的问题,请参考以下文章
Grails 4、Ubuntu 20、嵌入式 Tomcat - 请求中没有多部分文件