Hibernate学习英文文档翻译 4.3.11 1.教程

面向新用户,从一个简单的使用内存数据库的例子开始,本章提供对Hibernate的逐步介绍。本教程是基于Michael Gloegl早期开发的手册。所有代码包含在项目资源tutorials/web文件夹中。

这个教程要求读者掌握JAVA和SQL技术。如果你有一定的JAVA和SQL基础,那么建议你开始一段美好的介绍,在尝试学习Hibernate之前的技术。

在tutorial/eg项目资源目录下存在着另一个例子。

第一部分,第一个Hibernate程序

在这个例子中,我们可以建立一个可以用来存储的小型数据库应用,可以用来存储我们想要参加的events并且这些活动主办方的信息。

尽管你可以使用任何你觉得用着方便的数据库,但我们会使用HSQLDB(java内存数据库)这个数据库,该数据库可以避免花费篇章来对数据库服务器的安装和配置进行解释。

第一件事我们需要建立开发环境。我们将会使用许多构建工具例如maven所鼓吹的“标准格式”。特别是maven,他的资源对这个layout有很好的描述。因为本教程是一个web应用程序,我们将会创建和使用ofsrc/main/java,src/main/resources andsrc/main/webapp目录

在本教程中,我们将会使用maven,利用其传递依赖管理能力以及基于maven描述符用IDE自动创建一个项目的能力。

<span style="font-size:18px;"><project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>org.hibernate.tutorials</groupId>
    <artifactId>hibernate-tutorial</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <name>First Hibernate Tutorial</name>

    <build>
         <!-- we dont want the version to be part of the generated war file name -->
         <finalName>${artifactId}</finalName>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
        </dependency>

        <!-- Because this is a web app, we also have a dependency on the servlet api. -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
        </dependency>

        <!-- Hibernate uses slf4j for logging, for our purposes here use the simple backend -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
        </dependency>

        <dependency>
            <groupId>javassist</groupId>
            <artifactId>javassist</artifactId>
        </dependency>
    </dependencies>

</project></span>

Tip

It is not a requirement to use Maven. If you wish to use something else to build this tutorial (such as Ant), the layout will remain the same. The only change is that you will need to manually account for all the needed dependencies. If you use something like Ivy providing transitive dependency management you would still use the dependencies mentioned below. Otherwise, you'd need to graball dependencies, both explicit and transitive, and add them to the project's classpath. If working from the Hibernate distribution bundle, this would meanhibernate3.jar, all artifacts in thelib/required directory and all files from either thelib/bytecode/cglib orlib/bytecode/javassist directory; additionally you will need both the servlet-api jar and one of the slf4j logging backends.

Save this file as pom.xml in the project root directory.

在项目的根目录中保存这个文件为pom.xml。

这里我后来是使用的maven,但是中央仓库已经不在官网了,而是本地地址,使用他的地址是找不到我要用的jar包的,所以我手动从官网上下载的jar包,这并不难找到,把jar包加到自己公司的中央仓库中,简单的加载一下jar包即可。

It is not a requirement to use Maven. If you wish to use something else to build this tutorial (such as Ant), the layout will remain the same. The only change is that you will need to manually account for all the needed dependencies. If you use something like Ivy providing transitive dependency management you would still use the dependencies mentioned below. Otherwise, you'd need to graball dependencies, both explicit and transitive, and add them to the project's classpath. If working from the Hibernate distribution bundle, this would meanhibernate3.jar, all artifacts in thelib/required directory and all files from either thelib/bytecode/cglib orlib/bytecode/javassist directory; additionally you will need both the servlet-api jar and one of the slf4j logging backends.

不是必须使用maven才可以进行安装。如果你希望使用其他的方式来建立这个教程,布局仍旧一样。改变的只是你需要手工的记住这些依赖关系。如果你使用一些类似提供传递依赖管理的Ivy,你仍然会用到下面的依赖关系。否则,你需要抓取所有的依赖,显性和传递,把他们都添加到工程类路径中。如果需要Hibernate分布式的话,这就意味着hibernate3.jar,所有的在lib/required文件夹下的依赖,还有从lib/bytecode/cglib或者lib/bytecode/javasist其中之一的所有文件;另外,你将会需要servlet-api jar 和slf4j来记录日志。

Save this file as pom.xml in the project root directory.

保存这个pom.xml在工程的根目录中。

1.1.2. The first class

第一个类

Next, we create a class that represents the event we want to store in the database; it is a simple JavaBean class with some properties:

下一步,我们创建一个类,这个类代表了我们想要保存于数据库的事件;它是一个带有一些属性的简单的JavaBean类:

<span style="font-size:18px;">package org.hibernate.tutorial.domain;

import java.util.Date;

public class Event {
    private Long id;

    private String title;
    private Date date;

    public Event() {}

    public Long getId() {
        return id;
    }

    private void setId(Long id) {
        this.id = id;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}</span>

在工程中同样写入该类。

This class uses standard JavaBean naming conventions for property getter and setter methods, as well as private visibility for the fields. Although this is the recommended design, it is not required. Hibernate can also access fields directly, the benefit of accessor methods is robustness for refactoring.

这个类使用标准的对于属性getter和setter方法和私有变量命名的JavaBean。尽管这是推荐的使用方式,并不是必须的。Hibernate也可以直接访问域,直接访问的好处是结构的稳定性。

The id property holds a unique identifier value for a particular event. All persistent entity classes (there are less important dependent classes as well) will need such an identifier property if we want to use the full feature set of Hibernate. In fact, most applications, especially web applications, need to distinguish objects by identifier, so you should consider this a feature rather than a limitation. However, we usually do not manipulate the identity of an object, hence the setter method should be private. Only Hibernate will assign identifiers when an object is saved. Hibernate can access public, private, and protected accessor methods, as well as public, private and protected fields directly. The choice is up to you and you can match it to fit your application design.

id属性保存了一个特别的事件中唯一标示符值。如果我们想要使用所有的Hibernate的功能,所有的持久化实体类(以及一些不重要的类)将会需要这样一个标示符属性.事实上,大部分的应用,特别是web应用,需要需要通过唯一的标示符来区分对象,因此你应该考虑这些特性,而不是限制。然而,我们通常不会操作对象的唯一标示符,因此,setter方法应该是私有的。Hibernate可以在保存对象的时候来分配这个唯一标示的值。Hibernate可以访问公有、私有、保护的变量和方法。选择权在你,你可以为了适合你的应用设计而做出调整。

The no-argument constructor is a requirement for all persistent classes; Hibernate has to create objects for you, using Java Reflection. The constructor can be private, however package or public visibility is required for runtime proxy generation and efficient data retrieval without bytecode instrumentation.

无参的构造函数对所有的持久的类来说是必须的; Hibernate已经为您使用JAVA 反射来创建对象。构造函数可以是私有的,但是包和公有可见性对于动态代理生成而言是必须的。在没有字节码的情况下可以高效的数据检索。

Save this file to the src/main/java/org/hibernate/tutorial/domain directory.

保存文件。

1.1.3. The mapping file

Hibernate needs to know how to load and store objects of the persistent class. This is where the Hibernate mapping file comes into play. The mapping file tells Hibernate what table in the database it has to access, and what columns in that table it should use.

Hibernate需要知道如何加载和保存持久类的对象。这是Hibernate映射文件需要的地址。映射文件告诉Hibernate已经访问在数据库中的哪张表,并且表中的哪行在使用。           

The basic structure of a mapping file looks like this:

映射文件的基本结构如下:

<span style="font-size:18px;"><?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="org.hibernate.tutorial.domain">
[...]
</hibernate-mapping></span>

先在一个xml文件中写入该内容,可以暂时先不保存。

Hibernate DTD is sophisticated. You can use it for auto-completion of XML mapping elements and attributes in your editor or IDE. Opening up the DTD file in your text editor is the easiest way to get an overview of all elements and attributes, and to view the defaults, as well as some comments. Hibernate will not load the DTD file from the web, but first look it up from the classpath of the application. The DTD file is included inhibernate-core.jar (it is also included in thehibernate3.jar, if using the distribution bundle).

Hibernate DTD是复杂的。你可以在你的编辑器或者IDE中使用它,以便于自动完成XML的属性和元素的映射。在你的文本编辑器中打开DTD文件是获得一个所有元素和属性该来的最简单的方式,还有查看默认的内容。Hibernate不会从站点加载DTD文件,但是会先从classpath查看。DTD文件包含在hibernate-core.jar 这个jar包中(如果使用分布式的话,也包含在hibernate3.jar中)。

Important

重要事项

We will omit the DTD declaration in future examples to shorten the code. It is, of course, not optional.

为了缩短代码的长度我们将会省略DTD的声明。在实际使用中当然是必须的。

Between the two hibernate-mapping tags, include aclass element. All persistent entity classes (again, there might be dependent classes later on, which are not first-class entities) need a mapping to a table in the SQL database:

在两个hibernate-mapping 标签之间包括了一个类元素。所有持久化实体类需要映射到数据库中的表。

<span style="font-size:18px;"><hibernate-mapping package="org.hibernate.tutorial.domain">

    <class name="Event" table="EVENTS">

    </class>

</hibernate-mapping></span>

在刚刚的xml中添加这个class内容。

So far we have told Hibernate how to persist and load object of classEvent to the tableEVENTS. Each instance is now represented by a row in that table. Now we can continue by mapping the unique identifier property to the tables primary key. As we do not want to care about handling this identifier, we configure Hibernate's identifier generation strategy for a surrogate primary key column:

到目前为止,我们已经告诉Hibernate如何取持久和加载Event类到EVENTS表中。每个实例现在代表着表中的一行。现在我们可以继续通过映射唯一标示符属性到表中的主键中。因此我们不想关心怎么产生这个标示符,我们配置Hibernate的标示符产生策略对应着一个代理的主键行。

<span style="font-size:18px;"><hibernate-mapping package="org.hibernate.tutorial.domain">

    <class name="Event" table="EVENTS">
        < id name="id" column="EVENT_ID">
            <generator class="native"/>
        </id>
    </class>

</hibernate-mapping></span>

将中间的id补充到xml中。

The id element is the declaration of the identifier property. Thename="id" mapping attribute declares the name of the JavaBean property and tells Hibernate to use thegetId() and setId() methods to access the property. The column attribute tells Hibernate which column of theEVENTS table holds the primary key value.
这个id元素是唯一标示符属性的描述。name="id"映射属性定义JavaBean属性的名字和告诉Hibernate去使用getId()和setId()方法来访问属性。行属性告诉Hibernate,EVENTS表的哪行保持了主键的值。

The nested generator element specifies the identifier generation strategy (aka how are identifier values generated?). In this case we choosenative, which offers a level of portability depending on the configured database dialect. Hibernate supports database generated, globally unique, as well as application assigned, identifiers. Identifier value generation is also one of Hibernate's many extension points and you can plugin in your own strategy.

嵌套的generator元素指定了标示符产生的策略(又叫做标示符的值怎么产生的)。在这个例子中,我们选择native,native提供了一个依赖于配置数据库的方言的可移植性的水平。Hibernate提供数据库生成标示符全局唯一性还有应用分配。标示符值产生的方式是Hibernate的许多扩展点中的其中一个,并且你可以在你自己的策略中进行插入。

Tip

native is no longer consider the best strategy in terms of portability. for further discussion, seeSection 27.4, “Identifier generation”

native不再是根据可移植性来考虑的最佳策略。更多的讨论,详见连接。

Lastly, we need to tell Hibernate about the remaining entity class properties. By default, no properties of the class are considered persistent:

最后,我们需要告诉Hibernate关于仍旧保持实体类的属性。通过默认的方式,没有类中的属性是持久化的:

<span style="font-size:18px;"><hibernate-mapping package="org.hibernate.tutorial.domain">

    <class name="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></span>

将property的内容补充到xml文件中。

Similar to the id element, thename attribute of theproperty element tells Hibernate which getter and setter methods to use. In this case, Hibernate will search forgetDate(),setDate(),getTitle() andsetTitle() methods.

类似于id元素,property元素的name属性告诉Hibernate使用哪个getter和setter方法。在这个例子中,Hibernate将会搜索getDate(),setDate(),getTitle()和setTitle()方法。

Note

Why does the date property mapping include thecolumn attribute, but thetitle does not? Without thecolumn attribute, Hibernate by default uses the property name as the column name. This works fortitle, however,date is a reserved keyword in most databases so you will need to map it to a different name.

提示:

为什么date属性映射的时候包括了column属性,而title并没有呢?在没有column属性的情况下,Hibernate通过默认使用属性名称作为column名字。这对title是管用的,然而,date在大多数数据库中是一个保留关键字,因此你需要将它映射为一个不同的名字。

总的来说就是,一般情况下name后的名字基本都和数据库表的字段一样,所以不用column这个字段了,但是有的数据库中的字段不能是date,所以就指定一下映射的column。

The title mapping also lacks atype attribute. The types declared and used in the mapping files are not Java data types; they are not SQL database types either. These types are calledHibernate mapping types, converters which can translate from Java to SQL data types and vice versa. Again, Hibernate will try to determine the correct conversion and mapping type itself if thetype attribute is not present in the mapping. In some cases this automatic detection using Reflection on the Java class might not have the default you expect or need. This is the case with thedate property. Hibernate cannot know if the property, which is ofjava.util.Date, should map to a SQLdate,timestamp, ortime column. Full date and time information is preserved by mapping the property with atimestamp converter.

title映射也缺少一个type属性。在映射文件中类型的定义和使用并不是Java数据的类型;他们也不是SQL数据库的类型。这些类型称为Hibernate映射类型,翻译器可以从Java转换为SQL数据类型,反之亦然。再一次,Hibernate将会尝试去决定正确的转换并且映射类型自己如果type属性没有出现在映射中。在一些例子中,这些使用Java反射检查也许并不是你所需要和期望的。这个例子中带有date属性。如果是java.util.Date这个类的属性,Hibernate不能知道到底是映射为SQL中的date,timestamp还是time。所有的时间和日期信息会通过带有timestamp转换器的映射属性保存。

补充说明一下数据库的时间日期字段,以MySQL为例:

DATETIME类型用在你需要同时包含日期和时间信息的值时。MySQL检索并且以'YYYY-MM-DD HH:MM:SS'格式显示DATETIME值,支持的范围是'1000-01-01 00:00:00'到'9999-12-31 23:59:59'。(“支持”意味着尽管更早的值可能工作,但不能保证他们可以。)

DATE类型用在你仅需要日期值时,没有时间部分。MySQL检索并且以'YYYY-MM-DD'格式显示DATE值,支持的范围是'1000-01-01'到'9999-12-31'。

TIMESTAMP列类型提供一种类型,你可以使用它自动地用当前的日期和时间标记INSERT或UPDATE的操作。
TIME数据类型表示一天中的时间。MySQL检索并且以"HH:MM:SS"格式显示TIME值。支持的范围是'00:00:00'到'23:59:59'。

Tip

Hibernate makes this mapping type determination using reflection when the mapping files are processed. This can take time and resources, so if startup performance is important you should consider explicitly defining the type to use.

当访问映射文件的时候Hibernate去使用反射来确定这些映射的类型。这些需要消耗时间和资源,如果启动的时候性能是重要的话,你应该考虑使用明确的定义类型。

Save this mapping file as src/main/resources/org/hibernate/tutorial/domain/Event.hbm.xml.

保存文件问Event.hbm.xml

1.1.4. Hibernate configuration

Hibernate配置

At this point, you should have the persistent class and its mapping file in place. It is now time to configure Hibernate. First let's set up HSQLDB to run in "server mode"

在这一节中,你应该已经拥有了一个持久化的类和它的映射文件在一起。是时候配置Hibernate了。首先让我们在“server mode”下建立HSQLDB。

Note

We do this so that the data remains between runs.

我们这样做是为了让数据在两者之间持久运行。

We will utilize the Maven exec plugin to launch the HSQLDB server by running:mvn exec:java -Dexec.mainClass="org.hsqldb.Server" -Dexec.args="-database.0 file:target/data/tutorial" You will see it start up and bind to a TCP/IP socket; this is where our application will connect later. If you want to start with a fresh database during this tutorial, shutdown HSQLDB, delete all files in thetarget/data directory, and start HSQLDB again.

我们将会利用Maven exec插件运行HSQLDB服务器:mvn exec:java -Dexec.mainClass="org.hsqldb.server" -Dexec.args="-database.0file:target/data/tutorial" 。你会看到它启动和绑定到一个TCP/IP套接字中;这是我们的应用不久将会连接到的地方。如果你想要在这个教程中开始一个新的数据库,关闭HSQLDB,删除所有在target/data文件夹下的文件,并且再一次开始HSQLDB。

这里我自己本地使用的是mysql数据库,所以这步并没有去做。

Hibernate will be connecting to the database on behalf of your application, so it needs to know how to obtain connections. For this tutorial we will be using a standalone connection pool (as opposed to ajavax.sql.DataSource). Hibernate comes with support for two third-party open source JDBC connection pools:c3p0 andproxool. However, we will be using the Hibernate built-in connection pool for this tutorial.

Hibernate将会为你的应用连接到数据库,因此,它需要知道如何获得连接。对于这个教程来说,我们将会使用一个独立的连接池(和javax.sql.DataSource相反的)。Hibernate支持两个第三方的开源JDBC连接池:c3p0和proxool。然而,在这个教程中,我们将会使用Hibernate内置的连接池。

小心

The built-in Hibernate connection pool is in no way intended for production use. It lacks several features found on any decent connection pool.

内置的Hibernate连接池不能在产品中使用。它缺少一些连接池的几个属性。

这里我也不打算使用Hibernate内置的连接池,直接使用c3p0,这样直接可以在其他地方应用。

For Hibernate's configuration, we can use a simplehibernate.properties file, a more sophisticatedhibernate.cfg.xml file, or even complete programmatic setup. Most users prefer the XML configuration file:

对于Hibernate的配置来说,我们可以使用一个简单的hibernate.properties文件,或者是更复杂一些的hibernate.cfg.xml文件,甚至完全可以用程序来安装。大多数的用户更强相遇xml配置文件:

<span style="font-size:18px;"><?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

    <session-factory>

        <!-- Database connection settings -->
        <property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
        <property name="connection.url">jdbc:hsqldb:hsql://localhost</property>
        <property name="connection.username">sa</property>
        <property name="connection.password"></property>

        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">1</property>

        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.HSQLDialect</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.internal.NoCacheProvider</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>

        <!-- Drop and re-create the database schema on startup -->
        <property name="hbm2ddl.auto">update</property>

        <mapping resource="org/hibernate/tutorial/domain/Event.hbm.xml"/>

    </session-factory>

</hibernate-configuration></span>

这里可以在网上找一下c3p0如何部署和配置。

下面是我在网上找到的c3p0的配置:

<span style="font-size:18px;"><?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
	<session-factory>
		<!-- 配置数据库的连接属性 -->
		<property name="myeclipse.connection.profile">MySQL5.0</property>
		<property name="connection.url">
			jdbc:mysql://127.0.0.1:3306/test_hibernate?useUnicode=true&characterEncoding=gb2312
		</property>
		<property name="connection.username">root</property>
		<property name="connection.password">root</property>
		<property name="connection.driver_class">
			com.mysql.jdbc.Driver
		</property>
		<property name="dialect">
			org.hibernate.dialect.MySQLDialect
		</property>
		<property name="show_sql">true</property>
		<!-- 配置C3P0连接池属性 -->
		<property name="hibernate.connection.provider_class">
			org.hibernate.c3p0.internal.C3P0ConnectionProvider
		</property>
		<property name="hibernate.c3p0.max_size">20</property>
		<property name="hibernate.c3p0.min_size">5</property>
		<property name="hibernate.c3p0.timeout">50000</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">false</property>

		<!-- 配置持久化映射文件 -->
		<mapping resource="Event.hbm.xml" />
	</session-factory>
</hibernate-configuration></span>
c3p0相关的jar包可以在hibernate的\lib\optional\c3p0中找到,不用单独去下载。但是目前还是不太清楚如何去验证这个链接是否有效的,所以暂时先这样,往下走。

Note

注意

Notice that this configuration file specifies a different DTD

注意这个配置文件指定了一个不同的DTD文件。

You configure Hibernate's SessionFactory. SessionFactory is a global factory responsible for a particular database. If you have several databases, for easier startup you should use several<session-factory> configurations in several configuration files.

你配置Hibernate的SessionFactory。对一个特定的数据库来说,SessionFactory是一个全局的工厂仓库。如果你有几个数据库,更简单的开始方式是你在几个配置文件中使用几个<session-factory>配置。

The first four property elements contain the necessary configuration for the JDBC connection. The dialectproperty element specifies the particular SQL variant Hibernate generates.

首先的4个property元素包含了JDBC连接必要的配置。方言的property元素指定了通过不一样的Hibernate生成的一个特定的SQL。

Tip

提示

In most cases, Hibernate is able to properly determine which dialect to use. SeeSection 27.3, “Dialect resolution” for more information.

在大多数情况下,Hibernate能够做出合适的决定来使用哪种方言。点击连接。

Hibernate's automatic session management for persistence contexts is particularly useful in this context. Thehbm2ddl.auto option turns on automatic generation of database schemas directly into the database. This can also be turned off by removing the configuration option, or redirected to a file with the help of theSchemaExport Ant task. Finally, add the mapping file(s) for persistent classes to the configuration.

Hibernate对持久化文本的自动会话管理在这个文本中是非常有用的。打开hbm2ddl.auto选项自动生成的数据库模式-直接加入数据库中。也可以关闭他来移出配置项目或者直接直接Ant 任务SchemaExport的帮助文件。最后,增加映射文件到持久化类的配合中。

Save this file as hibernate.cfg.xml into thesrc/main/resources directory.

保存这个文件为hibernate.cfg.xml到src/main/resources 文件夹中。

We will now build the tutorial with Maven. You will need to have Maven installed; it is available from theMaven download page. Maven will read the/pom.xml file we created earlier and know how to perform some basic project tasks. First, lets run thecompile goal to make sure we can compile everything so far:

现在我们将会使用Maven来构建这个教程。你将会需要安装Maven。从这里可以下载到。Maven将会读取我们之前创建的pom.xml文件并且知道如何来执行一些基本的项目任务。首先,让我们运行compile命令来确保我们可以编译到目前为止的任何事情:           

[hibernateTutorial]$ mvn compile
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building First Hibernate Tutorial
[INFO]    task-segment: [compile]
[INFO] ------------------------------------------------------------------------
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Compiling 1 source file to /home/steve/projects/sandbox/hibernateTutorial/target/classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2 seconds
[INFO] Finished at: Tue Jun 09 12:25:25 CDT 2009
[INFO] Final Memory: 5M/547M
[INFO] ------------------------------------------------------------------------

1.1.6. Startup and helpers

启动和辅助类

It is time to load and store some Event objects, but first you have to complete the setup with some infrastructure code. You have to startup Hibernate by building a globalorg.hibernate.SessionFactory object and storing it somewhere for easy access in application code. Aorg.hibernate.SessionFactory is used to obtainorg.hibernate.Session instances. Aorg.hibernate.Session represents a single-threaded unit of work. Theorg.hibernate.SessionFactory is a thread-safe global object that is instantiated once.

是时候加载和存储一些Event对象了,但是首先你不得不完成建立一些基础的代码。你不得不通过构建一个全局的org.hibernate.SessionFactory对象来启动Hibernate ,并且可以在任何地方更容易的用应用代码来存储。org.hibernate.SessionFactory是用来获取org.hibernate.Session初始化的。一个org.hibernate.Session代表一个单线程单元工作。org.hibernate.SessionFactory是一个线程安全的只需要初始化一次的全局对象。          

We will create a HibernateUtil helper class that takes care of startup and makes accessing theorg.hibernate.SessionFactory more convenient.

我们将会创建一个HibernateUtil帮助类来负责管理启动和更方便的操作org.hibernate.SessionFactory。

package org.hibernate.tutorial.util;

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            new Configuration().configure().buildSessionFactory(
			    new StandardServiceRegistryBuilder().build() );
        }
        catch (Throwable ex) {
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

}

Save this code as src/main/java/org/hibernate/tutorial/util/HibernateUtil.java

保存这个代码。

在保存这个官网提供的代码之后,发现少了return,也不知道是为什么,是有什么搞错了吗,这里我不太清楚,所以有知道的谁能告诉我是怎么回事,暂时我先加上了return,防止eclipse报错。

This class not only produces the global org.hibernate.SessionFactory reference in its static initializer; it also hides the fact that it uses a static singleton. We might just as well have looked up theorg.hibernate.SessionFactory reference from JNDI in an application server or any other location for that matter.

这个类不仅在静态初始化类中产生全局org.hibernate.SessionFactory的引用,还隐藏它使用一个静态的单例模式的事实。我们也可能在应用服务器中从JNDI中查找org.hibernate.SessionFactory的引用或者其他本地的事件。

If you give the org.hibernate.SessionFactory a name in your configuration, Hibernate will try to bind it to JNDI under that name after it has been built. Another, better option is to use a JMX deployment and let the JMX-capable container instantiate and bind a HibernateService to JNDI. Such advanced options are discussed later.

如果你在你的配置中给org.hibernate.SessionFactory一个名字。在它创建之后,Hibernate将他的名字绑定到JNDI下。另外,更好的选项是使用JMX部署和让JMX能力的容器初始和绑定一个HibernateService到JNDI。更高级的选项在之后讨论。

You now need to configure a logging system. Hibernate uses commons logging and provides two choices: Log4j and JDK 1.4 logging. Most developers prefer Log4j: copylog4j.properties from the Hibernate distribution in theetc/ directory to your src directory, next tohibernate.cfg.xml. If you prefer to have more verbose output than that provided in the example configuration, you can change the settings. By default, only the Hibernate startup message is shown on stdout.

现在你需要配置一个日志系统。Hibernate使用公共日志和提供两个选择:Log4j和JDK1.4日志。大部分的开发者倾向于Log4j:从Hibernate目录下的etc中拷贝log4j.properties文件到你的src目录下,和hibernate.cfg.xml一起。如果你想要修改提供的示例配置中的输出,你可以改变设置。默认的,只有hibernate启动信息显示。

The tutorial infrastructure is complete and you are now ready to do some real work with Hibernate.

这个教程的基础部分已经完成了,你现在可以用Hibernate准备做一些真正的工作了。

1.1.7. Loading and storing objects

加载和存储对象

We are now ready to start doing some real work with Hibernate. Let's start by writing anEventManager class with amain() method:

我们现在已经准备使用Hibernate来开始做一些真正的工作了。让我们通过写一个EventManager类中的main()方法来开始:           

package org.hibernate.tutorial;

import org.hibernate.Session;

import java.util.*;

import org.hibernate.tutorial.domain.Event;
import org.hibernate.tutorial.util.HibernateUtil;

public class EventManager {

    public static void main(String[] args) {
        EventManager mgr = new EventManager();

        if (args[0].equals("store")) {
            mgr.createAndStoreEvent("My Event", new Date());
        }

        HibernateUtil.getSessionFactory().close();
    }

    private void createAndStoreEvent(String title, Date theDate) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();

        Event theEvent = new Event();
        theEvent.setTitle(title);
        theEvent.setDate(theDate);
        session.save(theEvent);

        session.getTransaction().commit();
    }

}

In createAndStoreEvent() we created a newEvent object and handed it over to Hibernate. At that point, Hibernate takes care of the SQL and executes anINSERT on the database.

在createAndStoreEvent()方法中我们创建了一个新的Event对象并且持有到Hibernate。在这时,Hibernate管理SQL和执行一个在数据库上的INSERT操作。

