apache / dubbo

The java implementation of Apache Dubbo. An RPC and microservice framework.
https://dubbo.apache.org/
Apache License 2.0
40.48k stars 26.43k forks source link

DubboService 和 @Transactional 一起配置事务失效 #10459

Closed liukefu2050 closed 2 years ago

liukefu2050 commented 2 years ago

Environment

Steps to reproduce this issue

@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class)
@Slf4j
@EnableJpaRepositories(basePackages = "com.xiushang") //用于扫描Dao @Repository
@EntityScan("com.xiushang.entity") //用于扫描JPA实体类 @Entity
@ServletComponentScan(basePackages = {"com.xiushang.filter"})
@EnableRedisHttpSession
@EnableDubbo
@EnableTransactionManagement(proxyTargetClass = true)
public class AdminApplication extends SpringBootServletInitializer {

  public static void main(String[] args) throws Exception {
    ConfigurableApplicationContext application = SpringApplication.run(AdminApplication.class, args);
  }

  @Override
  protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
    return builder.sources(AdminApplication.class);
  }

}
@DubboService(interfaceClass=CustomService.class,filter = "userFilter",retries = 0)
public class CustomServiceImpl extends BaseServiceImpl<CustomEntity> implements CustomService {

    @Transactional(readOnly = true)
    public PageTableVO findPageList(CustomSearchVo searchPageVo) {
       ...
        Page<CustomEntity> page = findPageList(ex, searchPageVo.createPageRequest(new Sort.Order(dir, "lastContactDate")));
        LazyLoadUtil.fullLoad(page);
        PageTableVO vo = new PageTableVO(page, searchPageVo);

        return vo;
    }
}

代码使用了JPA,CustomEntity 中有延迟加载的属性,因此需要session

Expected Behavior

能正常返回,并延迟加载 CustomEntity中所有属性

Actual Behavior

could not initialize proxy - no Session

If there is an exception, please attach the exception trace:


amic=true, service.filter=userFilter, anyhost=true},}, cause: org.apache.dubbo.remoting.RemotingException: Failed to send response: Response [id=6, version=2.0.2, status=20, event=false, error=null, result=AppResponse [value=com.xiushang.framework.entity.vo.PageTableVO@6fc8a7cf, exception=null]], cause: java.lang.RuntimeException: failed to lazily initialize a collection of role: com.xiushang.entity.shop.ShopEntity.images, could not initialize proxy - no Session Java field: private java.util.List com.xiushang.entity.shop.ShopEntity.images
 Java field: private com.xiushang.entity.shop.ShopEntity com.xiushang.entity.custom.CustomGroupEntity.belongShop
 Java field: private java.util.List com.xiushang.entity.custom.CustomEntity.groupList
 Java field: private java.util.List com.xiushang.framework.entity.vo.PageTableVO.rowData
java.lang.RuntimeException: failed to lazily initialize a collection of role: com.xiushang.entity.shop.ShopEntity.images, could not initialize proxy - no Session
 Java field: private java.util.List com.xiushang.entity.shop.ShopEntity.images
 Java field: private com.xiushang.entity.shop.ShopEntity com.xiushang.entity.custom.CustomGroupEntity.belongShop
 Java field: private java.util.List com.xiushang.entity.custom.CustomEntity.groupList
 Java field: private java.util.List com.xiushang.framework.entity.vo.PageTableVO.rowData
    at com.alibaba.com.caucho.hessian.io.JavaSerializer$FieldSerializer.serialize(JavaSerializer.java:304)
    at com.alibaba.com.caucho.hessian.io.JavaSerializer.writeInstance(JavaSerializer.java:284)
    at com.alibaba.com.caucho.hessian.io.JavaSerializer.writeObject(JavaSerializer.java:251)
    at com.alibaba.com.caucho.hessian.io.Hessian2Output.writeObject(Hessian2Output.java:412)
    at org.apache.dubbo.common.serialize.hessian2.Hessian2ObjectOutput.writeObject(Hessian2ObjectOutput.java:92)
    at org.apache.dubbo.rpc.protocol.dubbo.DubboCodec.encodeResponseData(DubboCodec.java:225)
    at org.apache.dubbo.remoting.exchange.codec.ExchangeCodec.encodeResponse(ExchangeCodec.java:309)
    at org.apache.dubbo.remoting.exchange.codec.ExchangeCodec.encode(ExchangeCodec.java:73)
    at org.apache.dubbo.rpc.protocol.dubbo.DubboCountCodec.encode(DubboCountCodec.java:47)
    at org.apache.dubbo.remoting.transport.netty4.NettyCodecAdapter$InternalEncoder.encode(NettyCodecAdapter.java:69)
    at io.netty.handler.codec.MessageToByteEncoder.write(MessageToByteEncoder.java:107)
    at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:717)
    at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:709)
    at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:792)
    at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:702)

