Hibernate中我们经常用到组件属性,以及关联属性(比如N-1关联),但是他们有什么区别?首先我们了解一下基本概念:

一:组件属性

组件属性的意思是:持久化类的属性并不是基本数据类型,也不是字符串、日期等标量类型的变量,而是一个复合类型的对象,在持久化过程中,它仅仅被当做值类型,而并非引用另一个持久化实体。组件属性的类型可以是任何自定义类,下面我们举个例子:

我们有个Person类,有id、name、age、还有个组件属性Address address(这个类型是我们定义的)

Person.java

1. import
2.   
3. @Entity
4. @Table(name="embeddable_inf")  
5. public class
6. @Id
7. @Column(name="person_id")  
8. @GeneratedValue(strategy=GenerationType.IDENTITY)  
9. private
10. private
11. private
12. //组件属性 Address为我们定义的类
13. private
14. public
15. super();  
16. this.name = name;  
17. this.age = age;  
18.     }  
19. //省略所有set、get方法



在Hibernate中,Address并不是一个持久化类,它也不是Java中的8大基本数据类型,它仅仅是一个我们自定义的类然后被当做address组件属性的类型,那既然不是一个持久化类,那么Address这个类中的属性就不会单独存储在一张数据表中,而是和Person这个类一同储存在一张表中。

我们在看看我们定义的组件属性类型Addess类

Address.java

1. import
2.   
3. import
4. //标明该类作为持久化类的组件类使用
5. @Embeddable
6. public class
7. @Column(name="address_order")  
8. private
9. @Column(name="address_detail")  
10. private
11. //指定含有该组件的持久化类
12. @Parent
13. private
14. //无参构造函数
15. public
16. super();  
17.     }  
18. public
19. super();  
20. this.id = id;  
21. this.addressDetail = addressDetail;  
22.     }  
23. //省略所有set、get方法



@Embeddable注解指定该类为持久化类的组件类使用,并且通过@Parent注解指定使用该组件的持久化类,可以发现,我们并没有通过@Entity将Address类指定为持久化类。

看我们的测试类 

Test.java

1. import
2.   
3. import
4.   
5. public class
6.   
7. public static void
8. // TODO Auto-generated method stub
9.         Session session=HibernateUtil.currentSession();  
10.         Transaction tx=session.beginTransaction();  
11. new Person("VipMao","23");  
12. new Address("01","山东青岛");  
13.         person.setAddress(address);  
14.         session.save(person);  
15.         tx.commit();  
16.         HibernateUtil.closeSession();  
17.         HibernateUtil.sessionFactory.close();  
18.     }  
19.   
20. }

这里的Session和Transaction都是通过HibernateUtil工具类创建的



数据库结果:

 

一个对象关联另一个个对象时新增数据java_持久化

可以看出,组件类中的列也和持久化中的类中的列保存在同一张表中。

二:关联映射

我们再拿同一个例子来看看Hibernate中的关联映射

拿Person-Address单向N-1关联来讲,多个Person关联一个Address。

于是我们这样定义Person类:同样有id、name、age属性,以及和Address形成N-1关联关系

Person.java

1. import
2.   
3. import
4. import
5.   
6.   
7. @Entity
8. @Table(name="person_inf")  
9. public class
10. @Id
11. @Column(name="person_id")  
12. @GeneratedValue(strategy=GenerationType.IDENTITY)  
13. private
14. private
15. private
16. @ManyToOne(targetEntity=Address.class)  
17. //指定外键
18. @JoinColumn(name="address_id",nullable=false)  
19. //级联操作
20. @Cascade(CascadeType.ALL)  
21. private
22.       
23. public
24. super();  
25. this.name = name;  
26. this.age = age;  
27.     }  
28. //省略所有set、get方法



我们通过@ManyToOne指定Address属性,完成N-1的映射,我们再来看看,Address类的定义:

Address.java

1. import
2.   
3. @Entity
4. @Table(name="address_inf")  
5. public class
6. @Id
7. @GeneratedValue(strategy=GenerationType.IDENTITY)  
8. @Column(name="address_id")  
9. private int
10. @Column(name="address_detail")  
11. private
12. public
13. super();  
14. this.addressDetail = addressDetail;  
15.     }  
16. //省略所有set、get方法



可以看出,Person、Address两个类我们都通过@Entity完成了持久化,这就要求两个类的属性都保存在不同的数据表中,这是和组件属性不同的,关联操作就是一个持久化类和另一个持久化类存在某种关联关系,而组件属性则是一个类是另一个持久化类的组件属性,

我们的测试类

Test.java

1. import
2.   
3. public class
4. public static void
5.         Session session=HibernateUtil.currentSession();  
6.         Transaction tx=session.beginTransaction();  
7. new Address("山东曲阜");  
8. new Address("江西南昌");  
9.         session.save(a1);  
10.         session.save(a2);  
11.         session.flush();  
12. new Person("VipMao","23");  
13.         person.setAddress(a1);  
14. new Person("马洪昌","23");  
15.         person2.setAddress(a1);  
16.         session.save(person);  
17.         session.save(person2);  
18.         tx.commit();  
19.         HibernateUtil.closeSession();  
20.         HibernateUtil.sessionFactory.close();  
21.           
22.           
23.       
24.     }  
25. }



数据库结果:

 

一个对象关联另一个个对象时新增数据java_hibernate_02

一个对象关联另一个个对象时新增数据java_hibernate_03

可以看出Person、Address的数据分别被保存在了不同的数据表中。

总结:

Hibernate中组件属性只是持久化类引用另一个复合类型的对象(可以是我们自定义的类,像上面的Address类),组件类并不是持久化类,组件类通过@Embeddable注解,并通过@Parent注解引用该组件的持久化类,组件类数据与持久化类数据保存在同一张表中。而映射关系则是某持久化类和另一个持久化类存在某种映射关系(比如N-1、1-N),两个都为持久化类,数据分别保存在不同的数据表中。