📄 tutorial.pot
字号:
#. Tag: para#: tutorial.xml:767#, no-c-formatmsgid "The difference compared with the earlier mapping is the <literal>element</literal> part, which tells Hibernate that the collection does not contain references to another entity, but a collection of elements of type <literal>String</literal> (the lowercase name tells you it's a Hibernate mapping type/converter). Once again, the <literal>table</literal> attribute of the <literal>set</literal> element determines the table name for the collection. The <literal>key</literal> element defines the foreign-key column name in the collection table. The <literal>column</literal> attribute in the <literal>element</literal> element defines the column name where the <literal>String</literal> values will actually be stored."msgstr ""#. Tag: para#: tutorial.xml:777#, no-c-formatmsgid "Have a look at the updated schema:"msgstr ""#. Tag: programlisting#: tutorial.xml:781#, no-c-formatmsgid "" "<![CDATA[\n" " _____________ __________________\n" " | | | | _____________\n" " | EVENTS | | PERSON_EVENT | | | ___________________\n" " |_____________| |__________________| | PERSON | | |\n" " | | | | |_____________| | PERSON_EMAIL_ADDR |\n" " | *EVENT_ID | <--> | *EVENT_ID | | | |___________________|\n" " | EVENT_DATE | | *PERSON_ID | <--> | *PERSON_ID | <--> | *PERSON_ID |\n" " | TITLE | |__________________| | AGE | | *EMAIL_ADDR |\n" " |_____________| | FIRSTNAME | |___________________|\n" " | LASTNAME |\n" " |_____________|\n" " ]]>"msgstr ""#. Tag: para#: tutorial.xml:783#, no-c-formatmsgid "You can see that the primary key of the collection table is in fact a composite key, using both columns. This also implies that there can't be duplicate email addresses per person, which is exactly the semantics we need for a set in Java."msgstr ""#. Tag: para#: tutorial.xml:789#, no-c-formatmsgid "You can now try and add elements to this collection, just like we did before by linking persons and events. It's the same code in Java:"msgstr ""#. Tag: programlisting#: tutorial.xml:794#, no-c-formatmsgid "" "<![CDATA[private void addEmailToPerson(Long personId, String emailAddress) {\n" "\n" " Session session = HibernateUtil.getSessionFactory().getCurrentSession();\n" " session.beginTransaction();\n" "\n" " Person aPerson = (Person) session.load(Person.class, personId);\n" "\n" " // The getEmailAddresses() might trigger a lazy load of the collection\n" " aPerson.getEmailAddresses().add(emailAddress);\n" "\n" " session.getTransaction().commit();\n" "}]]>"msgstr ""#. Tag: para#: tutorial.xml:796#, no-c-formatmsgid "This time we didn't use a <emphasis>fetch</emphasis> query to initialize the collection. Hence, the call to its getter method will trigger an additional select to initialize it, so we can add an element to it. Monitor the SQL log and try to optimize this with an eager fetch."msgstr ""#. Tag: title#: tutorial.xml:806#, no-c-formatmsgid "Bi-directional associations"msgstr ""#. Tag: para#: tutorial.xml:808#, no-c-formatmsgid "Next we are going to map a bi-directional association - making the association between person and event work from both sides in Java. Of course, the database schema doesn't change, we still have many-to-many multiplicity. A relational database is more flexible than a network programming language, so it doesn't need anything like a navigation direction - data can be viewed and retrieved in any possible way."msgstr ""#. Tag: para#: tutorial.xml:816#, no-c-formatmsgid "First, add a collection of participants to the <literal>Event</literal> Event class:"msgstr ""#. Tag: programlisting#: tutorial.xml:820#, no-c-formatmsgid "" "<![CDATA[private Set participants = new HashSet();\n" "\n" "public Set getParticipants() {\n" " return participants;\n" "}\n" "\n" "public void setParticipants(Set participants) {\n" " this.participants = participants;\n" "}]]>"msgstr ""#. Tag: para#: tutorial.xml:822#, no-c-formatmsgid "Now map this side of the association too, in <literal>Event.hbm.xml</literal>."msgstr ""#. Tag: programlisting#: tutorial.xml:826#, no-c-formatmsgid "" "<![CDATA[<set name=\"participants\" table=\"PERSON_EVENT\" inverse=\"true\">\n" " <key column=\"EVENT_ID\"/>\n" " <many-to-many column=\"PERSON_ID\" class=\"events.Person\"/>\n" "</set>]]>"msgstr ""#. Tag: para#: tutorial.xml:828#, no-c-formatmsgid "As you see, these are normal <literal>set</literal> mappings in both mapping documents. Notice that the column names in <literal>key</literal> and <literal>many-to-many</literal> are swapped in both mapping documents. The most important addition here is the <literal>inverse=\"true\"</literal> attribute in the <literal>set</literal> element of the <literal>Event</literal>'s collection mapping."msgstr ""#. Tag: para#: tutorial.xml:836#, no-c-formatmsgid "What this means is that Hibernate should take the other side - the <literal>Person</literal> class - when it needs to find out information about the link between the two. This will be a lot easier to understand once you see how the bi-directional link between our two entities is created ."msgstr ""#. Tag: title#: tutorial.xml:845#, no-c-formatmsgid "Working bi-directional links"msgstr ""#. Tag: para#: tutorial.xml:847#, no-c-formatmsgid "First, keep in mind that Hibernate does not affect normal Java semantics. How did we create a link between a <literal>Person</literal> and an <literal>Event</literal> in the unidirectional example? We added an instance of <literal>Event</literal> to the collection of event references, of an instance of <literal>Person</literal>. So, obviously, if we want to make this link working bi-directional, we have to do the same on the other side - adding a <literal>Person</literal> reference to the collection in an <literal>Event</literal>. This \"setting the link on both sides\" is absolutely necessary and you should never forget doing it."msgstr ""#. Tag: para#: tutorial.xml:857#, no-c-formatmsgid "Many developers program defensively and create link management methods to correctly set both sides, e.g. in <literal>Person</literal>:"msgstr ""#. Tag: programlisting#: tutorial.xml:862#, no-c-formatmsgid "" "<![CDATA[protected Set getEvents() {\n" " return events;\n" "}\n" "\n" "protected void setEvents(Set events) {\n" " this.events = events;\n" "}\n" "\n" "public void addToEvent(Event event) {\n" " this.getEvents().add(event);\n" " event.getParticipants().add(this);\n" "}\n" "\n" "public void removeFromEvent(Event event) {\n" " this.getEvents().remove(event);\n" " event.getParticipants().remove(this);\n" "}]]>"msgstr ""#. Tag: para#: tutorial.xml:864#, no-c-formatmsgid "Notice that the get and set methods for the collection are now protected - this allows classes in the same package and subclasses to still access the methods, but prevents everybody else from messing with the collections directly (well, almost). You should probably do the same with the collection on the other side."msgstr ""#. Tag: para#: tutorial.xml:871#, no-c-formatmsgid "What about the <literal>inverse</literal> mapping attribute? For you, and for Java, a bi-directional link is simply a matter of setting the references on both sides correctly. Hibernate however doesn't have enough information to correctly arrange SQL <literal>INSERT</literal> and <literal>UPDATE</literal> statements (to avoid constraint violations), and needs some help to handle bi-directional associations properly. Making one side of the association <literal>inverse</literal> tells Hibernate to basically ignore it, to consider it a <emphasis>mirror</emphasis> of the other side. That's all that is necessary for Hibernate to work out all of the issues when transformation a directional navigation model to a SQL database schema. The rules you have to remember are straightforward: All bi-directional associations need one side as <literal>inverse</literal>. In a one-to-many association it has to be the many-side, in many-to-many association you can pick either side, there is no difference."msgstr ""#. Tag: title#: tutorial.xml:889#, no-c-formatmsgid "Part 3 - The EventManager web application"msgstr ""#. Tag: para#: tutorial.xml:891#, no-c-formatmsgid "Let's turn the following discussion into a small web application..."msgstr ""#. Tag: para#: tutorial.xml:895#, no-c-formatmsgid "A Hibernate web application uses <literal>Session</literal> and <literal>Transaction</literal> almost like a standalone application. However, some common patterns are useful. We now write an <literal>EventManagerServlet</literal>. This servlet can list all events stored in the database, and it provides an HTML form to enter new events."msgstr ""#. Tag: title#: tutorial.xml:903#, no-c-formatmsgid "Writing the basic servlet"msgstr ""#. Tag: para#: tutorial.xml:905#, no-c-formatmsgid "Create a new class in your source directory, in the <literal>events</literal> package:"msgstr ""#. Tag: programlisting#: tutorial.xml:910#, no-c-formatmsgid "" "<![CDATA[package events;\n" "\n" "// Imports\n" "\n" "public class EventManagerServlet extends HttpServlet {\n" "\n" " // Servlet code\n" "}]]>"msgstr ""#. Tag: para#: tutorial.xml:912#, no-c-formatmsgid "The servlet handles HTTP <literal>GET</literal> requests only, hence, the method we implement is <literal>doGet()</literal>:"msgstr ""#. Tag: programlisting#: tutorial.xml:917#, no-c-formatmsgid "" "<![CDATA[protected void doGet(HttpServletRequest request,\n" " HttpServletResponse response)\n" " throws ServletException, IOException {\n" "\n" " SimpleDateFormat dateFormatter = new SimpleDateFormat(\"dd.MM.yyyy\");\n" "\n" " try {\n" " // Begin unit of work\n" " HibernateUtil.getSessionFactory()\n" " .getCurrentSession().beginTransaction();\n" "\n" " // Process request and render page...\n" "\n" " // End unit of work\n" " HibernateUtil.getSessionFactory()\n" " .getCurrentSession().getTransaction().commit();\n" "\n" " } catch (Exception ex) {\n" " HibernateUtil.getSessionFactory()\n" " .getCurrentSession().getTransaction().rollback();\n" " throw new ServletException(ex);\n" " }\n" "\n" "}]]>"msgstr ""#. Tag: para#: tutorial.xml:919#, no-c-formatmsgid "The pattern we are applying here is called <emphasis>session-per-request</emphasis>. When a request hits the servlet, a new Hibernate <literal>Session</literal> is opened through the first call to <literal>getCurrentSession()</literal> on the <literal>SessionFactory</literal>. Then a database transaction is started—all data access as to occur inside a transaction, no matter if data is read or written (we don't use the auto-commit mode in applications)."msgstr ""#. Tag: para#: tutorial.xml:928#, no-c-formatmsgid "Do <emphasis>not</emphasis> use a new Hibernate <literal>Session</literal> for every database operation. Use one Hibernate <literal>Session</literal> that is scoped to the whole request. Use <literal>getCurrentSession()</literal>, so that it is automatically bound to the current Java thread."msgstr ""#. Tag: para#: tutorial.xml:935#, no-c-formatmsgid "Next, the possible actions of the request are processed and the response HTML is rendered. We'll get to that part soon."msgstr ""#. Tag: para#: tutorial.xml:940#, no-c-formatmsgid "Finally, the unit of work ends when processing and rendering is complete. If any problem occurred during processing or rendering, an exception will be thrown and the database transaction rolled back. This completes the <literal>session-per-request</literal> pattern. Instead of the transaction demarcation code in every servlet you could also write a servlet filter. See the Hibernate website and Wiki for more information about this pattern, called <emphasis>Open Session in View</emphasis>—you'll need it as soon as you consider rendering your view in JSP, not in a servlet."msgstr ""#. Tag: title#: tutorial.xml:954#, no-c-formatmsgid "Processing and rendering"msgstr ""#. Tag: pa
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -