论坛首页 Java企业应用论坛

Hibernate 对象间关系映射从入门到精通(多对多关系)

浏览 12636 次
该帖已经被评为精华帖
作者 正文
   发表时间:2004-01-15  
Describe Hibernate 对象间关系映射从入门到精通(多对多关系) here. 下面来谈一下多对多的关系:以老师和学生的关系为例子:

    <class name="com.etech.bm.po.TeacherPO" table="TEACHER">
                <id name="id" column="ID" type="integer">
                        <generator class="identity"/>
                </id>
        <bag name="student" table="TEACHERSTUDENT" lazy="true" cascade="all">
                <key column="TEACHERID"/>
                <many-to-many class="com.etech.bm.po.StudentPO" column="STUDENTID"/>
        </bag>
    </class>
   <class name="com.etech.bm.po.StudentPO" table="STUDENT">
                <id name="id" column="ID" type="integer">
                        <generator class="identity"/>
                </id>
        <bag name="teacher" table="TEACHERSTUDENT" lazy="true" cascade="all>
                <key column="STUDENTID"/>
                <many-to-many class="com.etech.bm.po.TeacherPO" column="TEACHERID"/>
        </bag>
    </class>

由工具自动生成的dll为 drop table TEACHERSTUDENT;
drop table TEACHER;
drop table STUDENT;
create table TEACHERSTUDENT (TEACHERID INTEGER not null, STUDENTID INTEGER not null, primary key (TEACHERID, STUDENTID));
create table TEACHER (ID INTEGER not null generated by default as identity, primary key (ID));
create table STUDENT (ID INTEGER not null generated by default as identity, primary key (ID));
alter table TEACHERSTUDENT add constraint FKFE10D819307EFC76 foreign key (STUDENTID) references STUDENT;
alter table TEACHERSTUDENT add constraint FKFE10D8198B06785D foreign key (TEACHERID) references TEACHER;

程序                 ITxMgr tx = null;
                tx = HibernateTxMgr.beginTrans("Add a new relationships...");
                session = (Session) tx.getSession();
                student = new StudentPO();
                student1 = new StudentPO();
                List studentlist = new ArrayList();
                studentlist.add(student);
                studentlist.add(student1);
                teacher = new TeacherPO();
                teacher.setStudent(studentlist);
                session.save(teacher);
                session.flush();
                tx.endTrans();

生成的sql Hibernate: insert into TEACHER (ID) values (default)
Hibernate: insert into STUDENT (ID) values (default)
Hibernate: insert into STUDENT (ID) values (default)
Hibernate: insert into TEACHERSTUDENT (TEACHERID, STUDENTID) values (?, ?)

结果

C:\Myapp\SQLLIB\BIN>db2 select  * from student

ID
-----------
         34
         35
C:\Myapp\SQLLIB\BIN>db2 select *  from teacherstudent

TEACHERID   STUDENTID
----------- -----------
         21          34
         21          35
C:\Myapp\SQLLIB\BIN>db2 select *  from teacher

ID
-----------
         21


*但是如果我执行以下代码就会出错:

ITxMgr tx = null;
                tx = HibernateTxMgr.beginTrans("Add a new relationships...");
                session = (Session) tx.getSession();
                student = new StudentPO();
                student1 = new StudentPO();
                
                List studentlist = new ArrayList();
                studentlist.add(student);
                studentlist.add(student1);
                teacher = new TeacherPO();
                teacher.setStudent(studentlist);
                
                List teacherList = new ArrayList();
                teacherList.add(teacher);
                student.setTeacher(teacherList);
                
                session.save(teacher);
                session.flush();
                tx.endTrans();  

对照一开始的代码:多出了这么一段 List teacherList = new ArrayList();
                teacherList.add(teacher);
                student.setTeacher(teacherList);


出错信息 Hibernate: insert into TEACHER (ID) values (default)
Hibernate: values IDENTITY_VAL_LOCAL()
Hibernate: insert into STUDENT (ID) values (default)
Hibernate: values IDENTITY_VAL_LOCAL()
Hibernate: insert into STUDENT (ID) values (default)
Hibernate: values IDENTITY_VAL_LOCAL()
Hibernate: insert into TEACHERSTUDENT (TEACHERID, STUDENTID) values (?, ?)
Hibernate: insert into TEACHERSTUDENT (STUDENTID, TEACHERID) values (?, ?)
WARN [main] (JDBCExceptionReporter.java:38) - SQL Error: -803, SQLState: 23505
ERROR [main] (JDBCExceptionReporter.java:46) - [IBM][CLI Driver][DB2/NT] SQL0803N  INSERT 语句、UPDATE 语句或由 DELETE 语句导致的外键更新中的一个或多个值无效,因为由 "1" 标识的主键、唯一约束或者唯一索引将表 "BM.TEACHERSTUDENT" 的那些列限制为不能具有重复行。  SQLSTATE=23505

