设为首页 收藏本站
查看: 693|回复: 0

[经验分享] 第1 章在Tomcat中快速上手

[复制链接]

尚未签到

发表于 2018-12-6 12:09:09 | 显示全部楼层 |阅读模式
  1.1. 开始Hibernate之旅
  这份教程描述如何在Apache Tomcat servlet容器中为web应用程序配置Hibernate 3.0(我们使用Tomcat 4.1版本,与5.0版本差别很小)。Hibernate在大多数主流J2EE应用服务器 的运行环境中都可以工作良好,甚至也可以在独立Java应用程序中使用。在本教程中使用的示例数据库系统是PostgreSQL 7.4,只需要修改Hibernate SQL语言配置与连接属性,就可以很容易的支持其他数据库了。

  第一步,我们必须拷贝所有需要的库文件到Tomcat安装目录中。在这篇教程中,我们使用一个独立的web Context配置(webapps/quickstart)。我们确认全局库文件(TOMCAT/common/lib)和本web应用程序上下文的路径(对于jar来说是webapps/quickstart/WEB-INF/lib,对于class文件来说是webapps/quickstart/WEB-INF/classes)能够被类装载器检索到。我们把这两个类装载器级别分别称做全局类路径(globalclasspath)和上下文类路径(context>  现在,把这些库文件copy到两个类路径去:

  •   把数据库需要的JDBC驱动文件拷贝到全局类路径,这是tomcat捆绑的DBCP连接池所需要的。Hibernate使用JDBC连接数据库方式执行SQL语句,所以你要么提供外部连接池中的连接给Hibernate,或者配置Hibernate自带的连接池(C3PO,Proxool)。对于本教程来说,把pg74jdbc3.jar库文件(支持PostgreSQL     7.4和JDK 1.4)到全局类装载路径下即可。如果你希望使用其他的数据库,拷贝其相应的JDBC 驱动文件)。
  •   永远不要拷贝任何其他东西到Tomcat的全局类路径下,否则你可能在使用其他一些工具上遇到麻烦,比如log4j,     commons-logging等等。 一定要让每个web应用程序使用自己的上下文类路径,就是说把你自己需要的类库拷贝到WEB-INF/lib下去,把配置文件configuration/property等配置文件拷贝到WEB-INF/classes下面去。这两个目录都是当前程序缺省的上下文类路径。
  •   Hibernate本身打包成一个JAR类库。将hibernate3.jar文件拷贝到程序的上下文类路径下,和你应用程序的其他库文件放一起。在运行时,Hibernate还需要一些第三方类库,它们在Hibernate发行包的lib/目录下。参见表1.1 “ Hibernate 第三方类库”。把所需要的第三方库文件也拷贝到上下文类路径下。
  1.1.  Hibernate 第三方类库
  类库
  描述
  antlr (必需)
  Hibernate使用ANTLR来产生查询分析器,这个类库在运行环境下时也是必需的。
  dom4j (必需)
  Hibernate使用dom4j解析XML配置文件和XML映射元文件。
  CGLIB ,asm(必需)
  Hibernate在运行时使用这个代码生成库增强类(与Java反射机制联合使用)。
  Commons Collections, Commons Logging (必需)
  Hibernat使用Apache Jakarta Commons项目提供的多个工具类库。
  EHCache (必需)
  Hibernate可以使用不同cache缓存工具作为二级缓存。EHCache是缺省的cache缓存工具。
  Log4j (可选)
  Hibernate使用Commons Logging API,它也可以依次使用Log4j作为底层实施log的机制。如果上下文类目录中存在Log4j库,则Commons Logging使用Log4j和并它在上下文类路径中寻找的log4j.properties文件。你可以使用在Hibernate发行包中包含中的那个示例Log4j的配置文件。这样,把log4j.jar和它的配置文件(位于src/目录中)拷贝到你的上下文类路径下,就可以在后台看到底程序如何运行的。
  其他文件是不是必需的?
  请察看Hibernate发行包中的 lib/README.txt文件,这是一个Hibernate发行包中附带的第三方类库的列表,他们总是保持最新的。你可以在那里找到所有必需或者可选的类库(注意:其中的"buildtime required"指的是编译Hibernate时所需要而非编译你自己的程序所必需的类库)。
  接下来我们来配置在Tomcat和Hibernate中共用的数据库连接池。也就是说Tomcat会提供经过池处理的JDBC连接(用它内置的DBCP连接池),Hibernate通过JNDI方式来请求获得JDBC连接。作为替代方案,你也可以让Hibernate自行管理连接池。Tomcat把连接池绑定到JNDI,我们要在Tomcat的主配置文件(TOMCAT/conf/server.xml)中加一个资源声明:
  
  
  
  
  factory
  org.apache.commons.dbcp.BasicDataSourceFactory
  
  
  
  url
  jdbc:postgresql://localhost/quickstart
  
  
  driverClassNameorg.postgresql.Driver
  
  
  username
  quickstart
  
  
  password
  secret
  
  
  
  maxWait
  3000
  
  
  maxIdle
  100
  
  
  maxActive
  10
  
  
  
  我们在这个例子中要配置的上下文叫做quickstart,它位于TOMCAT/webapp/quickstart目录下。如果要访问这个应用程序,在你的浏览器中输入http://localhost:8080/quickstart就可以了(当然,在后面加上在你的web.xml文件中配置好你的servlet)。你现在可以创建一个只含有空process()的简单servlet了。
  Tomcat现在通过JNDI的方式:java:comp/env/jdbc/quickstart来提供连接。如果你在配置连接池遇到问题,请查阅Tomcat文档。如果你遇到了JDBC驱动所报的exception出错信息,请在没有Hibernate的环境下,先测试JDBC连接池本身是否配置正确。Tomcat和JDBC的配置教程可以在Web上查到。
  下一步就是配置Hibernate。首先Hibernate必须知道它如何获得JDBC连接,在这里我们使用基于XML格式的Hibernate配置文件。当然使用properties文件的进行配置,但缺少一些XML语法的特性。这个XML配置文件必须放在上下文类路径(WEB-INF/classes)下面,命名为hibernate.cfg.xml:
  
  
  
  
  java:comp/env/jdbc/quickstart
  false
  org.hibernate.dialect.PostgreSQLDialect
  
  
  
  
  在这里我们关闭了SQL命令的log,同时告诉Hibernate使用哪种SQL数据库用语(Dialet),以及如何得到JDBC连接(通过Tomcat声明绑定的JNDI地址)。Dialet是必需配置的,因为不同的数据库都和"SQL标准"有一些出入。不用担心,Hibernate会替你处理这些差异,Hibernate支持所有主流的商业和开放源代码数据库。
  SessionFactory是Hibernate的一个概念,表示对应一个数据存储源。通过创建多个XML配置文件并在你的程序中创建多个Configuration和SessionFactory对象,就可以支持多个数据库了。
  在hibernate.cfg.xml中的最后一个元素声明了Cat.hbm.xml,这是一个Hibernate XML映射文件,对应于持久化类Cat。这个文件包含了把Cat POJO类映射到数据库表(或多个数据库表)的元数据。我们稍后就回来看这个文件。下一步让我们先编写这个POJO类,然后在声明它的映射元数据。
  1.2. 第一个持久化类
  Hibernate使用简单的Java对象(Plain Old Java Objects ,就是POJOs,有时候也称作Plain Ordinary Java Objects)这种编程模型来进行持久化。一个POJO很像JavaBean,通过getter和setter方法访问其属性,对外则隐藏了内部实现的细节(假若需要的话,Hibernate也可以直接访问其属性字段)。
  package org.hibernate.examples.quickstart;

  public>
  private String>  private String name;
  private char sex;
  private float weight;
  public Cat() {
  }
  public String getId() {

  return>  }

  private void setId(String>
  this.id =>  }
  public String getName() {
  return name;
  }
  public void setName(String name){
  this.name = name;
  }
  public char getSex() {
  return sex;
  }
  public void setSex(char sex) {
  this.sex = sex;
  }
  public float getWeight() {
  return weight;
  }
  public void setWeight(floatweight) {
  this.weight = weight;
  }
  }
  Hibernate对属性使用的类型不加任何限制。所有的Java JDK类型和原始类型(比如String,char和Date)都可以被映射,也包括Java 集合(Java collections framework)中的类。你可以把它们映射成为值,值集合,或者与其他实体类相关联。id是一个特殊的属性,代表了这个类的数据库标识符(主键),对于类似于Cat这样的实体类我们强烈建议使用。Hibernate也可以使用内部标识符,但这样我们会失去一些程序架构方面的灵活性。
  持久化类不需要实现什么特别的接口,也不需要从一个特别的持久化根类继承下来。Hibernate也不需要使用任何编译期处理,比如字节码增强操作,它独立的使用Java反射机制和运行时类增强(通过CGLIB)。所以不依赖于Hibernate,我们就可以把POJO的类映射成为数据库表。
  1.3. 映射cat
  Cat.hbm.xml映射文件包含了对象/关系映射(O/R Mapping)所需的元数据。元数据包含持久化类的声明和属性到数据库的映射(指向字段和其他实体的外键关联)。
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  每个持久化类都应该有一个标识属性(实际上,这个类只代表实体,而不是独立的值类型类,后者会被映射称为实体对象中的一个组件)。这个属性用来区分持久化对象:如果catA.getId().equals(catB.getId())结果是true的话,这两个Cat就是相同的。这个概念称为数据库标识。Hiernate附带了几种不同的标识符生成器,用于不同的场合(包括数据库本地的顺序(sequence)生成器、hi/lo高低位标识模式、和程序自己定义的标识符)。我们在这里使用UUID生成器(只在测试时建议使用,如果使用数据库自己生成的整数类型的键值更好),并指定CAT表中的CAT_ID字段(作为表的主键)存放生成的标识值。
  Cat的其他属性都映射到同一个表的字段。对name属性来说,我们把它显式地声明映射到一个数据库字段。如果数据库schema是通过由映射声明使用Hibernate的SchemaExport工具自动生成的(作为SQL DDL指令)的话,这就特别有用。所有其它的属性都用Hibernate的默认值映射,大多数情况你都会这样做。数据库中的CAT表看起来是这样的:
  Column |         Type          | Modifiers
  --------+-----------------------+-----------
  cat_id | character(32)         | not null
  name   | character varying(16) | not null
  sex    | character(1)          |
  weight | real                  |
  Indexes: cat_pkey primary key btree (cat_id)
  你现在可以在你的数据库中手工创建这个表了,如果你需要使用hbm2ddl工具把这个步骤自动化,请参阅第21 章工具箱指南。这个工具能够创建完整的SQL DDL,包括表定义,自定义的字段类型约束,惟一约束和索引。
  1.4. 与Cat同乐
  我们现在可以开始Hibernate的Session了。它是一个持久化管理器,我们通过它来从数据库中存取Cat。首先,我们要从SessionFactory中获取一个Session(Hibernate的工作单元)。
  SessionFactory sessionFactory =
  newConfiguration().configure().buildSessionFactory();
  通过对configure()的调用来装载hibernate.cfg.xml配置文件,并初始化成一个Configuration实例。 在创建 SessionFactory之前(它是不可变的),你可以访问Configuration来设置其他属性(甚至修改映射的元数据)。我们应该在哪儿创建SessionFactory,在我们的程序中又如何访问它呢?SessionFactory通常只是被初始化一次,比如说通过一个load-on-startup servlet的来初始化。这意味着你不应该在serlvet中把它作为一个实例变量来持有,而应该放在其他地方。进一步的说,我们需要使用单例(Singleton)模式,我们才能更容易的在程序中访问SessionFactory。下面的方法就同时解决了两个问题:对SessionFactory的初始配置与便捷使用。
  我们实现一个HibernateUtil辅助类:
  import org.hibernate.*;
  import org.hibernate.cfg.*;

  public>  private static Log log =LogFactory.getLog(HibernateUtil.class);
  private static finalSessionFactory sessionFactory;
  static {
  try {
  // Create theSessionFactory
  sessionFactory = newConfiguration().configure().buildSessionFactory();
  } catch (Throwable ex) {
  // Make sure you log theexception, as it might be swallowed
  log.error("InitialSessionFactory creation failed.", ex);
  throw newExceptionInInitializerError(ex);
  }
  }
  public static final ThreadLocalsession = new ThreadLocal();
  public static SessioncurrentSession()  {
  Session s = (Session)session.get();
  // Open a new Session, ifthis Thread has none yet
  if (s == null) {
  s =sessionFactory.openSession();
  session.set(s);
  }
  return s;
  }
  public static voidcloseSession() {
  Session s = (Session)session.get();
  if (s != null)
  s.close();
  session.set(null);
  }
  }
  这个类不但在它的静态初始器中使用了SessionFactory,还使用了一个ThreadLocal变量来保存Session做为当前工作线程。在你使用这个辅助类之前,请确保你理解了thread-local变量这个Java概念。你可以在CaveatEmptor(http://caveatemptor.hibernate.org/)上找到一个更加复杂和强大的HibernateUtil。
  SessionFactory是安全线程,可以由很多线程并发访问并获取到Sessions。单个Session不是安全线程对象,它只代表与数据库之间的一次操作。Session通过SessionFactory获得并在所有的工作完成后关闭。在你servlet的process()中可以象是这么写的(省略了异常情况处理):
  Session session = HibernateUtil.currentSession();
  Transaction tx= session.beginTransaction();
  Cat princess = new Cat();
  princess.setName("Princess");
  princess.setSex('F');
  princess.setWeight(7.4f);
  session.save(princess);
  tx.commit();
  HibernateUtil.closeSession();
  在一个Session中,每个数据库操作都是在一个事务(transaction)中进行的,这样就可以隔离开不同的操作(甚至包括只读操作)。我们使用Hibernate的Transaction API来从底层的事务策略中(本例中是JDBC事务)脱身出来。这样,我们就不需要更改任何源代码,就可以把我们的程序部署到一个由容器管理事务的环境中去(使用JTA)。
  这样你就可以随心所欲的多次调用HibernateUtil.currentSession();,你每次都会得到同一个当前线程的Session。不管是在你的servlet代码中,或者在servlet filter中还是在HTTP结果返回之前,你都必须确保这个Session在你的数据库访问工作完成后关闭。这样做还有一个好处就是可以容易的使用延迟装载(lazy initialization):Session在渲染view层的时候仍然打开着的,所以你在遍历当前对象图的时候可以装载所需的对象。
  Hibernate有不同的方法用来从数据库中取回对象。最灵活的方式就是使用Hibernate查询语言(HQL),这是一种容易学习的语言,是对SQL的面向对象的强大扩展。
  Transaction tx= session.beginTransaction();
  Query query = session.createQuery("select c from Cat as c where c.sex= :sex");
  query.setCharacter("sex", 'F');
  for (Iterator it = query.iterate(); it.hasNext();) {
  Cat cat = (Cat) it.next();
  out.println("Female Cat:" + cat.getName() );
  }
  tx.commit();
  Hibernate也提供一种面向对象的按条件查询API,可以执行简洁安全类型的查询。当然,Hibernate在所有与数据库的交互中都使用PrepatedStatement和参数绑定。你也可以使用Hibernate的直接SQL查询特性,或者在特殊情况下从Session获取一个原始的JDBC连接。
  1.5. 结语
  在这个短小的教程中,我们对Hibernate浅尝即止。请注意我们没有在例子中包含任何servlet相关代码。你必须自行编写servlet,并插入适合你的Hibernate代码。
  请记住Hibernate作为一个数据库访问层,是与你的程序紧密相关的。通常情况下,所有其他层次都依赖持久机制。请确信你理解了这种设计的内涵。
  若希望学习更复杂的例子,请参阅http://caveatemptor.hibernate.org/ 。在 http://www.hibernate.org/Documentation 也可以得到其他教程的链接。
  来自:http://docs.huihoo.com/hibernate/reference-v3_zh-cn/quickstart.html


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-643967-1-1.html 上篇帖子: tomcat集群和负载均衡 下篇帖子: apache2+tomcat5.5集群+session同步
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表