Hibernate中一对多关联映射时,查询某个对象报 java.lang.StackOverflowError错误

在Hibernate框架中,一对多关系映射导致查询对象时出现`java.lang.StackOverflowError`错误。问题源于对象的toString()方法递归调用过深。解决方案包括:1) 删除所有领域对象的toString()方法,但会导致打印结果仅为内存地址;2) 修改其中一个对象的toString()方法,移除对方对象的属性引用,避免无限递归。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(Hibernate框架 一)

以客户和订单为例,模拟一对多关系映射

客户领域对象:(提供 setter();和getter();函数,以及toString()方法)

    private Integer id;

    private String name;

    // 客户对应多个订单 (订单不能重复)
    private Set<Order> orders = new HashSet<Order>();

    ......

    @Override
    public String toString() {
        return "Customer [id=" + id + ", name=" + name + ", orders=" + orders
                + "]";
    }

订单领域对象:(提供 setter();和getter();函数,以及toString()方法)

    private Integer id;

    private Double money;

    private String receiveinfo;//地址

    // 订单关联一个客户
    private Customer customer;

    ......

    @Override
    public String toString() {
        return "Order [id=" + id + ", money=" + money + ", receiveinfo="
                + receiveinfo + ", customer=" + customer + "]";
    }

初始化数据:

        //初始化数据,向数据库中插入客户和订单信息
        @Test
        public void demo1(){

            Session session =HibernateUtils.getSession();
            Transaction transaction =session.beginTransaction();

            Customer customer = new Customer();
            customer.setName("张三");

            for(int i = 1;i<=10;i++){

                Order order = new Order();
                order.setMoney(i*100d);
                order.setReceiveinfo(customer.getName()+"_addr"+i);

                //订单关联客户
                order.setCustomer(customer);
                //客户关联订单 
                customer.getOrders().add(order);

            }

            session.save(customer);

            transaction.commit();
            session.close();

      }

测试代码:

     @Test
    public void demo6(){

          Session session =HibernateUtils.getSession();
          Transaction transaction =session.beginTransaction();

          //查询张三的所有的订单
          //隐式内连接 o.customer.name=? (.name:隐式的内连接,自动查找
          List<Order> list = session.createQuery("from Order o where o.customer.name=?").setParameter(0, "张三").list();
          System.out.println(list);

          transaction.commit();
          session.close(); 

    }

打印张三客户的所有订单时,报错:

这里写图片描述

原因是两个对象的toString方法重写之后,应用程序递归太深了,所以发生了堆栈溢出。

解决办法

1、把领域对象的toString()方法去掉

这是最简单的方法,但是这样打印出来的结果只是订单的内存地址,不易查看

(1)把Order领域对象的toString方法去掉,打印结果为:

这里写图片描述

(2)把Customer领域对象中的toString方法去掉,打印结果为:

这里写图片描述

虽然看结果是可以的,但是当查询客户的时候,打印出来的就是客户对应的内存地址了,不方便查看,所以不推荐使用这一方法

(3)如果两个领域对象的toString方法都去掉,打印结果还是为对应的内存地址

2、把某一个领域对象 toString() 方法里的,另一个领域对象的属性去掉即可

(既然是函数的循环递归,那么我们只要破坏中间的某一环即可)

(1)在Customer领域对象中,将toString函数修改为
    @Override
    public String toString() {
        return "Customer [id=" + id + ", name=" + name + "]";
    }

打印结果:

这里写图片描述

(2)在Order领域对象中
    @Override
    public String toString() {
        return "Order [id=" + id + ", money=" + money + ", receiveinfo="
                + receiveinfo  + "]";
    }

打印结果:

这里写图片描述

(3)当然也可以把两个领域对象中的对方属性都去掉
打印结果和(2)中一样
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值