« | August 2025 | » | 日 | 一 | 二 | 三 | 四 | 五 | 六 | | | | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | | | | | | | |
|
公告 |
用努力之心改变自己能改变的,
用宽容之心适应自己不能改变的,
心灵的春天将永远与你相伴!
Javaers!Let' s GO!!

|
统计 |
blog名称:春天俱乐部 日志总数:24 评论数量:21 留言数量:1 访问次数:180609 建立时间:2005年7月12日 |
| 
|
本站首页 管理页面 写新日志 退出
[J2EE]Hibernate 学习笔记 |
转载:转载请保留本信息,本文来自http://www.matrix.org.cn/resource/article/1649_hibernate的总结.html 一 hibernate配置1.下载所需包下载hibernate2.13, hibernate-extension2.13,Middlegen(已装了jdk和ant)2.创建数据库(例子:student;course,stu_cou)Student(id,name)Course(id,name)Stu_cou(stu_id,cou_id)(分别是student表和course表的外健)3.使用MiddleGen(见附录)二 hibernate映射关系(many-to-many)1. 分析inverse参数(student.hbm.xml course.hbm.xml)inverse该参数用来负责映射之间的关系,设置为false的一方可以对他们的关系进行维护设置inverse = false的实体,表示在映射中是它是主动关系,由它来维户关系中的数据设置inverse = true 的实体,表示在映射中是它是被动关系,它不维护关系中的数据1) inverse=false的情况a) 添加记录的情况student.hbm.xml是主动方,由它来决定stu_cou表中的记录,故inverse=false当向stu_cou中写入记录时候,/** 测试目的:在stu_cou中添加一组对应关系(student,course)* 测试结果:当执行完该段代码后* 如stu_cou中没有(student,course)时,自动加入(student,course)* 如stu_cou中存在(student,course)时,什么都不作,不会存在主健冲突Student student=(Student)session.load(Student.class,student2.getId())Course course=(Course)session.load(Course.class,course2.getId());student.getCourses().add(course);session.save(student);执行完后,hibenrate成功显示Hibernate: select course0_.id as id0_, course0_.name as name0_ from course course0_ where course0_.id=?Hibernate: select student0_.id as id0_, student0_.name as name0_ from student student0_ where student0_.id=?Hibernate: select courses0_.cid as cid__, courses0_.sid as sid__ from stu_cou courses0_ where courses0_.sid=?Hibernate: insert into stu_cou (sid, cid) values (?, ?)b) 删除记录的情况Student student=(Student)session.load(Student.class,student2.getId())Course course=(Course)session.load(Course.class,course2.getId());student.getCourses().让remove(course);session.save(student);代码执行完后,可以成功执行,hibernate显示:Hibernate: select course0_.id as id0_, course0_.name as name0_ from course course0_ where course0_.id=?Hibernate: select student0_.id as id0_, student0_.name as name0_ from student student0_ where student0_.id=?Hibernate: select courses0_.cid as cid__, courses0_.sid as sid__ from stu_cou courses0_ where courses0_.sid=?Hibernate: delete from stu_cou where sid=?2) inverse=true的情况student.hbm.xml是被动方,设置它的inverse=truea) 添加记录情况* 测试目的:在stu_cou中添加一组对应关系(student,course)* 测试结果:当执行完该段代码后* 如stu_cou中没有(student,course)时,自动加入(student,course)* 如stu_cou中存在(student,course)时,什么都不作,不会存在主健冲突Student tudent=(Student)session.load(Student.class,student2.getId());Course course=(Course)session.load(Course.class,course2.getId());student.getCourses().add(course);session.save(student);代码执行完后,hibernate显示,没有插入记录Hibernate: select course0_.id as id0_, course0_.name as name0_ from course course0_ where course0_.id=?Hibernate: select student0_.id as id0_, student0_.name as name0_ from student student0_ where student0_.id=?Hibernate: select courses0_.cid as cid__, courses0_.sid as sid__ from stu_cou courses0_ where courses0_.sid=?b) 删除记录情况当向stu_cou中删除记录时候,Student student=(Student)session.load(Student.class,student2.getId())Course course= (Course)session.load(Course.class,course2.getId());student.getCourses().remove(course);session.save(student);执行完,hibernate显示如下,证明没有删除记录Hibernate: select course0_.id as id0_, course0_.name as name0_ from course course0_ where course0_.id=?Hibernate: select student0_.id as id0_, student0_.name as name0_ from student student0_ where student0_.id=?Hibernate: select courses0_.cid as cid__, courses0_.sid as sid__ from stu_cou courses0_ where courses0_.sid=?Hibernate: select course0_.id as id0_, course0_.name as name0_ from course course0_ where course0_.id=?Hibernate: select course0_.id as id0_, course0_.name as name0_ from course course0_ where course0_.id=?2. 分析cascade参数(student.hbm.xml course.hbm.xml)只有设置了inverse=false才可以操纵stu_cou的数据当inverse=true的时候,下列情况1中b)提示错误原因: stu_cou中存在外健约束,你无法直接删除student表中的数据1) cascade=save-update的情况a)添加记录情况Set set=new HashSet();set.add(course1);set.add(course2);set.add(course3);student3.setCourses(set);session.save(student3);执行后hibernate提示:Hibernate: insert into student (name) values (?)Hibernate: insert into course (name) values (?)Hibernate: insert into course (name) values (?)Hibernate: insert into course (name) values (?)Hibernate: insert into stu_cou (sid, cid) values (?, ?)可见,插入了student,course,和stu_cou三个表b)删除记录情况Student student=(Student)session.load(Student.class,new Integer(22));session.delete(student);成功执行后,hibernate提示:Hibernate: select student0_.id as id0_, student0_.name as name0_ from student student0_ where student0_.id=?Hibernate: delete from stu_cou where sid=?Hibernate: delete from student where id=? 2) cascade=all的情况a) 添加记录情况Set set=new HashSet();set.add(course1);set.add(course2);set.add(course3);student3.setCourses(set);session.save(student3);执行后hibernate提示:成功添加级联关系Hibernate: insert into student (name) values (?)Hibernate: insert into course (name) values (?)Hibernate: insert into course (name) values (?)Hibernate: insert into course (name) values (?)Hibernate: insert into stu_cou (sid, cid) values (?, ?)b) 删除记录情况Student student=(Student)session.load(Student.class,new Integer(22));session.delete(student);测试结果(所有和student(22)相关的记录均被删除)删除student表中的student(22)记录删除stu_cou表中的student(22)的记录删除course表中的student(22)对应的course的记录2) cascade=none情况a) 添加记录情况Set set=new HashSet();set.add(course1);set.add(course2);set.add(course3);student3.setCourses(set);session.save(student3);失败,因为没有级联关系,所以course记录添加不进去,造成外健失败b) 删除记录情况Student student=(Student)session.load(Student.class,new Integer(22));session.delete(student);正常,删除了student表中的记录student(22),同时删除了stu_cou中对应的student(22)的记录附录1.MiddleGen的使用1环境变量设置%Hibernate_Home%/lib/*.jar到%MiddleGen%/lib下%Hibernate_Home%/hibernate2.jar到%MiddleGen%/lib下%Hibernate-Extension_Home%/tools/lib/*.jar到%MiddleGen%/lib下%Hibernate-Extension_Home%/tools/hibernate-tools.jar到%MiddleGen%/lib下2 MiddleGen的配置配置目标数据库参数进入MiddleGen 目录下的\config\database 子目录,根据我们实际采用的数据库打开对应的配置文件。如这里我用的是mysql数据库,对应的就是mysql.xml文件。<propertyname="database.script.file" value="${src.dir}/sql/${name}-mysql.sql"/><property name="database.driver.file" value="${lib.dir}/mysql.jar"/><propertyname="database.driver.classpath" value="${database.driver.file}"/><propertyname="database.driver" value="org.gjt.mm.mysql.Driver"/><propertyname="database.url" value="jdbc:mysql://localhost/sample"/><propertyname="database.userid" value="user"/><propertyname="database.password" value="mypass"/><propertyname="database.schema" value=""/><propertyname="database.catalog" value=""/><propertyname="jboss.datasource.mapping" value="mySQL"/>其中下划线标准的部分是我们进行配置的内容,分别是数据url以及数据库用户名和密码。1) 修改Build.xml修改MiddleGen 根目录下的build.xml 文件,此文件是Middlegen-Hibernate 的Ant构建配置。Middlegen-Hibernate将根据build.xml文件中的具体参数生成数据库表映射文件。可配置的项目包括:a) 目标数据库配置文件地址查找关键字 ”!ENTITY”,得到:<!DOCTYPE project [<!ENTITY database SYSTEM"file:./config/database/hsqldb.xml">]>默认情况下,MiddleGen 采用的是hsqldb.xml,将其修改为我们所用的数据库配置文件(mysql.xml):<!DOCTYPE project [<!ENTITY database SYSTEM"file:./config/database/mysql.xml">]>b) Application name查找:<property name="name" value="airline"/>“aireline”是MiddleGen原始配置中默认的 Application Name,将其修改为我们所希望的名称,如“HibernateSample”:<property name="name" value="HibernateSample"/>c) 输出目录查找关键字“name="build.gen-src.dir"”,得到:<property name="build.gen-src.dir"value="${build.dir}/gen-src"/>修改value="${build.dir}/gen-src"使其指向我们所期望的输出目录,这里我们修改为:<property name="build.gen-src.dir"value="C:\sample"/>d) 对应代码的Package name查找关键字“destination”,得到:<hibernatedestination="${build.gen-src.dir}"package="${name}.hibernate"genXDocletTags="false"genIntergratedCompositeKeys="false"javaTypeMapper="middlegen.plugins.hibernate.HibernateJavaTypeMapper"/>可以看到,hibernate 节点package 属性的默认设置实际上是由前面的Application Name (${name})和“.hibernate”组合而成,根据我们的需要,这里还有一个属性genXDocletTags,如果设置为true,则生成的代码将包含xdoclet tag,这为以后在开发过程中借助xdoclet进行映射调整提供了帮助。注意,如果使用的数据库为SQLServer,需要将build.xml部分删除(参见夏?^的文档),否则Middlegen会报出找不到表的错误。至此为止,MiddleGen 已经配置完毕,在MiddleGen 根目录下运行ant,就将出现MiddleGen的界面:2 *.xml到.java在得到.xml后,使用ant hbm2java 即可得到相应的java文件总结:我第一次运行成功,但是后来则出现如下类似错误,检查发现在MiddleGen的lib目录下存在多个类似的jar包(velocity.jar,velocity1-0.8.jar),删除旧的jar包后,问题解决[middlegen] java.lang.IncompatibleClassChangeError[middlegen] at [middlegen] at org.apache.velocity.Template.process(Template.java:136)2.(评论)关于Many-to-Many需要注意的问题比如group/user,user/role,group/role,都是多对多的关系。所以有必要搞搞清楚。以group/user为例(1)group.getUsers() & user.getGroups()双向映射。在这里,考虑到user.setGroups()是不会放出来的。所以在user端加入inverse=true,就是说,让Group端来维护两者的关系表。(2)于是,添加的时候,要把user加入到group的user set中,保存,才有意义!(3)如果要删除group_user的关系,而不是group/user本身,那么,需要在group端设定casade=save-update。否则,group.getUsers().remove(user)不会起作用!(4)由于有了FK保护,你是无法单独删除User的。同时,由于你指定了inverse=true,所以无法光光的设置user.getGroups().clear就能够搞定一切。你必须首先在每个Group.getUsers中删除这个user,才能最后删除。所以,UserManagerImpl代码可能看起来像这样:public void delUser(User user) {if (user == null) {logger.info("Got a null user object!");return;}Session session = null;Transaction trans = null;boolean bSuccess = false;try {String username = new String(user.getName());session = PLUtils.getSession();trans = session.beginTransaction();session.update(user);Set groups = ((UserEntity)user).getGroups(); for(Iterator i = groups.iterator();i.hasNext();){GroupEntity g = (GroupEntity)i.next();session.update(g);g.getUsers().remove(user);session.update(g);}// ((UserEntity)user).getGroups().clear();session.delete(user);bSuccess = true;logger.debug("User " + username + " deleted ok!");}catch (ObjectNotFoundException onfe) {logger.info("user not found!", onfe);}catch (Exception e) {logger.error("failed!", e);}finally {try {if (bSuccess)trans.commit();elsetrans.rollback();session.close();}catch (Exception ex) {}}}
|
阅读全文(4360) | 回复(-1) | 编辑 | 精华 |
|