首页 | 资讯动态 | linux基础 | 系统管理 | 网络管理 | 编程开发 | linux数据库 | linux相关 | linux认证 | 下载中心 | 专题
oklinux
 系统管理:中文环境 系统管理 桌面应用 内核技术 Linux基础:安装配置 常用命令 经验技巧 软件应用 Linux数据库:Mysql POSTGRE
 网络管理:网络安全 网络应用 Linux服务器 编程开发:PHP CC++ Python Perl SHELL 嵌入式开发 | PHP基础 PHP技巧 PHP应用 PHP文摘
 首页 linux资讯动态 Linux专题 | 其他Unix Linux解决方案 硬件相关 Linux认证 企业应用 Apache | 相关下载:资料 参考手册 服务器
 → 当前位置:首页>编程开发>java>正文

Java企业应用-Hibernate实战全解

OKLinux www.oklinux.cn 2006-08-10 来源:oklinux收集整理 romeobh    会员收藏 游客收藏

bromon原创 请尊重版权

  对象关系映射(Object Relative Mapping)简称ORM,是面向对象开发的一个热点,用来解决JDBC开发中手动进行OR映射的繁杂与不便。EJB中的实体Bean在这个领域是很著名的——既因为它的先进而著名,也因为它的低效而著名。有过实体Bean开发经验的人可能都会为实现远程接口造成的效率低下而头痛,在很多不大不小的项目中,使用实体Bean是否得不偿失,争论很大。一个轻量级的持久化方案也许能够解决一些问题,Hibernate应此而生。

  Hibernate是一个中间层,它的目的是把数据库中的关系通过一定的规则映射成为对象,让Java开发人员不用太多的考虑底层数据库的问题,只需要像通常情况下管理对象一样的管理数据。在关系数据库仍将持续占据市场的情况下,它很可观。在数据持久化领域,即便是轻量级的方案也会是复杂饶舌的,也许如同周杰伦的音乐一样不知所云。在学习它之前,最好先回想一下以前进行数据库开发中遇到的问题和不便,想想为什么需要一个持久化层,才能知道很多操作的目的是什么,以及为什么要这么干,在这个问题上我不想做更多的叙述,因为“长久以来……”这样的句式通常long(不好意思,打不出来)长,会对我的键盘和热情造成很大的磨损。如果让我写一本书,那么我会乐意去叙述什么是数据持久化,它有什么好处等等。废话少说,来了。

  首先需要配置环境,下载Hibernate 2.1(www.hibernate.org),把lib下的*.jar添加到classpath,你的数据库JDBC驱动程序也应该在classpath中。打开hibernate.properties,针对你使用的数据库,配置相应的信息,比如我使用的是MS SQL Server,配置如下:

## MS SQL Server

hibernate.dialect net.sf.hibernate.dialect.SQLServerDialect
hibernate.connection.driver_class com.microsoft.jdbc.sqlserver.SQLServerDriver
hibernate.connection.url jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=zizz
hibernate.connection.username sa
hibernate.connection.password

  其中很大部分是已经写好的,只需要取掉注释即可,我自己只是修改了数据库名称、帐号、密码。建立一个名为zizz的数据库备用。

  然后把这个文件拷贝到你的应用的根目录下。

  我们谈论了很多次映射,应该首先来看看这个映射是如何完成的。假设一个最简单的应用,写一个功能最单一的留言板,设计的数据有留言的编号、留言者名称、留言内容,还有留言时间。足够简单吧,换做是你打算怎么干?我猜你要首先建立一个数据库表格,名字也许叫做guestbook。No,这不是面向对象的方式,不妨首先从对象的角度来考虑。我们当然希望每一条留言都以对象的方式呈现,每个对象应该具有的属性有:id、author、content、time。偷个懒,没有画UML。下面这个类应该是很容易理解的:

//GuestBook.java
package org.bromon.zizz;

import java.util.*;

public class GuestBook
{
private int id;
private String author;
private String content;
private Calendar time;

private void setId(int id)
{
  this.id=id;
}
public int getId()
{
  return(id);
}

public void setAuthor(String author)
{
  this.author=author;
}
public String getAuthro()
{
  return(author);
}

public void setContent(String content)
{
  this.content=content;
}
public String getContent()
{
  return(content);
}

public void setTime(Calendar time)
{
  this.time=time;
}
public Calendar getTime()
{
  return(time);
}
}


  基本上是最简单的Bean了,如果觉得困难的话,请你先回火星等我。

  需要注意的是setId方法被指定为private,这是因为我希望用这个字段做主键,它最好由系统自动生成,所以不应该由用户来指定,这个方法专为Hibernate准备,所以是私有的。

  如何把这个类与数据库映射起来?看看Hibernate的魔法,使用一个XML文件来描述,它应该被命名为GuestBook.hbm.xml:

&lt ?xml version="1.0"? &gt
&lt !DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
        "' target=_blank &gthttp://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" &gt

&lt hibernate-mapping package="org.bromon.zizz" &gt
    &lt class name="GuestBook" table=”guestbook" lazy="true" &gt
        &lt id name="id" type="integer" unsaved-value="null" &gt
   &lt column name="id" sql-type="int" not-null="true"/ &gt
   &lt generator class="identity"/ &gt
  &lt /id &gt
        
  &lt property name="author" column="author" not-null="true" unique="false"/ &gt
&lt property name="content" column="content" not-null="true"/ &gt
  &lt property name="time" column="time" not-null="true"/ &gt
    &lt /class &gt
&lt /hibernate-mapping &gt

虽然有点陌生,但是很易读,仔细琢磨一下。

下面来编写我们的应用,它的功能是插入数据:

//Operate.java
package org.bromon.zizz;
import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;
import net.sf.hibernate.tool.hbm2ddl.*;
import java.util.*;

public class Operate
{
public static void main(String args[])
{
  try
  {
   Configuration cfg=new Configuration().addClass(GuestBook.class);
   SessionFactory sessions=cfg.buildSessionFactory();
   new SchemaExport(cfg).create(true,true);
   Session session=sessions.openSession();
   
   GuestBook gb=new GuestBook();
   gb.setAuthor(“Bromon”);
   gb.setContent(“留言的内容”);
   gb.setTime(Calendar.getInstance());
   
   Transaction ts=session.beginTransaction();
   session.save(gb);
   ts.commit();
   session.close();
  }catch(Exception e)
  {
   System.out.println(e);
  }
}
}
  编译吧:javac –d . *.java
  执行一下:java org.bromon.zizz.Operate

到数据库里面看看,表格已经建立好了,并且数据也已经保存。如果把

new SchemaExport().create(true,true);

注释掉,那么系统不会创建表格,而只是在已有的表格中添加新的记录,当然,如果表格不存在的话,会产生异常。

你已经看到了Hibernate神奇魔法的5%,它足够的复杂强大,可以让你应付复杂的应用。

one-to-one关系
在绝大多数系统当中不可能只存在一个数据表格,否则就违背了关系数据库的初衷。表与表的关系比较复杂,可以分为几种情况:

● 一对一关联(one to one)
● 一对多关联(one to many)
● 多对一关联(many to one)
● 多对多关联(many to many)

按顺序来讲。假设一个一对一关联的例子是:
表格:person
id 编号(主键)
name 姓名
email email地址

表格:spouse
id 编号(外键)
name 姓名

person这个表保存用户信息,而spouse保存用户配偶的信息。在一般情况下一个人只有一个配偶,这很适合我们一对一的情况。如果你对婚外恋感兴趣的话,我们可以在一对多和多对一的关联中讨论这个问题,也许还可以在多对多中^_^(禽兽!)。

OK,下面设计POJO:
Person这个类非常简单:

/*
* Created on 2004-4-19
*/
package org.bromon.zizz;

/**
* @author Bromon
*/
public class Person
{
private int id;
private String name;
private String email;

public void setId(int id)
{
  this.id=id;
}
public int getId()
{
  return(id);
}

public void setName(String name)
{
  this.name=name;
}
public String getName()
{
  return(name);
}

public void setEmail(String email)
{
  this.email=email;
}
public String getEmail()
{
  return(email);
}
}


然后编写它的映射规则,这个应该能够理解了:
&lt ?xml version="1.0"? &gt
&lt !DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"' target=_blank &gthttp://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" &gt  

&lt hibernate-mapping package="org.bromon.zizz" &gt
&lt class name="Person" table="person" lazy="true" &gt
&lt id name="id" type="integer" unsaved-value="null" &gt
&lt column name="id" sql-type="int" not-null="true"/ &gt
&lt generator class="identity"/ &gt
&lt /id &gt

&lt property name="name" column="name" not-null="true" unique="false"/ &gt
&lt property name="email" column="email" not-null="false"/ &gt
&lt /class &gt
&lt /hibernate-mapping &gt

so easy是不是?一切都按部就班。下面是Souse类:

/*
* Created on 2004-4-20
*/
package org.bromon.zizz;

/**
* @author Bromon
*/
public class Spouse
{
private int id;
private String name;
private Person person;

public void setId(int id)
{
  this.id=id;
}
public int getId()
{
  return(id);
}

public void setName(String name)
{
  this.name=name;
}
public String getName()
{
  return(name);
}

public void setPerson(Person person)
{
  this.person=person;
}
public Person getPerson()
{
  return(person);
}
}


注意里面的域person。它的映射文件:

&lt ?xml version="1.0"? &gt
&lt !DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"' target=_blank &gthttp://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" &gt  

&lt hibernate-mapping package="org.bromon.zizz" &gt
&lt class name="Spouse" table="spouse" lazy="true" &gt
&lt id name="id" type="integer" unsaved-value="null" &gt
&lt column name="id" sql-type="int" not-null="true"/ &gt
&lt generator class="foreign" &gt
&lt param name="property" &gtperson&lt /param &gt
&lt /generator &gt
&lt /id &gt

&lt property name="name" column="name" not-null="true" unique="false"/ &gt
&lt one-to-one name="person" class="Person" cascade="all" constrained="true" / &gt
&lt /class &gt
&lt /hibernate-mapping &gt

这里指明了id的generator是一个外键,和person相关联。然后指定一个one-to-one关系,不难理解是不是?Hibernate的确很符合我们的思维习惯。需要提醒的是,这种关联关系是单向的,Person并不需要去指定Spouse。

下面来操作这两个类:

/*
* Created on 2004-4-20
*/
package org.bromon.zizz;
import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;
import net.sf.hibernate.tool.hbm2ddl.*;
/**
* @author Bromon
*/
public class OperateSpouse
{
public static void main(String args[])
{
  try
  {
   Configuration cfg=new Configuration().addClass(Spouse.class);
   cfg.addClass(Person.class);
   SessionFactory factory=cfg.buildSessionFactory();
   new SchemaExport(cfg).create(true,true);
   Session session=factory.openSession();
  
   Person person=new Person();
   person.setName("bromon");
   person.setEmail("[email protected]");
  
   Spouse spouse=new Spouse();
   spouse.setName("who");
   spouse.setPerson(person);
   
   Transaction ts=session.beginTransaction();
   session.save(person);
   session.save(spouse);
   ts.commit();
   session.close();
  }catch(Exception e)
  {
   System.out.println(e);
  }
}
}


这个例子和第一篇中的例子非常相似。OK,执行一下,然后看看zizz数据库,搞掂。

Many-to-One关系

很明显一对多或者多对一关系是关系数据库中非常常见的现象,下面通过父亲-儿子的例子来演示一对多关系,多对一关系是类似的,不过在我们的这个例子中不宜采用,否则会带来伦理学上的问题。

首先定义Child类:
/*
  * Created on 2004-5-8
  */
package org.bromon.zizz;

/**
  * @author Bromon
  */
public class Child
{
  private int id;
  private String name;
  private int fatherId;
  private Person father;

  public Child(){}
  
  /**
   * @return
   */
  public Person getFather()
  {
   return father;
  }

  /**
   * @return
   */
  public int getFatherId()
  {
   return fatherId;
  }

  /**
   * @return
   */
  public int getId()
  {
   return id;
  }

  /**
   * @return
   */
  public String getName()
  {
   return name;
  }

  /**
   * @param person
   */
  public void setFather(Person p)
  {
   father = p;
  }

  /**
   * @param i
   */
  public void setFatherId(int i)
  {
   fatherId = i;
  }

  /**
   * @param i
   */
  public void setId(int i)
  {
   id = i;
  }

  /**
   * @param string
   */
  public void setName(String string)
  {
   name = string;
  }

}

这里的fatherId是外键,关联person表的id字段。

下面是映射文件Child.hbm.xml:
&lt ?xml version="1.0"? &gt
&lt !DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
        "' target=_blank &gthttp://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" &gt  

&lt hibernate-mapping package="org.bromon.zizz" &gt
  &lt class name="Child" table="child" lazy="true" &gt
   &lt id name="id" type="integer" unsaved-value="null" &gt
    &lt column name="id" sql-type="int" not-null="true"/ &gt
    &lt generator class="identity"/ &gt
   &lt /id &gt
        
   &lt property name="name" column="name" not-null="true" unique="false"/ &gt
   &lt many-to-one name="father" column="fatherid" / &gt
      
  &lt /class &gt
&lt /hibernate-mapping &gt
需要注意的是fatherId并没有做为一个property被映射,而是在many-to-one声明中使用。

需要对Person..java做修改,添加以下代码:

import java.util.*;

private Set children=new HashSet();
/**
* @return
*/
public Set getChildren()
{
  return children;
}
/**
* @param set
*/
public void setChildren(Set set)
{
  children = set;
}

然后修改Person.hbm.xml,对添加的代码做映射:

&lt set name="books" lazy="true" inverse="true" cascade="all"  &gt
  &lt key column="fatherid"/ &gt
  &lt one-to-many class="Child" / &gt
&lt /set &gt

这里的key column是child表的外键,inverse需要指定为true。

下面做操作一下,功能是查询person表中id=1的记录,作为小孩的父亲,然后给child表添加一条新记录。

/*
  * Created on 2004-5-8
  */
package org.bromon.zizz;
import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;
import net.sf.hibernate.tool.hbm2ddl.*;
/**
  * @author Bromon
  */
public class OperateChild
{
  /**
   * @param args
   */
  public static void main(String args[])
  {
   try
   {
    Configuration cfg = new Configuration().addClass(Person.class);
    cfg.addClass(Child.class);
    SessionFactory sessions = cfg.buildSessionFactory();
    new SchemaExport(cfg).create(true, true);
    Session session = sessions.openSession();
   
    Child c=new Child();
   
    /*Query q=session.createQuery("from org.bromon.zizz.Person as p where p.id=1");
    Person p=(Person)q.list().get(0);*/
   
    Person p=(Person)session.find("from org.bromon.zizz.Person as p where p.id=?",new Integer(1),Hibernate.INTEGER).get(0);
    System.out.println(p.getName());
    c.setName("andy");
    c.setFather(p);
   
    Transaction ts = session.beginTransaction();
    session.save(c);
    ts.commit();
    session.close();
   } catch (Exception e)
   {
    System.out.println(e);
   }
  }
}

被注释掉的部分是HQL的另外一种查询方法。在这个例子中可以看出对象的查询非常容易,不需要自己再去封装数据,修改和删除对象也很容易:

//得到一个对象
Query q=session.createQuery("from org.bromon.zizz.Person as p where p.id=1");
Person p=(Person)q.list().get(0);

//修改数据
p.setName(“Mr Smith”);

//保存数据
session.save(p);
session.flush();

//删除数据
session.delete(p);
session.flush();
上一篇:JAVA基础:谈谈Java语言的垃圾收集器   下一篇:诊断Java代码:设计轻松的代码维护

收藏于收藏夹】 【评论】 【推荐】 【投稿】 【打印】 【关闭

相关文章
·JAVA基础:谈谈Java语言的垃圾收集器
·诊断Java代码:设计轻松的代码维护
·你应该知道的10件关于Java 6的事情
·Java多线程程序设计详细解析
·java基础入门之Hibernate 入门
·提高Java代码可重用性的三个措施
·Java常见问题集锦来自 Sun中国官方站
·JAVA基础:JAVA几个常见错误简析
·JAVA基础:Java程序的脏数据问题
·JAVA基础:初学Java注意什么?
发表评论
密码: 匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。)
站内搜索
阅读排行榜
·Linux 上的 WebSphere MQ
·AspectJ学习笔记之Pointcu
·设定执行Java程序的Linux
·spring中对hibernate的支
·算法--数据结构--图的多重
·Gcc使用的内嵌汇编语法格
·最新visual c++6.0视频教
·c++ builder视频教程
·Linux系统中安装JAVA JDK.
·JAVA 视频教学
最新文章
·Linux系统中安装JAVA JDK.
·Linux下运行JAVA程序 JRE
·设定执行Java程序的Linux
·Linux 上的 WebSphere MQ
·spring中对hibernate的支
·AspectJ学习笔记之Pointcu
·下载 程序员全集
·[转载]你该学什么程序语言
·JAVA初学者入门教学
·JAVA 视频教学
·JAVA代码编写的30条建议!
·使用Vi编辑器
·C++视频教程《下载》
·程序员的七种武器
·Java与C的不同点$$$$

设为首页 - 加入收藏 - 版权声明 - 广告服务 - 关于我们 - 联系我们 - 友情连接
Copyright © 2007 All rights reserved OKLinux.Cn 版权所有