*显然由于两张表都在维护关系,所以有两个Hibernate: insert into TEACHERSTUDENT (TEACHERID, STUDENTID) values (?, ?)
Hibernate: insert into TEACHERSTUDENT (STUDENTID, TEACHERID) values (?, ?)

*所以这是一个应该重视的问题 *如果我现在决定由teacher来维护关系呢么我修改StudentPO map 文件加上inverse ="true" <hibernate-mapping>
    <class name="com.etech.bm.po.StudentPO" table="STUDENT">
                <id name="id" column="ID" type="integer">
                        <generator class="identity"/>
                </id>
        <bag name="teacher" table="TEACHERSTUDENT" inverse ="true" lazy="true" cascade="all">
                <key column="STUDENTID"/>
                <many-to-many class="com.etech.bm.po.TeacherPO" column="TEACHERID"/>
        </bag>
    </class>

</hibernate-mapping>

呢么我再执行刚才出错的呢一段

ITxMgr tx = null;
                tx = HibernateTxMgr.beginTrans("Add a new relationships...");
                session = (Session) tx.getSession();
                student = new StudentPO();
                student1 = new StudentPO();
                
                List studentlist = new ArrayList();
                studentlist.add(student);
                studentlist.add(student1);
                teacher = new TeacherPO();
                teacher.setStudent(studentlist);
                
                List teacherList = new ArrayList();
                teacherList.add(teacher);
                student.setTeacher(teacherList);
                
                session.save(teacher);
                session.flush();
                tx.endTrans();  

现在旧没问题了因为                 List teacherList = new ArrayList();
                teacherList.add(teacher);
                student.setTeacher(teacherList);


这一段代码没作用了.以下这段程序可以证明这一点                 ITxMgr tx = null;
                tx = HibernateTxMgr.beginTrans("Add a new relationships...");
                session = (Session) tx.getSession();
                student = new StudentPO();
                student1 = new StudentPO();
                
                List studentlist = new ArrayList();
                //studentlist.add(student);
                //studentlist.add(student1);
                teacher = new TeacherPO();
                //teacher.setStudent(studentlist);
                
                List teacherList = new ArrayList();
                teacherList.add(teacher);
                student.setTeacher(teacherList);
                
                session.save(teacher);
                session.flush();
                tx.endTrans();  

生成的sql Hibernate: insert into TEACHER (ID) values (default)

仅此一句,显然把student.setTeacher(teacherList);所做的努力是而不见!
*小结:inverse="true再关系的维护责任分配中十分重要,如何设置,就要看你的实际需要了 另外维护关系的一端相对于另一段来说就有点像父子关系了,维护关系的一端的save update delte 都有点像对父亲的操作

下面再来看看delete的情形

1)在没有inverse="true"的时候

ITxMgr tx = null;
                tx = HibernateTxMgr.beginTrans("Delete a relationships...");
                session = (Session) tx.getSession();
                session.delete(teacher);
                session.flush();
                tx.endTrans();  

生成的sql Hibernate: delete from TEACHERSTUDENT where STUDENTID=?
Hibernate: delete from TEACHERSTUDENT where TEACHERID=?
Hibernate: delete from STUDENT where ID=?
Hibernate: delete from TEACHER where ID=?

*看这里teacher维护着关系他就像父子关系中的父亲,techer被删除了,呢所有和teacher相关的信息都被删除了
*如果我让学生来维护关系,然后执行相同的代码会产生产生什么影响呢

<class name="com.etech.bm.po.TeacherPO" table="TEACHER">
                <id name="id" column="ID" type="integer">
                        <generator class="identity"/>
                </id>
        <bag name="student" table="TEACHERSTUDENT" inverse="true" lazy="true" cascade="all">
                <key column="TEACHERID"/>
                <many-to-many class="com.etech.bm.po.StudentPO" column="STUDENTID"/>
        </bag>
    </class>


ITxMgr tx = null;
                tx = HibernateTxMgr.beginTrans("Delete a relationships...");
                session = (Session) tx.getSession();
                session.delete(teacher);
                session.flush();
                tx.endTrans();  

*结果失败,为什么现在由学生来维护关系表,呢么当session.delete(teacher)的时候不去删除关系表,呢么关系表可能还存在对teacher的外键联系,造成删除失败 *多对多的关系一般是双向维护的,所以说如果是0..多 vs 0..多的时候 将cascade="save-update"delete的时候手动删除
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics