1

I have a RESTful project that is build by Spring MVC framework, with Mybatis ORM.

There are two tables, Book and Author, with one-many relationship. enter image description here

I enable Lazy Load, so that when I query Book, it won't query Author unless I call book.getAuthor() method, and everything works well.

mybatis-config.xml: enable Lazy Load enter image description here

BookMapper.xml enter image description here

However, when RESTful controller return Book object, it use Jackson to transfer Book object to json, and it trigger mybatis to load Author object..

Controller: in line 30, it only query Book.enter image description hereenter image description here

After line 31, it also query Author enter image description here

Is there a way to prevent mybatis trigger lazy load when RESTful controller return json?

YM cho
  • 313
  • 2
  • 11

2 Answers2

1

The problem is not in mybatis. The problem is in serialization. If the property is queried mybatis has no choice but load the property.

The solution is to configure serialization so that authors property is not serialized.

This can be done for example using Jackson MixIns:

First, create mix-in that specifies additional configuration:

abstract class NoAuthorsMixIn {
   @JsonIgnore abstract List<Author> authors();
}

Then you need to add this mix-in to jackson mapper configuration that is used by spring. The exact way depends on whether you use xml or java configuration. For java configuration this looks like this:

@Configuration
public class JacksonConfiguration {

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.addMixIn(Book.class, NoAuthorsMixIn.class);
        return mapper;
    }
}

Note that this will disable serialization of authors in all controller methods. If you need to be able to switch it per controller and/or controller method the setup is more complicated (look to this for example)

  • Thx for your reply. Actually, in my case, it's possible to call Book.getAuthors() as long as user wants get author data, so this configuration may not fit my case since it disable all authors serialization. – YM cho Mar 28 '18 at 01:01
1

I found a solution, not the best, but it works. Still expect a better solution.

When Jackson serialize Book object, it trigger Book.getAuthors(), Mybatis detects that Book.getAuthors() is called, so Mybatis execute lazy load by Javassist proxy as follow: enter image description here

Note that "anyone who call getter will trigger lazy loading" (red circle), and that's the reason why Jackson always trigger lazy loading in serialization!

To solve this problem, I modify Book bean:

  1. Add @JsonIgnore on Book.getAuthors(), that prevent Jackson call getAuthors().
  2. Add @JsonGetter(value = "authors") on Book.loadDetail(), so that when Jackson can serialize authors and won't trigger lazy loading.

enter image description here

Here is the result: enter image description here enter image description here

enter image description here enter image description here

YM cho
  • 313
  • 2
  • 11