首页 > 技术文章 > 一次StackOverflowError事故-----参数类型问题

Cassie-wang 2019-07-11 14:09 原文

背景:公司需要做一个小程序,从把服务器数据库里面的数据拷贝到本地

技术:spring-boot, XXL-RPC, JPA

问题 : 客户端查询数据,调用RPC服务,一直报错 StackOverflowError:null,

问题重现:

数据表test

CREATE TABLE test (
  "rid" int(11) NOT NULL AUTO_INCREMENT,
  "name" varchar(45) DEFAULT NULL,
  "age" int(11) DEFAULT NULL,
  "create_time" datetime DEFAULT NULL,
  PRIMARY KEY ("rid")
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Test实体类

import java.io.Serializable;
import java.time.LocalDateTime;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Entity
@Table(name = "test")
public class TestEntity implements Serializable{

    /**
     * 
     */
    private static final long serialVersionUID = -7189192698006290220L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "rid")
    private Integer id;
    
    private String name;
    
    private Integer age;
    
    private LocalDateTime createTime;
    
    
}

Repository ,使用的是JPA,具体关于JPARepository的知识,自己补习吧

import org.springframework.data.jpa.repository.JpaRepository;

public interface TestRepository extends JpaRepository<TestEntity, Integer>{
    
}

Service服务,直接与数据库交互的

public interface TestService {
    TestEntity save(TestEntity entity);
}
@Service
public class TestServiceImpl implements TestService{
    
    @Resource
    private TestRepository testRepository;

    @Override
    public TestEntity save(TestEntity entity) {
        return testRepository.save(entity);
    }

}

服务端开放的RPC服务

public interface WqqTestRpcService {
    
    TestEntity save(TestEntity entity);
}
import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.wqq.test.TestEntity;
import com.wqq.test.WqqTestRpcService;
import com.wqq.test.TestService;
import com.xxl.rpc.remoting.provider.annotation.XxlRpcService;
@XxlRpcService
@Service
public class WqqTestRpcServiceImpl implements WqqTestRpcService{
    
    @Resource
    private TestService testService;

    @Override
    public TestEntity save(TestEntity entity) {
        return testService.save(entity);
    }

}

客户端使用

    @XxlRpcReference
    private WqqTestRpcService wqqTestRpcService;
    
    public void save() {
        TestEntity entity = new TestEntity();
        entity.setAge(23);
        entity.setName("我是谁");
        entity.setId(3);
        entity.setCreateTime(LocalDateTime.now());
        wqqTestRpcService.save(entity);
        
    }

习惯写完之后测试

测试TestService, WqqTestRpcService

@ContextConfiguration(classes = TestServerApplication.class)
@RunWith(SpringRunner.class)
@SpringBootTest
//@Transactional
//@Rollback
public class Test{
    
    @Resource
    private TestService testService;
    
    @Resource
    private WqqTestRpcService wqqTestRpcService;
    
    @Test
    public void test1() {
        TestEntity entity = new TestEntity();
        entity.setAge(23);
        entity.setName("测试1");
        entity.setId(1);
        entity.setCreateTime(LocalDateTime.now());
        wqqTestRpcService.save(entity);
    }
    @Test
    public void test2() {
        TestEntity entity = new TestEntity();
        entity.setAge(23);
        entity.setName("测试2");
        entity.setId(2);
        entity.setCreateTime(LocalDateTime.now());
        testService.save(entity);
    }
    
    
}

结果:数据库插入两条数据,说明方法是没有问题的

正式运行。开始报错 Caused by: java.lang.StackOverflowError: null

百思不得其解,查了网上很多基本都是说死循环或者是无线递归,可是我只是调用一个保存的方法,哪里来的死循环还有递归,还有说改变配置,但是我测试方法是行得通的,直觉告诉我不会说是改变配置(真的直觉,但是可能别人是有这样解决的,反正我没有试),后来又进行了很多次测试,结果完全想不到是参数类型的问题,把TestEntity的参数类型与LocalDateTime改成Date就可以,具体为啥这样,还没结论,只是知道这么不再报错,但是是不是真的最好的结局办法,依然不知, 希望有大神可以解惑吧

 

推荐阅读