📄 tutorial.pot
字号:
"\n" " // Accessor methods for all properties, private setter for 'id'\n" "\n" "}]]>"msgstr ""#. Tag: para#: tutorial.xml:609#, no-c-formatmsgid "Create a new mapping file called <literal>Person.hbm.xml</literal> (don't forget the DTD reference at the top):"msgstr ""#. Tag: programlisting#: tutorial.xml:614#, no-c-formatmsgid "" "<![CDATA[<hibernate-mapping>\n" "\n" " <class name=\"events.Person\" table=\"PERSON\">\n" " <id name=\"id\" column=\"PERSON_ID\">\n" " <generator class=\"native\"/>\n" " </id>\n" " <property name=\"age\"/>\n" " <property name=\"firstname\"/>\n" " <property name=\"lastname\"/>\n" " </class>\n" "\n" "</hibernate-mapping>]]>"msgstr ""#. Tag: para#: tutorial.xml:616#, no-c-formatmsgid "Finally, add the new mapping to Hibernate's configuration:"msgstr ""#. Tag: programlisting#: tutorial.xml:620#, no-c-formatmsgid "" "<![CDATA[<mapping resource=\"events/Event.hbm.xml\"/>\n" "<mapping resource=\"events/Person.hbm.xml\"/>]]>"msgstr ""#. Tag: para#: tutorial.xml:622#, no-c-formatmsgid "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 ""#. Tag: title#: tutorial.xml:632#, no-c-formatmsgid "A unidirectional Set-based association"msgstr ""#. Tag: para#: tutorial.xml:634#, no-c-formatmsgid "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 ""#. Tag: para#: tutorial.xml:641#, no-c-formatmsgid "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 ""#. Tag: programlisting#: tutorial.xml:646#, no-c-formatmsgid "" "<![CDATA[public class Person {\n" "\n" " private Set events = new HashSet();\n" "\n" " public Set getEvents() {\n" " return events;\n" " }\n" "\n" " public void setEvents(Set events) {\n" " this.events = events;\n" " }\n" "}]]>"msgstr ""#. Tag: para#: tutorial.xml:648#, no-c-formatmsgid "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 ""#. Tag: programlisting#: tutorial.xml:659#, no-c-formatmsgid "" "<![CDATA[<class name=\"events.Person\" table=\"PERSON\">\n" " <id name=\"id\" column=\"PERSON_ID\">\n" " <generator class=\"native\"/>\n" " </id>\n" " <property name=\"age\"/>\n" " <property name=\"firstname\"/>\n" " <property name=\"lastname\"/>\n" "\n" " <set name=\"events\" table=\"PERSON_EVENT\">\n" " <key column=\"PERSON_ID\"/>\n" " <many-to-many column=\"EVENT_ID\" class=\"events.Event\"/>\n" " </set>\n" "\n" "</class>]]>"msgstr ""#. Tag: para#: tutorial.xml:661#, no-c-formatmsgid "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 ""#. Tag: para#: tutorial.xml:673#, no-c-formatmsgid "The database schema for this mapping is therefore:"msgstr ""#. Tag: programlisting#: tutorial.xml:677#, no-c-formatmsgid "" "<![CDATA[\n" " _____________ __________________\n" " | | | | _____________\n" " | EVENTS | | PERSON_EVENT | | |\n" " |_____________| |__________________| | PERSON |\n" " | | | | |_____________|\n" " | *EVENT_ID | <--> | *EVENT_ID | | |\n" " | EVENT_DATE | | *PERSON_ID | <--> | *PERSON_ID |\n" " | TITLE | |__________________| | AGE |\n" " |_____________| | FIRSTNAME |\n" " | LASTNAME |\n" " |_____________|\n" " ]]>"msgstr ""#. Tag: title#: tutorial.xml:682#, no-c-formatmsgid "Working the association"msgstr ""#. Tag: para#: tutorial.xml:684#, no-c-formatmsgid "Let's bring some people and events together in a new method in <literal>EventManager</literal>:"msgstr ""#. Tag: programlisting#: tutorial.xml:688#, no-c-formatmsgid "" "<![CDATA[private void addPersonToEvent(Long personId, Long eventId) {\n" "\n" " Session session = HibernateUtil.getSessionFactory().getCurrentSession();\n" " session.beginTransaction();\n" "\n" " Person aPerson = (Person) session.load(Person.class, personId);\n" " Event anEvent = (Event) session.load(Event.class, eventId);\n" "\n" " aPerson.getEvents().add(anEvent);\n" "\n" " session.getTransaction().commit();\n" "}]]>"msgstr ""#. Tag: para#: tutorial.xml:690#, no-c-formatmsgid "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 ""#. Tag: para#: tutorial.xml:705#, no-c-formatmsgid "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 ""#. Tag: programlisting#: tutorial.xml:712#, no-c-formatmsgid "" "<![CDATA[private void addPersonToEvent(Long personId, Long eventId) {\n" "\n" " Session session = HibernateUtil.getSessionFactory().getCurrentSession();\n" " session.beginTransaction();\n" "\n" " Person aPerson = (Person) session\n" " .createQuery(\"select p from Person p left join fetch p.events where p.id = :pid\")\n" " .setParameter(\"pid\", personId)\n" " .uniqueResult(); // Eager fetch the collection so we can use it detached\n" "\n" " Event anEvent = (Event) session.load(Event.class, eventId);\n" "\n" " session.getTransaction().commit();\n" "\n" " // End of first unit of work\n" "\n" " aPerson.getEvents().add(anEvent); // aPerson (and its collection) is detached\n" "\n" " // Begin second unit of work\n" "\n" " Session session2 = HibernateUtil.getSessionFactory().getCurrentSession();\n" " session2.beginTransaction();\n" "\n" " session2.update(aPerson); // Reattachment of aPerson\n" "\n" " session2.getTransaction().commit();\n" "}]]>"msgstr ""#. Tag: para#: tutorial.xml:714#, no-c-formatmsgid "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 ""#. Tag: para#: tutorial.xml:721#, no-c-formatmsgid "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 ""#. Tag: programlisting#: tutorial.xml:729#, no-c-formatmsgid "" "<![CDATA[else if (args[0].equals(\"addpersontoevent\")) {\n" " Long eventId = mgr.createAndStoreEvent(\"My Event\", new Date());\n" " Long personId = mgr.createAndStorePerson(\"Foo\", \"Bar\");\n" " mgr.addPersonToEvent(personId, eventId);\n" " System.out.println(\"Added person \" + personId + \" to event \" + eventId);\n" "}]]>"msgstr ""#. Tag: para#: tutorial.xml:731#, no-c-formatmsgid "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 ""#. Tag: para#: tutorial.xml:744#, no-c-formatmsgid "You can also design a collection of value types. This is conceptually very different from a collection of references to other entities, but looks almost the same in Java."msgstr ""#. Tag: title#: tutorial.xml:752#, no-c-formatmsgid "Collection of values"msgstr ""#. Tag: para#: tutorial.xml:754#, no-c-formatmsgid "We add a collection of value typed objects to the <literal>Person</literal> entity. We want to store email addresses, so the type we use is <literal>String</literal>, and the collection is again a <literal>Set</literal>:"msgstr ""#. Tag: programlisting#: tutorial.xml:759#, no-c-formatmsgid "" "<![CDATA[private Set emailAddresses = new HashSet();\n" "\n" "public Set getEmailAddresses() {\n" " return emailAddresses;\n" "}\n" "\n" "public void setEmailAddresses(Set emailAddresses) {\n" " this.emailAddresses = emailAddresses;\n" "}]]>"msgstr ""#. Tag: para#: tutorial.xml:761#, no-c-formatmsgid "The mapping of this <literal>Set</literal>:"msgstr ""#. Tag: programlisting#: tutorial.xml:765#, no-c-formatmsgid "" "<![CDATA[<set name=\"emailAddresses\" table=\"PERSON_EMAIL_ADDR\">\n" " <key column=\"PERSON_ID\"/>\n" " <element type=\"string\" column=\"EMAIL_ADDR\"/>\n" "</set>]]>"msgstr ""
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -