hibernate中对象与对象的关系(三):组件映射
在hibernate中,component是某个实体的逻辑组成部分,它与实体的根本区别是没有oid(对象标识符),component是一个被包含的对象,它作为值类型被持久化,而非一个实体。
下面举两个例子说明其使用和配置:
1.以User和Address为例,一个User有id(Long类型)、name(String类型)、address地址(Address类型),其中Address类中没有id属性(即无对象标识符),则address就是User的一个component组件。
User持久化类:
public class User { private Long id; private String name; private Address address; //省略get,set方法 }
组件类Address:
public class Address { private String country;// 国家 private String province;// 省份 private String city;// 城市 //省略get,set方法 }
User.hbm.xml配置:
<hibernate-mapping package="objectn.exus.s6_componentmapping"> <class name="User"> <id name="id"> <generator class="native"/> </id> <property name="name" /> ------------------------------------------------------------------------- <component name="address"> <property name="country" class="Address"></property> <property name="province"></property> <property name="city"></property> </component> ------------------------------------------------------------------------- </class> </hibernate-mapping>
说明:
①:User类映射的表为user,id为主键,name为User的一般属性,被映射为name字段.
②:<component>指定User类的address为User的组件,address并不是一个可以直接映射为字段的属性,而是一个类的对象,class指定类的名称,<component>的子元素<property>指定组件类的属性与user表字段的映射关系.
③:不必为Address写一个Address.hbm.xml映射文件,因为Address是作为User的一部分即值类型而不是实体被持久化的,所以Address的属性会与User的其它属性一样被映射为users表中的字段,而不会将Address映射为单独的一个表。
④:user表的结构为:
保存user对象:
public void testUserSave() { Address address=new Address("国家", "省份", "城市"); User user=new User("张三", address); user.setAddress(address); Session session = HibernateUtils.getSession(); Transaction transaction = session.beginTransaction(); session.save(user); transaction.commit(); session.close(); }
执行的SQL语句为:
Hibernate: insert into User (name, country, province, city) values (?, ?, ?, ?)
2.若User可有多个地址,即User类中的address属性为Set<Address>类型时,配置如下:
持久化类User:
public class User { private Long id; private String name; private Set<Address> address = new HashSet<>(); //省略get,set方法 }
Address类不变:
配置user.hbm.xml:
<hibernate-mapping package="objectn.exus.s6_componentmapping"> <class name="User"> <id name="id"> <generator class="native" /> </id> <property name="name" /> <!--注意<set>中并不是<one-to-many>而是<composite-element> --> <set name="address" table="address_table"> <key column="user_id"></key> <composite-element class="Address"> <property name="country"></property> <property name="province"></property> <property name="city"></property> </composite-element> </set> </class> </hibernate-mapping>
说明:
①:与一对多关联关系不同,<set>中使用的不是<one-to-many>而是<composite-element>,Hibernate会将User对象address属性(Set类型)中的所有元素映射到另外一张表中(显然user表中的记录不能表示Set中的多个元素),table属性指定另外一张表的名称为"address_table",该表存放Set中的元素,并且该表中还有一个参照user表id的外键字段user_id.
②:user表与address_table表的结构为:(使用Hibernate自动建表功能创建)
address_table表的各字段说明:
可以发现address_table表中并没有主键,只有user_id参照user表中的主键id。
保存User对象:
public void testUserSave() { Address address = new Address("中国", "陕西", "123"); Address address1 = new Address("中国", "河北", "456"); Address address2 = new Address("中国", "河南", "789"); User user = new User("张三"); User user1 = new User("李四"); user.getAddress().add(address); user.getAddress().add(address1); user.getAddress().add(address2); user1.getAddress().add(address); user1.getAddress().add(address1); user1.getAddress().add(address2); Session session = HibernateUtils.getSession(); Transaction transaction = session.beginTransaction(); session.save(user); session.save(user1); transaction.commit(); session.close(); }
输出的SQL语句为:
Hibernate: insert into User (name) values (?) Hibernate: insert into User (name) values (?) Hibernate: insert into address_table (user_id, country, province, city) values (?, ?, ?, ?) Hibernate: insert into address_table (user_id, country, province, city) values (?, ?, ?, ?) Hibernate: insert into address_table (user_id, country, province, city) values (?, ?, ?, ?) Hibernate: insert into address_table (user_id, country, province, city) values (?, ?, ?, ?) Hibernate: insert into address_table (user_id, country, province, city) values (?, ?, ?, ?) Hibernate: insert into address_table (user_id, country, province, city) values (?, ?, ?, ?)