如图,当多个对象之间有类似的属性的时候,可以将其公用的属性进行抽离:

拿User和Employee对象举例,此时User和Employee中的公用属性已经被抽离到一个单独的对象“Comtact”当中,但是此时数据表仍然如下:

由此可见,Component这种映射的方法,在对象模型中“细粒度”,在关系模型中仍然是“粗粒度”。
代码实现:
(1)实体
1.抽取的公共类Contact
public class Contact { PRivate String email; private String address; private String zipCode; private String contactTel; public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getZipCode() { return zipCode; } public void setZipCode(String zipCode) { this.zipCode = zipCode; } public String getContactTel() { return contactTel; } public void setContactTel(String contactTel) { this.contactTel = contactTel; }} 2.User类public class User { private String id; private String name; private Contact userContact; public Contact getUserContact() { return userContact; } public void setUserContact(Contact userContact) { this.userContact = userContact; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }} 3.Employee类public class Employee { private int id; private String name; private Contact employeeContact; public Contact getEmployeeContact() { return employeeContact; } public void setEmployeeContact(Contact employeeContact) { this.employeeContact = employeeContact; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }} 由此可见,Contact单独抽取之后,在User和Employee中,将Contact作为引用,成为其中的一个属性,并生成对应get和set方法。 (2).hbm.xml配置文件
<hibernate-mapping> <class name="com.bjpowernode.hibernate.Employee" table="t_emplyee"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <component name="employeeContact"> <property name="email"/> <property name="address"/> <property name="zipCode"/> <property name="contactTel"/> </component> </class> <class name="com.bjpowernode.hibernate.User" table="t_user"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <component name="employeeContact"> <property name="email"/> <property name="address"/> <property name="zipCode"/> <property name="contactTel"/> </component> </class></hibernate-mapping> 由此可见,在该hbm.xml当中,主键生成策略为"native",正常的name属性之后,加入<component>关联属性,子标签中加入<email><address>等子属性。
(3)存储、加载测试
public void testSave1(){ session session = null; try{ session = HibernateUtils.getSession(); session.beginTransaction(); User user = new User(); user.setName("张三"); Contact userContact = new Contact(); userContact.setAddress("address"); userContact.setContactTel("contactTel"); userContact.setEmail("email"); userContact.setZipCode("zipCode"); user.setUserContact(userContact); session.save(user); session.getTransaction().commit(); }catch(Exception e){ e.printStackTrace(); }finally{ HibernateUtils.closeSession(session); }} 分别实例化User和Contact对象并复制,将Contact对象关联到User当中后,直接session.save(user)即可,因为表中实际只有一张表,不会因对象状态出现Exception问题。 同理,加载方法如下:
public void testLoad1(){ Session session = null; try{ session = HibernateUtils.getSession(); session.beginTransaction(); User user = (User)session.load(User.class, 1); System.out.println(user.getName()); System.out.println(user.getUserContact().getAddress()); session.save(user); session.getTransaction().commit(); }catch(Exception e){ e.printStackTrace(); }finally{ HibernateUtils.closeSession(session); }} 通过加载User对象,即可加载出Contact中的内容。 总结:
采用Component的好处在于,实现对象模型的细粒度划分,复用率更高,层次更加分明。
新闻热点
疑难解答