请问最新版本dubbo 不是已经解决了DubboService 和 @Transactional 的问题吗,我是缺少了什么配置吗

AlbumenJ commented 2 years ago

这个和 Dubbo 没啥关系,是你的 com.xiushang.framework.entity.vo.PageTableVO 不支持 @transactional

liukefu2050 commented 2 years ago

你好,感谢回复,能具体点吗?如何解决这个问题?service我改造成dubbo之前,功能正常的啊,变成DubboService,才不行的。

AlbumenJ commented 2 years ago

https://stackoverflow.com/questions/11746499/how-to-solve-the-failed-to-lazily-initialize-a-collection-of-role-hibernate-ex 看一下这篇呢

liukefu2050 commented 2 years ago

我感觉不会是延迟加载问题,LazyLoadUtil.fullLoad(page); 方法应该已经加载了

@DubboService(interfaceClass=CustomService.class,filter = "userFilter",retries = 0)
public class CustomServiceImpl extends BaseServiceImpl<CustomEntity> implements CustomService {

    @Transactional(readOnly = true)
    public PageTableVO findPageList(CustomSearchVo searchPageVo) {
       ...
        Page<CustomEntity> page = findPageList(ex, searchPageVo.createPageRequest(new Sort.Order(dir, "lastContactDate")));
       //请注意下面这行代码
        LazyLoadUtil.fullLoad(page);
        PageTableVO vo = new PageTableVO(page, searchPageVo);

        return vo;
    }
}

public class LazyLoadUtil {

    public synchronized static void fullLoad(Object object) {
        if(object == null)
            return;
        JSON.toJSONString(object, new LazyLoadFilter());
    }

}
AlbumenJ commented 2 years ago

我感觉不会是延迟加载问题,LazyLoadUtil.fullLoad(page); 方法应该已经加载了

@DubboService(interfaceClass=CustomService.class,filter = "userFilter",retries = 0)
public class CustomServiceImpl extends BaseServiceImpl<CustomEntity> implements CustomService {

    @Transactional(readOnly = true)
    public PageTableVO findPageList(CustomSearchVo searchPageVo) {
       ...
        Page<CustomEntity> page = findPageList(ex, searchPageVo.createPageRequest(new Sort.Order(dir, "lastContactDate")));
       //请注意下面这行代码
        LazyLoadUtil.fullLoad(page);
        PageTableVO vo = new PageTableVO(page, searchPageVo);

        return vo;
    }
}

public class LazyLoadUtil {

    public synchronized static void fullLoad(Object object) {
        if(object == null)
            return;
        JSON.toJSONString(object, new LazyLoadFilter());
    }

}

看报错是在返回的时候了,可以 debug 看下

liukefu2050 commented 2 years ago

测试仓库 已重现报错,见: https://github.com/liukefu2050/DubboTransactional.git

liukefu2050 commented 2 years ago

已解决,参见 参考文章 原因:dubbo 不能序列化hibernate 中Lazy,persistent 对象。需要引入hibernate 对象序列化实现