Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 278|回复: 0

[Java框架学习]Hibernate起步(1)

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-11-7 00:01:35 | 显示全部楼层 |阅读模式
    创建一个命令行为基础的简单的java应用程序,利用Hibernate持久化java对象。
    一、准备工作
    1. 安装Java SDK 5.0 or 6.0
    2. 下载Hibernate3(http://www.hibernate.org)
    3. 安装mysql数据库
    4. 将Hibernate的jar包拷贝到工作目录c:worklib下,mysql的驱动程序mysql-connector-java-3.1.10-bin.jar也拷入这个目录,hibernate必须的jar包如下:
       antlr.jar
       cglib.jar
       asm.jar
       asm-attrs.jars
       commons-collections.jar
       commons-logging.jar
       hibernate3.jar
       jta.jar
       dom4j.jar
       log4j.jar  
      
       
       
         
       

         
       
      
       5.编译用的批处理文件h.bat:
    set classpath=.;c:worklibhibernate3.jar;c:worklibmysql-connector-java-3.1.10-bin.jar;c:worklibcommons-logging-1.0.4.jar;c:worklibdom4j-1.6.1.jar;c:worklibcommons-collections-2.1.1.jar;c:worklibc3p0-0.9.1.jar;c:worklibasm.jar;c:worklibcglib-2.1.3.jar;c:worklibjta.jar;c:worklibantlr-2.7.6.jar
    二、要持久化的java对象 创建第一个JavaBean类:代码如下:
    1. package events;
    2. import java.util.*;
    3. public class Event {
    4.     private Long id;
    5.     private String title;
    6.     private Date date;
    7.     public Event() {}
    8.     public Long getId() {
    9.         return id;
    10.     }
    11.     private void setId(Long id) {
    12.         this.id = id;
    13.     }
    14.     public Date getDate() {
    15.         return date;
    16.     }
    17.     public void setDate(Date date) {
    18.         this.date = date;
    19.     }
    20.     public String getTitle() {
    21.         return title;
    22.     }
    23.     public void setTitle(String title) {
    24.         this.title = title;
    25.     }
    26. }
    复制代码
    这就是一个简单的JavaBean,包含一些private属性和public方法,其中对于Hibernate有以下特点:
    Hibernate可以直接存取私有属性。
    id属性包含一个唯一的标志符。所有的持久化类对象都有一个唯一的标记符。事实上,很多应用程序都是通过标志来识别对象的。由于我们不会手动的管理id的值,所以setId方法被设置为private。
      所有的持久化类都需要一个不带参数的构造函数,Hibernate需要通过Java Reflection来创建实例。 三、Hibernate映射:
    Hibernate需要知道如何加载和存储持久化的类,这就是Hibernate映射需要完成的工作。映射文件告诉Hibernate该使用数据库中的哪个表,以及表中的列。
    基本的Hibernate映射文件结构如下: <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

    <hibernate-mapping>
    ...
    </hibernate-mapping> ...  实际上,Hibernate映射的定义非常复杂,可以通过一些DTD工具进行查看DTD文件,该文件中包含了一些注释,可以帮助理解映射文件的内容。注意,Hibernate并不从网络中加载DTD文件,而是首先从classpath中寻找,DTD文件包含在hibernate3.jar文件中。  在hibernate-mappings元素中,包含一个class元素,所有的持久化实体类需要一个到数据库表的映射。
    <hibernate-mapping>
        <class name="events.Event" table="EVENTS">
    </class>
    </hibernate-mapping>  这段配置告诉Hibernate如何存储和加载类Event的对象到EVENTS表,每一个对象对应着表中的一行。  现在,我们继续来研究表的主键与唯一标志属性的映射,由于我们不关心这个标记符的处理,所以我们使用代理的主键列。
    <hibernate-mapping>
    <class name="events.Event" table="EVENTS">
       <id name="id" column="EVENT_ID">
         <generator class="native"/>
       </id>
    </class>
    </hibernate-mapping>

         id元素是标志属性的声明,name=”id”是Java属性的声明。Hibernate使用getter和setter方法来存取属性。column属性告诉Hibernate在EVENTS表中的哪一列对应着主键。嵌套的generator元素指定了标志的生成策略,这里我们使用native策略(根据配置的数据库选择最好的策略)。

    最后,我们将类中的持久化属性添加到映射文件中,默认情况下,类的所有属性都不是持久化的。
    <hibernate-mapping>
        <class name="events.Event" table="EVENTS">
          <id name="id" column="EVENT_ID">
            <generator class="native"/>
          </id>
         <property name="date" type="timestamp" column="EVENT_DATE"/>
         <property name="title"/>
       </class>
    </hibernate-mapping>

          和id元素一样,property的name属性指定了Hibernate要使用的getter和settter方法。在上面的配置文件中,Hibernate会查找getDate()/setDate()和getTitle()/setTtile()方法。  如果property没有包含column属性,那么Hibernate默认使用property的名字作为数据库表的列的名字,对于title来说没有问题。但是在大多数数据库中,date是一个保留字,所以最好将其映射到其他的名字。      另外一个比较有趣的话题是,title还缺少一个type属性(和date相比)。也许你认为在映射文件中的声明的类型是java数据类型,那就错了。是SQL数据库类型?也不对。这些types是所谓的Hibernate映射类型,转化器可以将其从java数据类型转换为SQL数据类型,反之亦然。在type属性不存在的时候,Hibernate试图确定正确的转换以及映射的类型。在某些情况下,这个自动的检测(对java类使用Reflection)可能没有你期望或者需要的默认类型。date属性就属于这种类型。Hibernate不知道java.util.Date属性应该映射到SQL的date,timestamp还是time列上,我们通过使用timestamp转换来获取完整的date和time信息。

         这个映射文件应该以Event.hbm.xml作为文件名保存。和java类文件在同一个目录。映射文件名字是任意的, 但是hbm.xml后缀是一个习惯命名 四、配置Hibernate
         Hibernate是应用程序链接数据库的外层,所以它需要一些连接信息。连接通过JDBC连接池完成,这是需要进行配置的。Hibernate发布包中包含了几个开源的JDBC连接池,但是在本教程中使用内置(built-in)的连接池。当使用不同的连接池时,需要将连接池的驱动程序拷贝到类路径中。

    可以使用hibernate.properties文件,或者稍微复杂些的hibernate.cg.xml文件,甚至完全使用编程的方法来进行Hibernate的配置,大多数用户使用XML配置文件: <?xml version="1.0" encoding="GBK"?>
    <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
    <!--上面四行对所有的hibernate连接配置文件都相同 -->
    <!-- hibernate- configuration是连接配置文件的根元素 -->
    <hibernate-configuration>
      <session-factory>
      <!-- 指定连接数据库所用的驱动 -->
      <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
      <!-- 指定连接数据库的url,hibernate连接的数据库名 -->
      <property name="connection.url">jdbc:mysql://localhost/hbs</property>
      <!-- 指定连接数据库的用户名 -->
      <property name="connection.username">root</property>
      <!-- 指定连接数据库的密码 -->
      <property name="connection.password"></property>
      <!-- 指定连接池的大小-->
      <!-- C3P0 connection pool -->
      <property name="hibernate.c3p0.max_size">20</property>
      <property name="hibernate.c3p0.min_size">1</property>
      <property name="hibernate.c3p0.timeout">5000</property>
      <property name="hibernate.c3p0.max_statements">100</property>
      <property name="hibernate.c3p0.idle_test_period">3000</property>
      <property name="hibernate.c3p0.acquire_increment">2</property>
      <property name="hibernate.c3p0.validate">true</property>
      <!-- 指定数据库方言-->
      <property name="dialect">org.hibernate.dialect.MySQLDialect</property>   <!-- Enable Hibernate"s automatic session context management -->
      <property name="current_session_context_class">thread</property>
      <!-- Disable the second-level cache -->
      <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
      <!-- Echo all executed SQL to stdout -->
      <property name="show_sql">true</property>   <!-- 根据需要自动创建数据库表-->
      <property name="hbm2ddl.auto">create</property>
      <!-- 罗列所有的映射文静-->
      <mapping resource="events/Event.hbm.xml"/>
    </session-factory>
    </hibernate-configuration>     首先,这个XML配置文件使用一个不同于映射配置文件的DTD,Hibernate的SessionFactory元素用于配置一个针对于特定数据库的全局工厂类。如果使用多个数据库时,为了方便启动,一般使用多个配置文件,或者包含多个<session-factory>。     属性hbm2ddl启用自动生成数据库schemas-直接存入数据库。最后,我们将持久化类的映射文件(一个或者多个)添加到配置文件中。 五、启动
         在加载和存储一些Event对象之前,先完成基础设施(util)代码。我们得启动Hibernate。这里说的启动包括创建一个全局的SessionFactory对象,然后将其保存在程序代码可以引用的地方。SessionFactory可以打开新的Session,Session代表一个单线程的工作单元,SessionFactory是一个线程安全的全局对象,只初始化一次。  我们创建一个叫做HibernateUtil的辅助类,这个类用于方便的启动和调用SessionFactory,代码如下:
    1. package util;
    2. import org.hibernate.*;
    3. import org.hibernate.cfg.*;
    4. public class HibernateUtil {
    5.     private static final SessionFactory sessionFactory;
    6.     static {
    7.         try {
    8.             // Create the SessionFactory from hibernate.cfg.xml
    9.             sessionFactory = new Configuration().configure().buildSessionFactory();
    10.         } catch (Throwable ex) {
    11.             // Make sure you log the exception, as it might be swallowed
    12.             System.err.println("Initial SessionFactory creation failed." + ex);
    13.             throw new ExceptionInInitializerError(ex);
    14.         }
    15.     }
    16.     public static SessionFactory getSessionFactory() {
    17.         return sessionFactory;
    18.     }
    19. }
    复制代码
         这个类不仅静态初始化了一个全局的SessionFactory(在类加载时,JVM只调用该方法一次),并且隐藏了它使用静态单例的事实。它也可能在应用程序服务器的JNDI中查找SessionFactory。 如果在配置文件中为SessionFactory指定一个名字,创建完这个对象后Hibernate会试着将其绑定到JNDI。为了避免这样的代码,可以使用JMX部署,让JMX初始化并绑定HibernateService到JNDI。这里不做深入的讨论。 六、加载和存储对象
    我们终于可以使用Hibernate来加载和存储对象了。我们编写一个带main方法的EventManager类,内容如下:
    1. package events;
    2. import org.hibernate.Session;
    3. import java.util.Date;
    4. import java.util.List;
    5. import util.HibernateUtil;
    6. public class EventManager {
    7.        public static void main(String[] args) {
    8.               EventManager mgr = new EventManager();
    9.               if (args[0].equals("store")) {
    10.                      mgr.createAndStoreEvent("My Event1", new Date());
    11.               }
    12.               else if (args[0].equals("list")) {
    13.                  List events = mgr.listEvents();
    14.                  for (int i = 0; i < events.size(); i++) {
    15.                   Event theEvent = (Event) events.get(i);
    16.                   System.out.println("Event: " + theEvent.getTitle() +
    17.                            " Time: " + theEvent.getDate());
    18.                  }
    19.               }
    20.               HibernateUtil.getSessionFactory().close();
    21.        }
    22.        private List listEvents() {
    23.         Session session = HibernateUtil.getSessionFactory().getCurrentSession();
    24.         session.beginTransaction();
    25.         List result = session.createQuery("from Event").list();
    26.         session.getTransaction().commit();
    27.            return result;
    28.         }
    29.        private void createAndStoreEvent(String title, Date theDate) {
    30.               Session session = HibernateUtil.getSessionFactory().getCurrentSession();
    31.               session.beginTransaction();
    32.               Event theEvent = new Event();
    33.               theEvent.setTitle(title);
    34.               theEvent.setDate(theDate);
    35.               session.save(theEvent);
    36.               session.getTransaction().commit();
    37.        }
    38. }
    复制代码
      创建Event对象,传递给Hibernate,Hibernate使用SQL语句,将其INSERT到数据库,在执行之前,我们先看一下Session和Transaction代码:      Session是一个单独的工作单元。简而言之,Hibernate的Session和数据库的Transaction是一对一的关系。为了隔离我们的代码与实际的底层事务系统(本例中是JDBC,也可能是JTA Java Transaction API),我们使用在Hibernate中使用Session来完成Transaction API。 sessionFactory.getCurrentSession()完成以下工作:
    可以在任意位置调用任意次这个方法,一旦你获取了SessionFactory对象,getCurrentSession()方法总是返回当前的工作单元。还记得我们在hibernate.cfg.xml中对这个配置的设置吗? <!-- Enable Hibernate"s automatic session context management -->
    <property name="current_session_context_class">thread</property>      因此,当前的工作单元与当前的Java线程绑定在一起的。然后,你还需要考虑范围,工作单元的起始和结束。Session当第一次需要的时候就开始了,当第一次调用getCurrentSession()的时候创建了Session,借下来被Hibernate绑定到当前线程中。当事务结束时(通过commit或者rollback),Hibernate自动将其从当前线程中结束绑定,并将其关闭。当你再次调用getCurrentSession()方法时,就获取了一个新的Session,从而开始一个新的工作单元。线程绑定编程模型是使用Hibernate的最常用方式,因为它允许代码的灵活层次化(事务分界代码可以与数据存取代码相分离,在本教程后面会提及到)。

         对于一个工作单元,Hibernate的Session是否可以用来执行一个或者多个数据库操作?上面的例子中使用Session进行了一个操作。这只是一个巧合,上面的例子比较简单而已。Session的范围很灵活,但是在应用程序中对每个database操作使用一个新的Session是绝对不应该的。所以虽然你在本教程的许多例子中看到这种情况,但是session-per-operation是一个不推荐的模式。在本教程的后面将展示一个实际的应用程序。

    七:编译和运行

    c:work>h.bat c:work>set classpath=.;c:worklibhibernate3.jar;c:worklibmysql-connector-java-3.
    1.10-bin.jar;c:worklibcommons-logging-1.0.4.jar;c:worklibdom4j-1.6.1.jar;c:work
    libcommons-collections-2.1.1.jar;c:worklibc3p0-0.9.1.jar;c:worklibasm.jar;c:
    kklibcglib-2.1.3.jar;c:worklibjta.jar;c:worklibantlr-2.7.6.jar c:work>javac -d . *.java c:work>java events.EventManager store 八:结果
    mysql> use hbs;
    Database changed
    mysql> show tables;
    +----------------------+
    | Tables_in_hbs   |
    +----------------------+
    | events             |
    +----------------------+
    1 row in set (0.00 sec) mysql> select * from events;
    +-----------------+-----------------------------------+-----------------+
    | EVENT_ID   | EVENT_DATE               | title            |
    +-----------------+-----------------------------------+-----------------+
    | 1               | 2007-10-20 09:26:14      | My Event    |
    +-----------------+-----------------------------------+-----------------+
    1 row in set (0.02 sec)



      
      
       
       

         
       

         
       
      
    复制代码

    源码下载:http://www.hnzz3z.com:8103/zz3zcwb/work1.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-25 10:19 , Processed in 0.297044 second(s), 36 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

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