Upgrade issue to Grails 2.4.4

2019-04-06 15:47发布

问题:

I keep getting an error when starting my Grails application after I upgraded from Grails 2.4.3 to 2.4.4 . The full error can be read here: http://pastebin.com/UXQ34JKD

2014-10-31 16:26:32 ERROR [context.GrailsContextLoaderListener] Error initializing the application: Error creating bean with name 'transactionManagerPostProcessor': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Invocation of init method failed; nested exception is org.hibernate.MappingException: Association references unmapped class: java.util.List
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManagerPostProcessor': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Invocation of init method failed; nested exception is org.hibernate.MappingException: Association references unmapped class: java.util.List
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Invocation of init method failed; nested exception is org.hibernate.MappingException: Association references unmapped class: java.util.List
        ... 4 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Invocation of init method failed; nested exception is org.hibernate.MappingException: Association references unmapped class: java.util.List
        ... 4 more
Caused by: org.hibernate.MappingException: Association references unmapped class: java.util.List
        ... 4 more

It shows an Association references unmapped class: java.util.List

It doesn't say what domain class or any really helpful information. I've tried removing some domain classes and trying to figure what the cause is, but it's large application and I have been unsuccessful.

Can anyone point me in the right direction for figuring out where this is being triggered and how to fix it?

回答1:

Finding out what's wrong

The first thing you need to do is to find out which field(s) cause the issue. Likely it'll be any field in a domain class declared as a List.

In my case it was easy to find them, because the project is on very early stage and there is not too much domains.

However, I found a possible solution to narrow down the possible culprits set.

The interesting part is:

What sucks is the only good way to figure out where they are is to set a breakpoint on line 436 of AbstractGrailsDomainBinder and look at the state of affairs

Fixing the issue

When you find the improper fields, it's time to implement a workaround.

Let's assume that our culprit was List authors in a domain class like:

class Book {
   List<Integer> authors // keeps author ids
} 

We need to get rid of the list, of course, so the solution would be something like:

class Book {

    static transients = ['authors']

    String authorIds

    public void setAuthors(List<Integer> authorList) {
        this.authorIds = authorList ? authorList.join(";") : ''
    }

    public List<Integer> getAuthors() {
        return authorIds?.split(";")?.collect { it.toInteger() } ?: []
    }

} 

Possible side effect

I noticed that the setter needs to be called explicitly to work.

I'm quite sure that in previous Grails version the following code would call the setter:

new Book(authors: [1, 2, 3])

But it looks like in Grails 2.4.4 it needs to be done like:

def book = new Book()
book.setAuthors([1, 2, 3])


回答2:

You also need to specify the hasMany map. It seems that it is not more sufficient to just add List<DomainClassName> listName in your Domain-Class

you also need to add

static hasMany = [
        listName: DomainClassName
]

at least it works for me.



回答3:

Try to replace problematic List interface with something that is real class, for example ArrayList