A org.hibernate.Session is designed to represent a single unit of work (a single atomic piece of work to be performed). For now we will keep things simple and assume a one-to-one granularity between a Hibernateorg.hibernate.Session and a database transaction. To shield our code from the actual underlying transaction system we use the Hibernateorg.hibernate.Transaction API. In this particular case we are using JDBC-based transactional semantics, but it could also run with JTA.

org.hibernate.Session被设计用来代表一个简单的单元块。对于现在的我们来说,我们将会保存事情的简单性和

What does sessionFactory.getCurrentSession() do? First, you can call it as many times and anywhere you like once you get hold of yourorg.hibernate.SessionFactory. ThegetCurrentSession() method always returns the "current" unit of work. Remember that we switched the configuration option for this mechanism to "thread" in oursrc/main/resources/hibernate.cfg.xml? Due to that setting, the context of a current unit of work is bound to the current Java thread that executes the application.

sessionFactory.getCurrentSession()是用来做什么的呢?首先,一旦你持有了org.hibernate.SessionFactoy你可以在任何时间任何地点调用它。getCurrentSession()方法总是返回"当前的"工作单元。记住

Importa

重要


Hibernate提供了三种跟踪当前session的方法。基于"线程"的方法并不是为了在生产环境中使用的;


Related to the unit of work scope, should the Hibernateorg.hibernate.Session be used to execute one or several database operations? The above example uses oneorg.hibernate.Session for one operation. However this is pure coincidence; the example is just not complex enough to show any other approach. The scope of a Hibernateorg.hibernate.Session is flexible but you should never design your application to use a new Hibernateorg.hibernate.Session forevery database operation. Even though it is used in the following examples, considersession-per-operation an anti-pattern. A real web application is shown later in the tutorial which will help illustrate this.

SeeChapter 13,Transactions and Concurrency for more information about transaction handling and demarcation. The previous example also skipped any error handling and rollback.

To run this, we will make use of the Maven exec plugin to call our class with the necessary classpath setup:mvn exec:java -Dexec.mainClass="org.hibernate.tutorial.EventManager" -Dexec.args="store"

Note

You may need to performmvn compile first.

You should see Hibernate starting up and, depending on your configuration, lots of log output. Towards the end, the following line will be displayed:

你应该看到Hibernate启动和许多日志输出

[java] Hibernate: insert into EVENTS (EVENT_DATE, title, EVENT_ID) values (?, ?, ?)

This is the INSERT executed by Hibernate.

To list stored events an option is added to the main method:

        if (args[0].equals("store")) {
            mgr.createAndStoreEvent("My Event", new Date());
        }
        else if (args[0].equals("list")) {
            List events = mgr.listEvents();
            for (int i = 0; i < events.size(); i++) {
                Event theEvent = (Event) events.get(i);
                System.out.println(
                        "Event: " + theEvent.getTitle() + " Time: " + theEvent.getDate()
                );
            }
        }

A new listEvents() method is also added:

一个新的listEvents()方法也被添加:

    private List listEvents() {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        List result = session.createQuery("from Event").list();
        session.getTransaction().commit();
        return result;
    }

Here, we are using a Hibernate Query Language (HQL) query to load all existingEvent objects from the database. Hibernate will generate the appropriate SQL, send it to the database and populateEvent objects with the data. You can create more complex queries with HQL. SeeChapter 16,HQL: The Hibernate Query Language for more information.

这里,我们正在试用一个Hibenate Query Language(HQL)查询去加载所有数据库中已经存在的Event对象。Hibernate将会生成合适的SQL,发送它到数据库并装入带有Event对象的数据。你可以创建更复杂的HQL。详见链接获得更多的信息。

Now we can call our new functionality, again using the Maven exec plugin:mvn exec:java -Dexec.mainClass="org.hibernate.tutorial.EventManager" -Dexec.args="list"

现在我们可以调用我们的新方法了,再一次使用Maven执行插件:mvn exec:java -Dexec.mainClass="org.hibernate.tutorial.EventManager" -Dexec.args="list"








  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值