📄 tutorial.pot
字号:
#: tutorial.xml:503(para) msgid "It's time to load and store some <literal>Event</literal> objects, but first we have to complete the setup with some infrastructure code. We have to startup Hibernate. This startup includes building a global <literal>SessionFactory</literal> object and to store it somewhere for easy access in application code. A <literal>SessionFactory</literal> can open up new <literal>Session</literal>'s. A <literal>Session</literal> represents a single-threaded unit of work, the <literal>SessionFactory</literal> is a thread-safe global object, instantiated once."msgstr ""#: tutorial.xml:513(para) msgid "We'll create a <literal>HibernateUtil</literal> helper class which takes care of startup and makes accessing a <literal>SessionFactory</literal> convenient. Let's have a look at the implementation:"msgstr ""#: tutorial.xml:545(para) msgid "This class does not only produce the global <literal>SessionFactory</literal> in its static initializer (called once by the JVM when the class is loaded), but also hides the fact that it uses a static singleton. It might as well lookup the <literal>SessionFactory</literal> from JNDI in an application server."msgstr ""#: tutorial.xml:552(para) msgid "If you give the <literal>SessionFactory</literal> a name in your configuration file, Hibernate will in fact try to bind it to JNDI after it has been built. To avoid this code completely you could also use JMX deployment and let the JMX-capable container instantiate and bind a <literal>HibernateService</literal> to JNDI. These advanced options are discussed in the Hibernate reference documentation."msgstr ""#: tutorial.xml:561(para) msgid "Place <literal>HibernateUtil.java</literal> in the development source directory, in a package next to <literal>events</literal>:"msgstr ""#: tutorial.xml:579(para) msgid "This should again compile without problems. We finally need to configure a logging system - Hibernate uses commons logging and leaves you the choice between Log4j and JDK 1.4 logging. Most developers prefer Log4j: copy <literal>log4j.properties</literal> from the Hibernate distribution (it's in the <literal>etc/</literal> directory) to your <literal>src</literal> directory, next to <literal>hibernate.cfg.xml</literal>. Have a look at the example configuration and change the settings if you like to have more verbose output. By default, only Hibernate startup message are shown on stdout."msgstr ""#: tutorial.xml:589(para) msgid "The tutorial infrastructure is complete - and we are ready to do some real work with Hibernate."msgstr ""#: tutorial.xml:597(title) msgid "Loading and storing objects"msgstr ""#: tutorial.xml:599(para) msgid "Finally, we can use Hibernate to load and store objects. We write an <literal>EventManager</literal> class with a <literal>main()</literal> method:"msgstr ""#: tutorial.xml:640(para) msgid "We create a new <literal>Event</literal> object, and hand it over to Hibernate. Hibernate now takes care of the SQL and executes <literal>INSERT</literal>s on the database. Let's have a look at the <literal>Session</literal> and <literal>Transaction</literal>-handling code before we run this."msgstr ""#: tutorial.xml:647(para) msgid "A <literal>Session</literal> is a single unit of work. For now we'll keep things simple and assume a one-to-one granularity between a Hibernate <literal>Session</literal> and a database transaction. To shield our code from the actual underlying transaction system (in this case plain JDBC, but it could also run with JTA) we use the <literal>Transaction</literal> API that is available on the Hibernate <literal>Session</literal>."msgstr ""#: tutorial.xml:655(para) msgid "What does <literal>sessionFactory.getCurrentSession()</literal> do? First, you can call it as many times and anywhere you like, once you get hold of your <literal>SessionFactory</literal> (easy thanks to <literal>HibernateUtil</literal>). The <literal>getCurrentSession()</literal> method always returns the \"current\" unit of work. Remember that we switched the configuration option for this mechanism to \"thread\" in <literal>hibernate.cfg.xml</literal>? Hence, the current unit of work is bound to the current Java thread that executes our application. However, this is not the full picture, you also have to consider scope, when a unit of work begins and when it ends."msgstr ""#: tutorial.xml:666(para) msgid "A <literal>Session</literal> begins when it is first needed, when the first call to <literal>getCurrentSession()</literal> is made. It is then bound by Hibernate to the current thread. When the transaction ends, either through commit or rollback, Hibernate automatically unbinds the <literal>Session</literal> from the thread and closes it for you. If you call <literal>getCurrentSession()</literal> again, you get a new <literal>Session</literal> and can start a new unit of work. This <emphasis>thread-bound</emphasis> programming model is the most popular way of using Hibernate, as it allows flexible layering of your code (transaction demarcation code can be separated from data access code, we'll do this later in this tutorial)."msgstr ""#: tutorial.xml:677(para) msgid "Related to the unit of work scope, should the Hibernate <literal>Session</literal> be used to execute one or several database operations? The above example uses one <literal>Session</literal> for one operation. This is pure coincidence, the example is just not complex enough to show any other approach. The scope of a Hibernate <literal>Session</literal> is flexible but you should never design your application to use a new Hibernate <literal>Session</literal> for <emphasis>every</emphasis> database operation. So even if you see it a few more times in the following (very trivial) examples, consider <emphasis>session-per-operation</emphasis> an anti-pattern. A real (web) application is shown later in this tutorial."msgstr ""#: tutorial.xml:688(para) msgid "Have a look at <xref linkend=\"transactions\"/> for more information about transaction handling and demarcation. We also skipped any error handling and rollback in the previous example."msgstr ""#: tutorial.xml:694(para) msgid "To run this first routine we have to add a callable target to the Ant build file:"msgstr ""#: tutorial.xml:705(para) msgid "The value of the <literal>action</literal> argument is set on the command line when calling the target:"msgstr ""#: tutorial.xml:712(para) msgid "You should see, after compilation, Hibernate starting up and, depending on your configuration, lots of log output. At the end you will find the following line:"msgstr ""#: tutorial.xml:719(para) msgid "This is the <literal>INSERT</literal> executed by Hibernate, the question marks represent JDBC bind parameters. To see the values bound as arguments, or to reduce the verbosity of the log, check your <literal>log4j.properties</literal>."msgstr ""#: tutorial.xml:725(para) msgid "Now we'd like to list stored events as well, so we add an option to the main method:"msgstr ""#: tutorial.xml:741(para) msgid "We also add a new <literal>listEvents() method</literal>:"msgstr ""#: tutorial.xml:758(para) msgid "What we do here is use an HQL (Hibernate Query Language) query to load all existing <literal>Event</literal> objects from the database. Hibernate will generate the appropriate SQL, send it to the database and populate <literal>Event</literal> objects with the data. You can create more complex queries with HQL, of course."msgstr ""#: tutorial.xml:765(para) msgid "Now, to execute and test all of this, follow these steps:"msgstr ""#: tutorial.xml:771(para) msgid "Run <literal>ant run -Daction=store</literal> to store something into the database and, of course, to generate the database schema before through hbm2ddl."msgstr ""#: tutorial.xml:777(para) msgid "Now disable hbm2ddl by commenting out the property in your <literal>hibernate.cfg.xml</literal> file. Usually you only leave it turned on in continous unit testing, but another run of hbm2ddl would <emphasis>drop</emphasis> everything you have stored - the <literal>create</literal> configuration setting actually translates into \"drop all tables from the schema, then re-create all tables, when the SessionFactory is build\"."msgstr ""#: tutorial.xml:787(para) msgid "If you now call Ant with <literal>-Daction=list</literal>, you should see the events you have stored so far. You can of course also call the <literal>store</literal> action a few times more."msgstr ""#: tutorial.xml:793(para) msgid "Note: Most new Hibernate users fail at this point and we see questions about <emphasis>Table not found</emphasis> error messages regularly. However, if you follow the steps outlined above you will not have this problem, as hbm2ddl creates the database schema on the first run, and subsequent application restarts will use this schema. If you change the mapping and/or database schema, you have to re-enable hbm2ddl once again."msgstr ""#: tutorial.xml:806(title) msgid "Part 2 - Mapping associations"msgstr ""#: tutorial.xml:808(para) msgid "We mapped a persistent entity class to a table. Let's build on this and add some class associations. First we'll add people to our application, and store a list of events they participate in."msgstr ""#: tutorial.xml:814(title) msgid "Mapping the Person class"msgstr ""#: tutorial.xml:816(para) msgid "The first cut of the <literal>Person</literal> class is simple:"msgstr ""#: tutorial.xml:835(para) msgid "Create a new mapping file called <literal>Person.hbm.xml</literal> (don't forget the DTD reference at the top):"msgstr ""#: tutorial.xml:853(para) msgid "Finally, add the new mapping to Hibernate's configuration:"msgstr ""#: tutorial.xml:860(para) msgid "We'll now create an association between these two entities. Obviously, persons can participate in events, and events have participants. The design questions we have to deal with are: directionality, multiplicity, and collection behavior."msgstr ""#: tutorial.xml:870(title) msgid "A unidirectional Set-based association"msgstr ""#: tutorial.xml:872(para) msgid "We'll add a collection of events to the <literal>Person</literal> class. That way we can easily navigate to the events for a particular person, without executing an explicit query - by calling <literal>aPerson.getEvents()</literal>. We use a Java collection, a <literal>Set</literal>, because the collection will not contain duplicate elements and the ordering is not relevant for us."msgstr ""#: tutorial.xml:879(para) msgid "We need a unidirectional, many-valued associations, implemented with a <literal>Set</literal>. Let's write the code for this in the Java classes and then map it:"msgstr ""#: tutorial.xml:897(para) msgid "Before we map this association, think about the other side. Clearly, we could just keep this unidirectional. Or, we could create another collection on the <literal>Event</literal>, if we want to be able to navigate it bi-directional, i.e. <literal>anEvent.getParticipants()</literal>. This is not necessary, from a functional perspective. You could always execute an explicit query to retrieve the participants for a particular event. This is a design choice left to you, but what is clear from this discussion is the multiplicity of the association: \"many\" valued on both sides, we call this a <emphasis>many-to-many</emphasis> association. Hence, we use Hibernate's many-to-many mapping:"msgstr ""#: tutorial.xml:923(para) msgid "Hibernate supports all kinds of collection mappings, a <literal><set></literal> being most common. For a many-to-many association (or <emphasis>n:m</emphasis> entity relationship), an association table is needed. Each row in this table represents a link between a person and an event. The table name is configured with the <literal>table</literal> attribute of the <literal>set</literal> element. The identifier column name in the association, for the person's side, is defined with the <literal><key></literal> element, the column name for the event's side with the <literal>column</literal> attribute of the <literal><many-to-many></literal>. You also have to tell Hibernate the class of the objects in your collection (correct: the class on the other side of the collection of references)."msgstr ""#: tutorial.xml:935(para) msgid "The database schema for this mapping is therefore:"msgstr ""#: tutorial.xml:956(title) msgid "Working the association"msgstr ""#: tutorial.xml:958(para) msgid "Let's bring some people and events together in a new method in <literal>EventManager</literal>:"msgstr ""#: tutorial.xml:975(para) msgid "After loading a <literal>Person</literal> and an <literal>Event</literal>, simply modify the collection using the normal collection methods. As you can see, there is no explicit call to <literal>update()</literal> or <literal>save()</literal>, Hibernate automatically detects that the collection has been modified and needs to be updated. This is called <emphasis>automatic dirty checking</emphasis>, and you can also try it by modifying the name or the date property of any of your objects. As long as they are in <emphasis>persistent</emphasis> state, that is, bound to a particular Hibernate <literal>Session</literal> (i.e. they have been just loaded or saved in a unit of work), Hibernate monitors any changes and executes SQL in a write-behind fashion. The process of synchronizing the memory state with the database, usually only at the end of a unit of work, is called <emphasis>flushing</emphasis>. In our code, the unit of work ends with a commit (or rollback) of the database transaction - as defined by the <literal>thread</literal> configuration option for the <literal>CurrentSessionContext</literal> class."msgstr ""#: tutorial.xml:990(para) msgid "You might of course load person and event in different units of work. Or you modify an object outside of a <literal>Session</literal>, when it is not in persistent state (if it was persistent before, we call this state <emphasis>detached</emphasis>). You can even modify a collection when it is detached:"msgstr ""#: tutorial.xml:1025(para) msgid "The call to <literal>update</literal> makes a detached object persistent again, you could say it binds it to a new unit of work, so any modifications you made to it while detached can be saved to the database. This includes any modifications (additions/deletions) you made to a collection of that entity object."msgstr ""#: tutorial.xml:1032(para) msgid "Well, this is not much use in our current situation, but it's an important concept you can design into your own application. For now, complete this exercise by adding a new action to the <literal>EventManager</literal>'s main method and call it from the command line. If you need the identifiers of a person and an event - the <literal>save()</literal> method returns it (you might have to modify some of the previous methods to return that identifier):"msgstr ""#: tutorial.xml:1047(para) msgid "This was an example of an association between two equally important classes, two entities. As mentioned earlier, there are other classes and types in a typical model, usually \"less important\". Some you have already seen, like an <literal>int</literal> or a <literal>String</literal>. We call these classes <emphasis>value types</emphasis>, and their instances <emphasis>depend</emphasis> on a particular entity. Instances of these types don't have their own identity, nor are they shared between entities (two persons don't reference the same <literal>firstname</literal> object, even if they have the same first name). Of course, value types can not only be found in the JDK (in fact, in a Hibernate application all JDK classes are considered value types), but you can also write dependent classes yourself, <literal>Address</literal> or <literal>MonetaryAmount</literal>, for example."msgstr ""#: tutorial.xml:1060(para)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -