Hibernate Set集合映射简单例子
用户表(user_set)和电子邮件表(email_set)之间的关系:每个用户可以有多个不同的电子邮件地址,对用户来说,电子邮件就是一个集合,则在用户的实体类中就可以通过定义一个集合类型的属性来表达。
创建两个对应表:
email_set:
create table email_set( id int(11) not null, address varchar(100) not null )engine=innodb default charset=gbk;
user_set:
create table user_set( id int(11) not null auto_increment, name varchar(100) not null default '', primary key(id) )engine=innodb default charset=gbk;
建立角色实体类UserSet.java:
package collect.set; import java.util.HashSet; import java.util.Set; public class UserSet implements java.io.Serializable { // Fields private Integer id; private String name; private Set emails = new HashSet(); // Constructors /** default constructor */ public UserSet() { } /** full constructor */ public UserSet(String name) { this.name = name; } // Property accessors public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public Set getEmails() { return emails; } public void setEmails(Set emails) { this.emails = emails; } public void addEmail(String email) { this.emails.add(email); } public void removeEmail(String email) { this.emails.remove(email); } }
解析:由于一个user可以有多个电子邮件,而且每个电子邮件不能重复。所以在UserSet类中定义了Set类型的变量,用来保存电子邮件。
建立Set类型的映射文件UserSet.hbm.xml:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping> <class name="collect.set.UserSet" table="user_set" catalog="ssh"> <id name="id" type="java.lang.Integer"> <column name="id" /> <generator class="native" /> </id> <property name="name" type="java.lang.String"> <column name="name" length="100" not-null="true" /> </property> <!--Set类型映射--> <set name="emails" table="email_set"> <key column="id"></key> <element type="java.lang.String"> <column name="address"></column></element> </set> </class> </hibernate-mapping>
解析:使用set映射元素来关联email_set表,set映射元素的上面几个配置:
name:集合属性的名字。
table:这个集合对应表的名称(在此指定了Set元素对应的表为email_set)。
嵌套的标签<key>和<element>对应表"email_set"中的字段,其中<key>即表email_set的外键(取值为表user_set的主键值)。
对于List集合的话,要多加一个<index>标签来配置List索引。
通过此Set类型映射,当在表user_set中INSERT一条记录时,user_set表中多了一条记录如('1' , 'user1'),这时集合属性emails中添加的元素如email1、email2就会自动对应地(以id='1')INSERT到表email_set中去。对于“修改、删除数据”操作是一样的道理,两表同步完成UPDATE、DELETE操作。
将该映射文件加入到Hibernate配置文件中,建立测试类Test.java:
package collect.set; import java.util.Iterator; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; public class Test { public static void main(String[] args) { // Configuration管理Hibernate配置 Configuration config = new Configuration().configure(); // 根据Configuration建立 SessionFactory // SessionFactory用来建立Session SessionFactory sessionFactory = config.buildSessionFactory(); // 创建实例 UserSet user1 = new UserSet(); user1.setName("user1"); user1.addEmail("email1"); user1.addEmail("email2"); user1.addEmail("email2"); UserSet user2 = new UserSet(); user2.setName("user2"); user2.addEmail("email3"); // 定义主键变量 Integer pid; // 添加数据 Session session = sessionFactory.openSession(); Transaction tx = null; try { tx = session.beginTransaction(); // 创建主键变量 pid = (Integer) session.save(user1); session.save(user2); tx.commit(); } catch (RuntimeException e) { if (tx != null) tx.rollback(); throw e; } finally { session.close(); } // 修改数据 session = sessionFactory.openSession(); tx = null; try { tx = session.beginTransaction(); user1 = (UserSet) session.get(UserSet.class, pid); //修改user名字 user1.setName("user1 update"); user1.removeEmail("email1"); user1.addEmail("email4"); session.update(user1); tx.commit(); } catch (RuntimeException e) { if (tx != null) tx.rollback(); throw e; } finally { session.close(); } // 查询数据 session = sessionFactory.openSession(); user1 = (UserSet) session.get(UserSet.class, pid); System.out.println("user name:" + user1.getName()); Iterator iter = user1.getEmails().iterator(); while (iter.hasNext()) { System.out.println("email name:" + (String) iter.next()); } session.close(); // 删除数据 session = sessionFactory.openSession(); tx = null; try { tx = session.beginTransaction(); user1 = (UserSet) session.get(UserSet.class, pid); session.delete(user1); tx.commit(); } catch (RuntimeException e) { if (tx != null) tx.rollback(); throw e; } finally { session.close(); } // 关闭sessionFactory sessionFactory.close(); } }
注意:添加、修改、查询、删除数据,这几步要一步一步来进行测试,即在添加数据时,其他代码先注释掉;添加完后在数据库里查询结果,然后再解除"修改数据"部分的注释,就这样一步步完成测试工作。否则出现意想不到的结果。
只完成"添加数据"后的数据库中结果:
清空数据库,同时完成“添加、修改数据”,数据库中结果:
(可见在修改数据时,删除了email1,增加了email4)