【问题标题】:Avoid Jackson serialize Mybatis lazyload object in SpringMVC避免 Jackson 在 SpringMVC 中序列化 Mybatis 延迟加载对象
【发布时间】:2018-09-04 07:57:38
【问题描述】:

我有一个由 Spring MVC 框架构建的 RESTful 项目,使用 Mybatis ORM。

有两个表,Book 和 Author,具有一对多的关系。

我启用了延迟加载,这样当我查询 Book 时,它不会查询 Author,除非我调用 book.getAuthor() 方法,并且一切正常。

mybatis-config.xml:启用延迟加载

BookMapper.xml

但是,当RESTful控制器返回Book对象时,它使用Jackson将Book对象转成json,并触发mybatis加载Author对象..

Controller:在第 30 行,它只查询 Book.

在第 31 行之后,它还查询作者

RESTful控制器返回json时,有没有办法防止mybatis触发延迟加载?

【问题讨论】:

    标签: spring-mvc jackson lazy-loading mybatis


    【解决方案1】:

    问题不在mybatis。问题在于序列化。如果查询属性,mybatis 只能加载属性。

    解决方法是配置序列化,使authors属性不被序列化。

    这可以例如使用Jackson MixIns

    首先,创建指定附加配置的混入:

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

    然后你需要将这个 mix-in 添加到 spring 使用的 jackson mapper 配置中。确切的方法取决于您是使用 xml 还是 java 配置。对于 java 配置,这看起来像这样:

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

    请注意,这将在所有控制器方法中禁用authors 的序列化。如果您需要能够根据控制器和/或控制器方法进行切换,则设置会更复杂(例如,查看 this

    【讨论】:

    • 感谢您的回复。实际上,就我而言,只要用户想要获取作者数据,就可以调用 Book.getAuthors(),因此此配置可能不适合我的情况,因为它禁用了所有作者序列化。
    【解决方案2】:

    我找到了一个解决方案,虽然不是最好的,但它确实有效。仍然期待更好的解决方案。

    Jackson序列化Book对象时,触发Book.getAuthors(),Mybatis检测到Book.getAuthors()被调用,于是Mybatis通过Javassist代理执行延迟加载如下:

    注意“任何调用getter的人都会触发延迟加载”(红圈),这就是Jackson在序列化中总是触发延迟加载的原因!

    为了解决这个问题,我修改了Book bean:

    1. 在 Book.getAuthors() 上添加 @JsonIgnore,以防止 Jackson 调用 getAuthors()。
    2. 在Book.loadDetail()上添加@JsonGetter(value = "authors"),这样Jackson可以序列化作者时不会触发延迟加载。

    结果如下:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-23
      • 1970-01-01
      • 1970-01-01
      • 2012-07-27
      • 2015-04-26
      相关资源
      最近更新 更多