HIbernate的一对多操作:
1. 创建实体类:一个Customer类(客户类)和一个LinkMan类(联系人),两者的关系为:一个客户中可能有多个联系人(关于一对多的实体类之间的关联,不做详细介绍,看下代码)。
Customer:
package com.geore.pojo.customer; import java.util.HashSet; import java.util.Set; import com.geore.pojo.linkman.LinkMan; public class Customer { private String cid = null; private String custLevel = null; private String custName = null; private String custSource = null; private String custMobile = null; private Set<LinkMan> mans = new HashSet<LinkMan>(); @Override public String toString() { return "Customer [cid=" + cid + ", custLevel=" + custLevel + ", custName=" + custName + ", custSource=" + custSource + ", custMobile=" + custMobile + "]"; } public String getCid() { return cid; } public void setCid(String cid) { this.cid = cid; } public String getCustLevel() { return custLevel; } public void setCustLevel(String custLevel) { this.custLevel = custLevel; } public String getCustName() { return custName; } public void setCustName(String custName) { this.custName = custName; } public String getCustSource() { return custSource; } public void setCustSource(String custSource) { this.custSource = custSource; } public String getCustMobile() { return custMobile; } public void setCustMobile(String custMobile) { this.custMobile = custMobile; } public Set<LinkMan> getMans() { return mans; } public void setMans(Set<LinkMan> mans) { this.mans = mans; } }
LinkMan:
1 package com.geore.pojo.linkman; 2 3 import com.geore.pojo.customer.Customer; 4 5 public class LinkMan { 6 private String lid = null; 7 private String linkName = null; 8 private String linkGender = null; 9 private String linkPhone = null; 10 private Customer customer = null; 11 12 public LinkMan() { 13 super(); 14 } 15 @Override 16 public String toString() { 17 return "LinkMan [lid=" + lid + ", linkName=" + linkName 18 + ", linkGender=" + linkGender + ", linkPhone=" + linkPhone 19 + ", customer=" + customer + "]"; 20 } 21 public String getLid() { 22 return lid; 23 } 24 public void setLid(String lid) { 25 this.lid = lid; 26 } 27 public String getLinkName() { 28 return linkName; 29 } 30 public void setLinkName(String linkName) { 31 this.linkName = linkName; 32 } 33 public String getLinkGender() { 34 return linkGender; 35 } 36 public void setLinkGender(String linkGender) { 37 this.linkGender = linkGender; 38 } 39 public String getLinkPhone() { 40 return linkPhone; 41 } 42 public void setLinkPhone(String linkPhone) { 43 this.linkPhone = linkPhone; 44 } 45 public Customer getCustomer() { 46 return customer; 47 } 48 public void setCustomer(Customer customer) { 49 this.customer = customer; 50 } 51 }
2. 配置实体类的Hibernate实体类配置文件
对于Hibernate实体类的配置:第一,首先将基本的class,id和property等标签的内容配置好之后,因为在Customer中,是一个一对多的关系,因此在Customer实体类中用Set集合表示一个Customer可以拥有多个联系人(Hibernate规定,在表示一对多的时候,使用的集合必须为Set集合),因此在配置文件中,需要对这种关系进行配置,而Hibernate配置文件提供了一个set标签进行配置,具体配置见下代码:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping> 6 <class name="com.geore.pojo.customer.Customer" table="t_customer"> 7 <id name="cid" column="cid"> 8 <generator class="uuid"></generator> 9 </id> 10 <property name="custLevel" column="custLevel"></property> 11 <property name="custName" column="custName"></property> 12 <property name="custSource" column="custSource"></property> 13 <property name="custMobile" column="custMobile"></property> 14 <set name="mans" cascade="save-update,delete"> 15 <key column="clid"></key> 16 <one-to-many class="com.geore.pojo.linkman.LinkMan"/> 17 </set> 18 </class> 19 </hibernate-mapping>
同时在LinkMan.hbm.xml文件中,也需要进行配置,因为Hibernate是进行双向关联,因此在LinkMan中也会有一个字段关联到Customer类,一般这个字段我们使用Customer的对象来表示,所以在xml文件中,也需要进行配置。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping> 6 <class name="com.geore.pojo.linkman.LinkMan" table="t_linkman"> 7 <id name="lid" column="lid"> 8 <generator class="uuid"></generator> 9 </id> 10 <property name="linkName" column="linkName"></property> 11 <property name="linkGender" column="linkGender"></property> 12 <property name="linkPhone" column="linkPhone"></property> 13 <many-to-one name="customer" class="com.geore.pojo.customer.Customer" not-found="ignore"> 14 <column name="clid"></column> 15 </many-to-one> 16 </class> 17 </hibernate-mapping>
3. 一对多的级联操作:
(1)、保存操作
代码片段:
1 @Test 2 public void fun1() { 3 Transaction ts = null; 4 Session session = null; 5 SessionFactory factory = null; 6 try { 7 factory = Tools.getSessionFactory(); 8 session = factory.openSession(); 9 ts = session.beginTransaction(); 10 // 一对多的操作 11 Customer customer = new Customer(); 12 customer.setCustLevel("vip"); 13 customer.setCustMobile("1378*******"); 14 customer.setCustName("Geore"); 15 customer.setCustSource("Baidu"); 16 LinkMan linkman = new LinkMan(); 17 linkman.setLinkGender("M"); 18 linkman.setLinkName("Mr.Li"); 19 linkman.setLinkPhone("****-*******"); 20 // 添加兩個對象的之间的一对多关系 21 customer.getMans().add(linkman); 22 linkman.setCustomer(customer); 23 // 添加到数据库 24 session.save(customer); 25 session.save(linkman); 26 27 ts.commit(); 28 } catch (Exception e) { 29 ts.rollback(); 30 e.printStackTrace(); 31 } finally { 32 session.close(); 33 } 34 } 35 36 @Test 37 // 级联保存的简化写法 38 public void fun2() { 39 Transaction ts = null; 40 Session session = null; 41 SessionFactory factory = null; 42 try { 43 factory = Tools.getSessionFactory(); 44 session = factory.openSession(); 45 ts = session.beginTransaction(); 46 // 一对多的操作 47 Customer customer = new Customer(); 48 customer.setCustLevel("svip"); 49 customer.setCustMobile("1378*******"); 50 customer.setCustName("Alley"); 51 customer.setCustSource("Google"); 52 LinkMan linkman = new LinkMan(); 53 linkman.setLinkGender("F"); 54 linkman.setLinkName("Mr.Wang"); 55 linkman.setLinkPhone("****-*******"); 56 // 添加兩個對象的之间的一对多关系 57 customer.getMans().add(linkman); 58 // 添加到数据库 59 session.save(customer); 60 ts.commit(); 61 } catch (Exception e) { 62 ts.rollback(); 63 e.printStackTrace(); 64 } finally { 65 session.close(); 66 } 67 }
运行截图:
对于上面的简单方法的插入,需要在Hibernate实体类的配置文件中进行配置,配置代码如下:
<set name="mans" cascade="save-update"> 需要配置的就是cascade="save-update",这个save-update表示的就是自动的会对一对多的关系在HIbernate底层进行处理,配置了这个,就不需要在代码中双向关联对应的实体类对象了
(2)、删除操作
代码片段:
1 @Test 2 // 级联删除操作,在set标签中进行配置 3 public void fun3() { 4 Transaction ts = null; 5 Session session = null; 6 SessionFactory factory = null; 7 try { 8 factory = Tools.getSessionFactory(); 9 session = factory.openSession(); 10 ts = session.beginTransaction(); 11 12 // 通过id找到对应的数据记录 13 Customer customer = session.get(Customer.class, 14 "4028d4015e6dedd5015e6deddbeb0000"); 15 session.delete(customer); 16 17 ts.commit(); 18 } catch (Exception e) { 19 ts.rollback(); 20 e.printStackTrace(); 21 } finally { 22 session.close(); 23 } 24 }
运行截图:
同样的,对于删除操作,因为是1对多,删除一个Customer,那么对应的Customer下的LinkMan也要删除,那么这样删除的话,同样要配置Hibernate的配置文件,来实现级联删除。代码如下:
1 <set name="mans" cascade="save-update,delete"> 2 <key column="clid"></key> 3 <one-to-many class="com.geore.pojo.linkman.LinkMan"/> 4 </set> 5 同样的也是在cascade中进行配置,在这个属性中给个只delete,至于之前保存操作的save-update不用删除,只需要在后面加上一个,号,在写上delete表示进行级联删除操作即可
(3)、一对多表的维护操作
代码片段:
1 @Test 2 // 将Mr.wang公司修改带Baidu,加上not-found="ignore",否则报错,原因不明 3 public void fun4() { 4 Transaction ts = null; 5 Session session = null; 6 SessionFactory factory = null; 7 try { 8 factory = Tools.getSessionFactory(); 9 session = factory.openSession(); 10 ts = session.beginTransaction(); 11 12 // 通过id找到baidu公司客户记录 13 Customer customer = session.get(Customer.class, 14 "4028d4015e6f04a6015e6f04ad120000"); 15 System.out.println(customer); 16 // 通过id找到联系人Mr.wang的记录 17 LinkMan Mr_wang = session.get(LinkMan.class, 18 "4028d4015e6f04d3015e6f04da2c0001"); 19 System.out.println(Mr_wang); 20 customer.getMans().add(Mr_wang); 21 Mr_wang.setCustomer(customer); 22 23 ts.commit(); 24 } catch (Exception e) { 25 ts.rollback(); 26 e.printStackTrace(); 27 } finally { 28 session.close(); 29 } 30 }
运行截图:
注意:使用这个修改的时候,须在一对多的多方的实体类配置文件中,配置如下属性值:
<many-to-one name="customer" class="com.geore.pojo.customer.Customer" not-found="ignore"> 就是not-found="ignore",现在还没有发现具体造成原因,不加上此句将报异常
Hibernate 多对多的操作
1. 创建多对多的实体类,并且在实体类中建立起表的多对多关系(用户表和角色表,一个用户可以有多个角色,一个角色也可以属于多个用户),实体类如下:
Role:
1 package com.geore.pojo.role; 2 3 import java.util.HashSet; 4 import java.util.Set; 5 6 import com.geore.pojo.users.Users; 7 8 public class Role { 9 private String rid = null; 10 private String roleName = null; 11 private String roleMemo = null; 12 private Set<Users> users = new HashSet<Users>(); 13 14 public Set<Users> getUsers() { 15 return users; 16 } 17 public void setUsers(Set<Users> users) { 18 this.users = users; 19 } 20 @Override 21 public String toString() { 22 return "Role [rid=" + rid + ", roleName=" + roleName + ", roleMemo=" 23 + roleMemo + "]"; 24 } 25 public String getRid() { 26 return rid; 27 } 28 public void setRid(String rid) { 29 this.rid = rid; 30 } 31 public String getRoleName() { 32 return roleName; 33 } 34 public void setRoleName(String roleName) { 35 this.roleName = roleName; 36 } 37 public String getRoleMemo() { 38 return roleMemo; 39 } 40 public void setRoleMemo(String roleMemo) { 41 this.roleMemo = roleMemo; 42 } 43 }
Users:
1 package com.geore.pojo.users; 2 3 import java.util.HashSet; 4 import java.util.Set; 5 6 import com.geore.pojo.role.Role; 7 8 public class Users { 9 private String uid = null; 10 private String username = null; 11 private String password = null; 12 private Set<Role> roles = new HashSet<Role>(); 13 14 public Set<Role> getRoles() { 15 return roles; 16 } 17 public void setRoles(Set<Role> roles) { 18 this.roles = roles; 19 } 20 @Override 21 public String toString() { 22 return "Users [uid=" + uid + ", username=" + username + ", password=" 23 + password + "]"; 24 } 25 public String getUid() { 26 return uid; 27 } 28 public void setUid(String uid) { 29 this.uid = uid; 30 } 31 public String getUsername() { 32 return username; 33 } 34 public void setUsername(String username) { 35 this.username = username; 36 } 37 public String getPassword() { 38 return password; 39 } 40 public void setPassword(String password) { 41 this.password = password; 42 } 43 }
2. 多对多关系的配置文件,Hibernate的多对多也是进行双向关联,因此对于多对多关系的两表均需要进行配置
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping> 6 <class name="com.geore.pojo.users.Users" table="t_users"> 7 <id name="uid" column="uid"> 8 <generator class="uuid"></generator> 9 </id> 10 <property name="username" column="username"></property> 11 <property name="password" column="password"></property> 12 <set name="roles" table="t_roleuser" cascade="save-update,delete"> 13 <key column="userId"></key> 14 <many-to-many class="com.geore.pojo.role.Role" column="roleId"></many-to-many> 15 </set> 16 </class> 17 </hibernate-mapping>
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping> 6 <class name="com.geore.pojo.role.Role" table="t_role"> 7 <id name="rid" column="rid"> 8 <generator class="uuid"></generator> 9 </id> 10 <property name="roleName" column="roleName"></property> 11 <property name="roleMemo" column="roleMemo"></property> 12 <set name="users" table="t_roleuser" cascade="save-update,delete"> 13 <!-- 第三张表中Users表的外键id --> 14 <key column="roleId"></key> 15 <!-- class:表示的是set集合关联的对象的全路径;column:表示关联表在第三张表中的外键 --> 16 <many-to-many class="com.geore.pojo.users.Users" column="userId"></many-to-many> 17 </set> 18 </class> 19 </hibernate-mapping>
对于这两个配置文件而言,因为是多对多的关系,因此在实体类中均需要集合进行保存,因此在配置文件中使用set标签来配置多对多的关系,又因为对于多对多的关系,一般使用的是第三张表来维护多对多的欢喜,因此在set标签中有一个属性table,表示的就是第三张表的名字.
3. 多对多的级练操作
(1)、保存操作:
代码片段:
1 @Test 2 public void fun1() { 3 // 多对多级练操作 4 Transaction ts = null; 5 Session session = null; 6 SessionFactory factory = null; 7 try { 8 factory = Tools.getSessionFactory(); 9 session = factory.openSession(); 10 ts = session.beginTransaction(); 11 12 // 往用户中添加角色 13 Users u1 = new Users(); 14 u1.setUsername("Alley"); 15 u1.setPassword("123456"); 16 17 Users u2 = new Users(); 18 u2.setUsername("Mary"); 19 u2.setPassword("456789"); 20 // 设置角色 21 Role r1 = new Role(); 22 r1.setRoleName("HR"); 23 r1.setRoleMemo("HR"); 24 25 Role r2 = new Role(); 26 r2.setRoleName("Teacher"); 27 r2.setRoleMemo("Teacher"); 28 29 Role r3 = new Role(); 30 r3.setRoleName("CEO"); 31 r3.setRoleMemo("CEO"); 32 // 用户1添加角色r1,r2 33 u1.getRoles().add(r1); 34 u1.getRoles().add(r2); 35 // 用户2添加角色r13,r2 36 u2.getRoles().add(r3); 37 38 session.save(u2); 39 session.save(u1); 40 41 ts.commit(); 42 } catch (Exception e) { 43 ts.rollback(); 44 e.printStackTrace(); 45 } finally { 46 session.close(); 47 } 48 }
对于多对多的级联保存操作,也需要对实体类的配置文件的set标签的cascade属性进行配置,如下:
1 <set name="users" table="t_roleuser" cascade="save-update">
运行截图:
(2)、级联删除操作
代码片段:
1 // 级联删除 2 @Test 3 public void fun2() { 4 // 多对多级练操作 5 Transaction ts = null; 6 Session session = null; 7 SessionFactory factory = null; 8 try { 9 factory = Tools.getSessionFactory(); 10 session = factory.openSession(); 11 ts = session.beginTransaction(); 12 13 // 第一步:查找用戶 14 Users user = session.get(Users.class, 15 "4028d4015e6f140b015e6f1411490000"); 16 session.delete(user); 17 18 ts.commit(); 19 } catch (Exception e) { 20 ts.rollback(); 21 e.printStackTrace(); 22 } finally { 23 session.close(); 24 } 25 }
同样的级联删除也需要配置实体类的HIbernate配置文件,如下:
1 <set name="users" table="t_roleuser" cascade="save-update,delete">
运行截图:
(3)、维护第三种表
>>>.维护第三张表---为用户添加新的角色(给Mary添加Teacher职责)
代码片段:
1 // 维护第三张表---为用户添加新的角色 2 @Test 3 public void fun3() { 4 // 多对多级练操作 5 Transaction ts = null; 6 Session session = null; 7 SessionFactory factory = null; 8 try { 9 factory = Tools.getSessionFactory(); 10 session = factory.openSession(); 11 ts = session.beginTransaction(); 12 13 // 第一步:查找用戶, 14 Users user = session.get(Users.class, 15 "4028d4015e6f1fe3015e6f1fe99a0000"); 16 // 查找角色 17 Role role = session.get(Role.class, 18 "4028d4015e6f1fe3015e6f1fe9da0004"); 19 // 添加角色到用户 20 user.getRoles().add(role); 21 22 ts.commit(); 23 } catch (Exception e) { 24 ts.rollback(); 25 e.printStackTrace(); 26 } finally { 27 session.close(); 28 } 29 }
运行截图:
>>>.维护第三张表---删除为用户的角色(删除Mary添加Teacher职责)
代码片段:
1 // 维护第三张表---一处用户的某个角色 2 @Test 3 public void fun4() { 4 // 多对多级练操作 5 Transaction ts = null; 6 Session session = null; 7 SessionFactory factory = null; 8 try { 9 factory = Tools.getSessionFactory(); 10 session = factory.openSession(); 11 ts = session.beginTransaction(); 12 13 // 第一步:查找用戶, 14 Users user = session.get(Users.class, 15 "4028d4015e6f1fe3015e6f1fe99a0000"); 16 // 查找角色 17 Role role = session.get(Role.class, 18 "4028d4015e6f1fe3015e6f1fe9da0004"); 19 // 添加角色到用户 20 user.getRoles().remove(role); 21 22 ts.commit(); 23 } catch (Exception e) { 24 ts.rollback(); 25 e.printStackTrace(); 26 } finally { 27 session.close(); 28 } 29 }
运行截图: