什么是一对多,多对一?
一对多,比如你去找一个父亲的所有孩子,孩子可能有两个,三个甚至四个孩子. 这就是一对多 父亲是1 孩子是多
多对一,比如你到了两个孩子,它们都是有一个共同的父亲. 此时孩子就是多 父亲是1
总结:
- 一对多就是: 1找到n
- 多对一就是: n找到1
有些人写概念写一大堆搞起我之前是一脸懵逼,还好弄懂了(手动滑稽)
双向多对一和双向一对多是不是同一个概念?
是一个概念,双向多对一和双向一对多都是配置一个 一对多和多对一
什么是双向多对多?
可以理解为n找n,如项目可以有很多人做,1个人可以做多个项目.
配置单向多对一
通过上面我们可以了解,双向一对多是 1找n,因为区县有总有很多街道,虽然有的街道没有名字(滑稽),下面我将拿街道和区县举例,实体类的getset我就省略了
//编号 private Integer id; //街道名称 private String name; //所属区县编号 private Integer district_Id; //所属区县 private District district;
因为要找所属区县,所以就增加了一个类类型的变量.
我们来看下配置完后是否可以查询到区县
dao层
public Street findDistrct(Serializable id){ return (Street)HibernateUtil.currentSession().get(Street.class,id); }
service层
public Street getStreet(Integer id){ Transaction tx=null; Street streets=null; try { tx=HibernateUtil.currentSession().beginTransaction(); //获取持久对象 注意这里没 commit() 因为延迟加载的原因所以没有commit streets = street.findDistrct(id); } catch (HibernateException e) { e.printStackTrace(); if(tx!=null) tx.rollback(); } return streets; }
测试
StreetServiceImpl streetService = new StreetServiceImpl();System.out.println(streetService.getStreet(1001).getDistrict().getName());
结果:
配置双向一对多
实体类属性 多了一个set因为是 1找n 所以是一个set因为set不允许重复值
//编号 private Integer id; //区县名称 private String name; //街道 private SetstreetSet;
双向多对一就是在上面的基础上加了个一对多即成了双向,
配置完1找n后我们再来查询下
dao层
public District getDistrct(Integer id){ return (District)HibernateUtil.currentSession().get(District.class,id); }
service层
public SetfindStreet(Integer id){ Transaction tx=null; Set streets=null; try { tx=HibernateUtil.currentSession().beginTransaction(); //得到持久状态的对象 District distrct = distrctDao.getDistrct(id); //得到set streets=distrct.getStreetSet(); } catch (HibernateException e) { e.printStackTrace(); if(tx!=null) tx.rollback(); } return streets; }
测试
DistrctServiceImpl ds = new DistrctServiceImpl();IteratorstreetIter = ds.findStreet(1004).iterator();while (streetIter.hasNext()){ System.out.println(streetIter.next().getName());}
数据库的数据
结果
对双向一对读关联进行更新
dao 层
public Street findDistrct(Serializable id){ return (Street)HibernateUtil.currentSession().get(Street.class,id); }
service层 这里为了快点就没传参了 直接调用即可
public void updateStreet(){ Transaction tx=null; try { //打开事务 tx=HibernateUtil.currentSession().beginTransaction(); //获得持久层对象 Street streets = street.findDistrct(1000); //对区县进行修改 streets.getDistrict().setName("京城"); //提交事务 tx.commit(); } catch (HibernateException e) { e.printStackTrace(); if(tx!=null) tx.rollback(); }}
我们来看看数据库没运行之前
运行之后 可以看到 知春路所属的区县改变了
双向多对多
下面将用项目和员工之间的关系进行配置,因为项目表和员工表需要互相关联,如果两个表直接关联会导致数据有冗余,最重要的是因为相互关联会导致不能删除数据
可以看到这样关联是十分的不好的,这时候我们就可以找一个中间商,进行中转通过它可找到两个表的数据
注意中间商不用建实体类
项目实体类属性如下
//编号 private Integer empId; //员工名 private String empName; //开发过的项目 private Setprojects;
项目配置
员工实体类属性
//编号private Integer id;//项目名称private String proName;//工作人员private Setemployees;
员工配置
配置完了进行添加如下
dao层
public void add(Project project){ HibernateUtil.currentSession().save(project); }
service层
public void add(Project project){ Transaction tx=null; try { //打开事务 tx=HibernateUtil.currentSession().beginTransaction(); //保存 empDao.add(project); //提交 tx.commit(); } catch (HibernateException e) { e.printStackTrace(); if (tx!=null) //回滚 tx.rollback(); }}
测试
//创建项目Project project = new Project(3,"项目3");//创建员工Employee employee = new Employee();Setemployees = new HashSet<>();employees.add(employee);employee.setEmpName("王麻子");//添加员工 到项目中project.setEmployees(employees);//添加项目 保存到数据库empSerivce.add(project);
没添加之前
运行后
因为控制权给了项目,在员工中进行如上操作对数据库中的项目表并不会进行改动,但是可以查询到如下
dao层
public Employee get(Serializable id){ return (Employee)HibernateUtil.currentSession().get(Employee.class,id);}
service层
EmpDao empDao =new EmpDao(); public Employee get(Integer id){ Transaction tx = null; Employee emp = null; try { //打开事务 tx=HibernateUtil.currentSession().beginTransaction(); //获取持久化对象 emp = empDao.get(id); } catch (HibernateException e) { e.printStackTrace(); } return emp; }
测试
EmpSerivce empSerivce = new EmpSerivce(); Employee emp = empSerivce.get(1); //员工名 System.out.println(emp.getEmpName()); //迭代器 Iteratoriterable = emp.getProjects().iterator(); //遍历 做过的项目 while (iterable.hasNext()){ System.out.println(iterable.next().getProName()); }
结果
工具类代码如下:
package tool; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateUtil { private static Configuration configuration; private static SessionFactory sessionFactory; //初始化配置和session static { try { //读取配置文件 try { configuration = new Configuration().configure(); //获取session对象 sessionFactory =configuration.buildSessionFactory(); } catch (HibernateException e) { e.printStackTrace(); } } catch (HibernateException e) { throw new ExceptionInInitializerError(); } } private HibernateUtil(){} //获取session对象 public static Session currentSession(){ return sessionFactory.getCurrentSession(); } }