1 Hibernate的多对多又分为单相多对多和双向多对多,两者大同小异,产生的表结构基本相同,
中间表的外键映射:
不同的是单向能从一方通知获取一个定义为集合的字段获取另外一方的数据,而双向则均可以的。
2 单向映射,只在一方配置与中间表的关系,另一方不用配置。
2.1 一方的表结构及说明
所谓单向,即该对象可以通过添加的一个集合字段来获取另一方相关的数据。
关键字cascade说明:设置级联操作的级别,可能值有:
all: 所有情况下均进行关联操作,即save-update和delete。
none: 所有情况下均不进行关联操作。这是默认值。
save-update: 在执行save/update/saveOrUpdate时进行关联操作。
delete: 在执行delete 时进行关联操作。
all-delete-orphan: 当一个节点在对象图中成为孤儿节点时,删除该节点。比如在一个一对多的关系中,Student包含多个book,当在对象关系中删除一个book时,此book即成为孤儿节点。
比如在添加时:
Function f1 = new Function("","user_mag","userAction");
Function f2 = new Function("","role_mag","roleAction");
Role r1 = new Role();
r1.setName("admin");
r1.getFunctions().add(f1);
r1.getFunctions().add(f2);
session.save(r1);
如果不设置,将会报错:
object references an unsaved transient instance - save the transient instance before flushing: com.text.hibernate.pojo.Function
创建的两个Function对象的值没有插入到数据库中,而设置了cascade则将会级联添加相关的数据,不会出现role表中的功能数据在function表中不存在的情况,即外键约束异常,外键连接的数据不存在。
2.2 而另一方正常映射到表结构中。
生成的表结构如下:
2.3 存读取数据
存:
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Function f1 = new Function("","user_mag","userAction");
Function f2 = new Function("","role_mag","roleAction");
Function f3 = new Function("","sys_mag","sysAction");
Function f4 = new Function("","prev_mag","prevAction");
Role r1 = new Role();
r1.setName("admin");
r1.getFunctions().add(f1);
r1.getFunctions().add(f2);
r1.getFunctions().add(f3);
r1.getFunctions().add(f4);
Role r2 = new Role();
r2.setName("vip");
r2.getFunctions().add(f1);
r2.getFunctions().add(f2);
session.save(r1);
session.save(r2);
tx.commit();
读:
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Role role = (Role)session.get(Role.class, 1);
System.out.println(""+role.getName());
System.out.println("");
for(Iterator<Function> iter = role.getFunctions().iterator();
iter.hasNext();){
Function func = iter.next();
System.out.println(func.getName()+"---"+func.getCode());
}
tx.commit();
从一个集合字段中读取。
3 双向多对多
3.1 双向多对多与单向多对多类似,不同的是在另一方定义一个集合字段与配置信息,比如学生与课程,课程中添加一个集合字段表示哪些学生选择了该课程。
inverse说明:inverse的真正作用就是指定由哪一方来维护之间的关联关系。当一方中指定了“inverse=true”(默认),那么另外一方就有责任负责之间的关联关系。比如添加一个学生及选的课程,在course表配置文件中添加了inverse=”true”,关系将会由student来生成,如下:
session.beginTransaction();
Student stu01 = new Student();
stu01.setName("张三");
stu01.setPassword("123");
Course course01 = new Course();
course01.setName("语文");
Course course02 = new Course();
course02.setName("数学");
stu01.getCourses().add(course01);
stu01.getCourses().add(course02);
session.save(stu01);
执行 sql:
将会在student_course表中加关系记录,来连接student和course。所有的双向关联需要有一端被
设置为 inverse。在一对多中,他必须是设置在多的一方,而在多对多的关联中,你可以选择任意的一方。
3.2 存取方法与单向类似。
附文档中重要的说明:
1 所有的持久化类都要求有无参的构造器,因为Hibernate必须使用Java反射机制来为你创建对象。构造器的级别可以是private级别,
2 一个 Session 代表一个单线程的单元
操作,org.hibernate.SessionFactory 则是个线程安全的全局对象,只需要被实例化一次。
附报错及解决方案:
报错:Exception in thread “main” org.hibernate.HibernateException: No CurrentSessionContext configured!
原因,Hibernate配置文件中没有配置将当前工作单元绑定到当前执行我们应用程序的Java线程。
thread