2.1、Hibernate多表操作--一对多、多对一、多对多。
一、什么是一对一、一对多、多对一及多对多关系(以简单的学生和老师的关系为例来说):
1、一对一:学生具有学号和姓名(假定没有同名的学生)这两个属性,那么我知道了学生的学号也就能找到对应的学生姓名,如果我找到了学生的姓名也就能够找到学生的学号,两者之间是一一对应的,即一对一。
2、一对多:以一个学生为对象,学生可以选择多门门课程,每门课程对应一个老师,即一个学生对应多个老师为他教学。那么这样就产生了一对多的关系。
3、多对一:每一个学生都可以选择不同的课程,但是课程的数量是有限的,这样一来就会有多个学生选择选择同一门课,即就是多个学生对应于同一个老师。这样就产生了多对一的关系。
4、多对多:从学生的角度来说:一个学生可以对应多个老师,从老师的角度来说:一个老师可以同时教多个学生。如果同时考虑学生和老师,那么就产生了多对多的关系。
二、简单的一对多关系(.xml):
1、创建两张表:
1 create table t_item( 2 id number primary key, 3 item_name varchar2(30) 4 ); 5 create table t_image( 6 item_id number references t_item(id), 7 img_name varchar2(30) 8 );
2、创建一个web项目,将Hibernate框架所需的jar包拷贝到lib目录下。
3、粘贴上一篇日志中的HibernateTools工具类。
4、创建一个ItemBean类
1 package com.st.bean1; 2 3 import java.util.HashSet; 4 import java.util.Set; 5 6 public class ItemBean { 7 8 private long id; 9 private String itemName; 10 11 private Set<String> imge =new HashSet<String>(); 12 13 public long getId() { 14 return id; 15 } 16 17 public void setId(long id) { 18 this.id = id; 19 } 20 21 public String getItemName() { 22 return itemName; 23 } 24 25 public void setItemName(String itemName) { 26 this.itemName = itemName; 27 } 28 29 public Set<String> getImge() { 30 return imge; 31 } 32 33 public void setImge(Set<String> imge) { 34 this.imge = imge; 35 } 36 37 @Override 38 public String toString() { 39 return "ItemBean [id=" + id + ", itemName=" + itemName + ", imge=" 40 + imge + "]"; 41 } 42 }
5、.拷贝一个xxx.hbm.xml文件到com.st.bean目录下,重命名为item.hbm.xml,并修改class标签中的属性:使item表与ItemBean类之间存在映射关系:
1 <?xml version="1.0"?> 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 6 <hibernate-mapping> 7 8 <class name="com.st.bean1.ItemBean" table="t_item"> 9 <id name="id" column="ID"> 10 <!-- class用于设置主键生成方式increment-自增长; assigned-指定的 --> 11 <generator class="increment"></generator> 12 </id> 13 <!-- 普通节点配置 --> 14 <property name="itemName" column="ITEM_NAME" type="java.lang.String" ></property> 15 16 <!-- 基本的一对多配置 17 name:javaBean 里面的集合名 18 table:映射外键对应的表 19 key:映射的外表的外键 20 elememt:元素值对应的列 21 --> 22 <set name="imge" table="t_image"> 23 <!-- 指定外键 --> 24 <key column="item_id"></key> 25 <element column="IMG_NAME" type="java.lang.String"></element> 26 </set> 27 </class> 28 </hibernate-mapping>
6、拷贝一个hibernate.cfg.xml文件到src文件下,删除hibernate.xml文件中无用的映射文件后,添加映射文件-item.hbm.xml。
7、6、在新建一个BeanTest类,在里面即可编写相应的增删改查的代码:
1 @Test 2 public void bean1test1(){ 3 // 获取一个会话 4 Session session = HibernateTools.openSession(); 5 //开启一次事物 6 Transaction tran = session.beginTransaction(); 7 ItemBean item = new ItemBean (); 8 item.setItemName("第四个项目"); 9 item.getImge().add("a4.jpg"); 10 item.getImge().add("b4.jpg"); 11 session.save(item); 12 //确认提交事物 13 tran.commit(); 14 } 15 @Test 16 public void bean1test2(){ 17 Session session = HibernateTools.openSession(); 18 List<ItemBean> list= session.createCriteria(ItemBean.class).list(); 19 for(ItemBean a : list) 20 System.out.println(a); 21 } 22 @Test 23 public void bean1test3(){ 24 Session session = HibernateTools.openSession(); 25 ItemBean item = (ItemBean)session.get(ItemBean.class,1L); //1L代表主键 26 Transaction tran = session.beginTransaction(); 27 session.delete(item); 28 tran.commit(); 29 }
三、复杂的一对多关系:
1、创建两张表:
1 /*部门表*/ 2 create table dept( 3 id number primary key, 4 name varchar2(30) /*部门名称*/ 5 ); 6 /*员工表*/ 7 create table employee( 8 id number primary key, 9 name varchar2(30), 10 sex varchar2(2), 11 job varchar2(20), 12 dept_id number references dept(id) /*所在部门*/ 13 );
2、创建一个DeptBean类
1 package com.st.bean2; 2 3 import java.util.HashSet; 4 import java.util.Set; 5 6 public class DeptBean { 7 private long id; 8 private String name; 9 10 private Set<EmployeeBean> emp = new HashSet<EmployeeBean>(); 11 12 @Override 13 public String toString() { 14 return "DeptBean [id=" + id + ", name=" + name +"]"; 15 } 16 17 public long getId() { 18 return id; 19 } 20 21 public void setId(long id) { 22 this.id = id; 23 } 24 25 public String getName() { 26 return name; 27 } 28 29 public void setName(String name) { 30 this.name = name; 31 } 32 33 public Set<EmployeeBean> getEmp() { 34 return emp; 35 } 36 37 public void setEmp(Set<EmployeeBean> emp) { 38 this.emp = emp; 39 } 40 41 42 }
3、创建一个EmployeeBean类
1 package com.st.bean2; 2 3 public class EmployeeBean { 4 private long id; 5 private String name; 6 private String sex; 7 private String job; 8 private long deptId; 9 //一个员工对应于一个部门号,所以这里不用集合 10 private DeptBean dept ; //注意这个地方不要new对象,否则会无法运行 11 12 public long getId() { 13 return id; 14 } 15 16 public void setId(long id) { 17 this.id = id; 18 } 19 20 public String getName() { 21 return name; 22 } 23 24 public void setName(String name) { 25 this.name = name; 26 } 27 28 public String getSex() { 29 return sex; 30 } 31 32 public void setSex(String sex) { 33 this.sex = sex; 34 } 35 36 public String getJob() { 37 return job; 38 } 39 40 public void setJob(String job) { 41 this.job = job; 42 } 43 44 public long getDeptId() { 45 return deptId; 46 } 47 48 public void setDeptId(long deptId) { 49 this.deptId = deptId; 50 } 51 52 public DeptBean getDept() { 53 return dept; 54 } 55 56 public void setDept(DeptBean dept) { 57 this.dept = dept; 58 } 59 60 @Override 61 public String toString() { 62 return "EmployeeBean [id=" + id + ", name=" + name + ", sex=" + sex 63 + ", job=" + job + ", deptId=" + deptId + ", dept=" + dept 64 + "]"; 65 } 66 }
4、配置DeptBean这个类的xml文件
1 <hibernate-mapping> 2 3 <class name="com.st.bean2.DeptBean" table="DEPT"> 4 <id name="id" column="ID"> 5 <!-- class用于设置主键生成方式increment-自增长; assigned-指定的 --> 6 <generator class="increment"></generator> 7 </id> 8 <!-- 普通节点配置 --> 9 <property name="name" column="NAME" type="java.lang.String" ></property> 10 11 <!-- 一对多配置一的一方 12 name:javaBean 里面的集合名 13 cascade:级联关系(增加、删除、修改) 14 inverse:表示是否维护关系 15 key:映射的外表的外键 16 class:对应外表的JavaBean 17 --> 18 <set name="emp" cascade="all" inverse="false"> 19 <!-- 指定外键 --> 20 <key column="dept_id"></key> 21 <one-to-many class="com.st.bean2.EmployeeBean"/> <!-- 外表对应的JavaBean --> 22 </set> 23 </class> 24 </hibernate-mapping>
5、配置EmployeeBean这个类的xml文件
1 <hibernate-mapping> 2 3 <class name="com.st.bean2.EmployeeBean" table="employee"> 4 <id name="id" column="ID"> 5 <!-- class用于设置主键生成方式increment-自增长; assigned-指定的 --> 6 <generator class="increment"></generator> 7 </id> 8 <!-- 普通节点配置 --> 9 <property name="name" column="NAME" type="java.lang.String" ></property> 10 <property name="sex" column="SEX" ></property> 11 <property name="job" column="JOB" ></property> 12 13 <!-- 多的一方的属性名 --> 14 <many-to-one name="dept" column="DEPT_ID"></many-to-one> 15 </class> 16 </hibernate-mapping>
6、将上面两个类的配置文件映射到hibernate.cfg.xml文件中去。
7、在BeanTest类下面编写测试代码:
1 @Test 2 public void bean2test1(){ 3 // 获取一个会话 4 Session session = HibernateTools.openSession(); 5 //开启一次事物 6 Transaction tran = session.beginTransaction(); 7 8 //首先在dept中新增一条数据,再在关联的employee中新增一条数据 9 DeptBean dept = new DeptBean(); 10 //先读去dept中的数据,再在读取的基础上关联的在employee中新增一条数据 11 // DeptBean dept = (DeptBean) session.get(DeptBean.class,1L); //1L代表主键 12 EmployeeBean emp = new EmployeeBean(); 13 dept.setName("技术部"); 14 emp.setName("陈泽俊"); 15 emp.setSex("男"); 16 emp.setJob("STM32"); 17 emp.setDeptId(1); 18 dept.getEmp().add(emp); 19 session.save(dept); 20 //确认提交事物 21 tran.commit(); 22 } 23 @Test 24 public void bean2test2(){ 25 Session session = HibernateTools.openSession(); 26 List<DeptBean> list= session.createCriteria(DeptBean.class).list(); 27 for(DeptBean a : list) 28 System.out.println(a.getEmp()); 29 System.out.println("/************************************************************************/"); 30 List<EmployeeBean> list1= session.createCriteria(EmployeeBean.class).list(); 31 for(EmployeeBean a : list1) 32 System.out.println(a); 33 } 34 @Test 35 //注意以下三种删除方法的不同之处,更新和删除一样 36 public void bean2test3(){ 37 Session session = HibernateTools.openSession(); 38 Transaction tran = session.beginTransaction(); 39 //先将employee的dept_id更新为null,再讲dept删除 40 /* DeptBean dept = new DeptBean(); 41 dept.setId(1L); 42 session.delete(dept);*/ 43 //直接将employee中的类容删除,dept中的类容不删除 44 /* EmployeeBean employee = new EmployeeBean(); 45 employee.setId(1L); 46 session.delete(employee);*/ 47 //将employee中的关联外键dept_id更新为null,再删除employee中的数据再删除dept中的数据 48 DeptBean dept = (DeptBean) session.get(DeptBean.class, 1L); 49 session.delete(dept); 50 tran.commit(); 51 }
四、多对多关系
1、新建三张表t_user、t_role及第三张关联表user_role
1 create table t_user( 2 id number primary key, 3 name varchar2(30), 4 sex varchar2(10) 5 ); 6 create table t_role( 7 id number primary key, 8 post varchar2(30),--职位 9 pay number --薪资 10 ); 11 create table user_role( 12 user_id number references t_user(id) , 13 role_id number references t_role(id) 14 ); 15 16 17 select *from t_role; 18 select *from t_user; 19 select *from user_role; 20 21 drop table user_role; 22 drop table t_role; 23 drop table t_user;
2、上述已有的目下新建一个bean3包,再在包下面新建两个类:UserBean和RoleBean
a)userBean
1 package com.st.bean3; 2 import java.util.HashSet; 3 import java.util.Set; 4 public class UserBean { 5 private long id; 6 private String name; 7 private String sex; 8 9 private Set<RoleBean> role = new HashSet<RoleBean>(); 10 11 public long getId() { 12 return id; 13 } 14 public void setId(long id) { 15 this.id = id; 16 } 17 public String getName() { 18 return name; 19 } 20 public void setName(String name) { 21 this.name = name; 22 } 23 public String getSex() { 24 return sex; 25 } 26 public void setSex(String sex) { 27 this.sex = sex; 28 } 29 public Set<RoleBean> getRole() { 30 return role; 31 } 32 public void setRole(Set<RoleBean> role) { 33 this.role = role; 34 } 35 @Override 36 public String toString() { 37 return "UserBean [id=" + id + ", name=" + name + ", sex=" + sex 38 + ", role=" + role + "]"; 39 } 40 }
b)RoleBean
1 package com.st.bean3; 2 import java.util.HashSet; 3 import java.util.Set; 4 public class RoleBean { 5 private long id; 6 private String post;//职位 7 private int pay; //薪资 8 9 private Set<UserBean> user = new HashSet<UserBean>(); 10 11 public long getId() { 12 return id; 13 } 14 public void setId(long id) { 15 this.id = id; 16 } 17 public String getPost() { 18 return post; 19 } 20 public void setPost(String post) { 21 this.post = post; 22 } 23 public int getPay() { 24 return pay; 25 } 26 public void setPay(int pay) { 27 this.pay = pay; 28 } 29 public Set<UserBean> getUser() { 30 return user; 31 } 32 public void setUser(Set<UserBean> user) { 33 this.user = user; 34 } 35 @Override 36 public String toString() { 37 return "RoleBean [id=" + id + ", post=" + post + ", pay=" + pay + "]"; 38 } 39 }
3、在bean包下面添加两个Bean类的.xml配置文件
a)user.hbm.xml
1 <hibernate-mapping> 2 3 <class name="com.st.bean3.UserBean" table="T_USER"> 4 <id name="id" column="ID"> 5 <!-- class用于设置主键生成方式increment-自增长; assigned-指定的 --> 6 <generator class="increment"></generator> 7 </id> 8 <!-- 普通节点配置 --> 9 <property name="name" column="NAME" type="java.lang.String" ></property> 10 <property name="sex" column="SEX" type="java.lang.String" ></property> 11 12 <!-- 多对多关系映射 13 name:javaBean对应的属性名 14 table:中间表 15 key中的column:与本类主键对应的中间表的外键 16 many-to-many中的column:class里设置的类的主键对应的中间表的外键 17 --> 18 <set name="role" table = "user_role" cascade="save-update" inverse="false"> 19 <key column="USER_ID"></key> 20 <many-to-many class="com.st.bean3.RoleBean" column="ROLE_ID"></many-to-many> 21 </set> 22 </class> 23 </hibernate-mapping>
b)role.hbm.xml
1 <hibernate-mapping> 2 3 <class name="com.st.bean3.RoleBean" table="T_ROLE"> 4 <id name="id" column="ID"> 5 <!-- class用于设置主键生成方式increment-自增长; assigned-指定的 --> 6 <generator class="increment"></generator> 7 </id> 8 <!-- 普通节点配置 --> 9 <property name="post" column="POST" type="java.lang.String" ></property> 10 <property name="pay" column="PAY" ></property> 11 12 <set name="user" table="user_role" cascade="save-update" inverse="false"> 13 <key column="ROLE_ID"></key> 14 <many-to-many class="com.st.bean3.UserBean" column="USER_ID"/> 15 </set> 16 </class> 17 </hibernate-mapping>
4、早hibernate.cfg.xml文件中引入步骤三种的两个配置文件:
1 <mapping resource="com/st/bean3/role.hbm.xml"/> 2 <mapping resource="com/st/bean3/user.hbm.xml"/>
5、在BeanTest类中编写测试代码
1 @Test 2 public void bean3test1(){ 3 // 获取一个会话 4 Session session = HibernateTools.openSession(); 5 //开启一次事物 6 Transaction tran = session.beginTransaction(); 7 UserBean user = new UserBean(); 8 RoleBean role = (RoleBean) session.get(RoleBean.class,3L); 9 // RoleBean role = new RoleBean(); 10 user.setName("陈泽俊"); 11 user.setSex("男"); 12 // role.setPost("单片机开发工程师"); 13 // role.setPay(9000); 14 role.getUser().add(user); 15 session.save(role); 16 //确认提交事物 17 tran.commit(); 18 } 19 @Test 20 public void bean3test2(){ 21 // 获取一个会话 22 Session session = HibernateTools.openSession(); 23 /* List<UserBean> list = session.createCriteria(UserBean.class).list(); 24 for(UserBean user : list) 25 System.out.println(user);*/ 26 String hql = "select new Map(u.name as name,u.sex as sex,r.post as post,r.pay as pay) from UserBean u join u.role r"; 27 List<Map<String,Object>> list = session.createQuery(hql).list(); 28 for(Map<String,Object> data : list) 29 System.out.println(data); 30 }
19:41:06