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

(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
                + "]";
    }


  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

订单领域对象:(提供 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 + "]";
    }

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

初始化数据:

        //初始化数据,向数据库中插入客户和订单信息
        @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();

      }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

测试代码:

     @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(); 

    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

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

这里写图片描述

原因是两个对象的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 + "]";
    }
  
  
  • 1
  • 2
  • 3
  • 4

打印结果:

这里写图片描述

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

打印结果:

这里写图片描述

(3)当然也可以把两个领域对象中的对方属性都去掉
打印结果和(2)中一样
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值