(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)中一样