📄 index.xtp
字号:
<document> <header> <title>CMP Transactions</title> <description> <p>Demonstrates protecting database updates using some basic transaction patterns.</p> <p>Topics:</p> <ul> <li>Stateless session beans for transaction management </li><li>UserTransaction for direct control of transactions </li><li>REQUIRED for updating methods </li><li>SUPPORTS for read-only methods </li></ul> <p>See also:</p> <ul> <li>The <a href="../cmp-basic-field/index.xtp">basic field CMP tutorial</a> for the basics of creating entity beans. </li><!-- <li>The <a href="../resin-xa/index.xtp">ResinEnhanced transaction</a> example for a simpler alternative to session beans. </li>--> </ul> </description> <type>tutorial</type> <tutorial-startpage>xa</tutorial-startpage> </header> <body> <summary/><s1 title="Files in this tutorial"><deftable><tr><td><viewfile-link file="WEB-INF/web.xml"/> </td><td>web.xml configuration</td></tr><tr><td><viewfile-link file="WEB-INF/classes/example/Course.java"/> </td><td>The course bean</td></tr><tr><td><viewfile-link file="WEB-INF/classes/example/SwapBean.java"/> </td><td>The swap stateless session bean</td></tr><tr><td><viewfile-link file="WEB-INF/classes/example/Swap.java"/> </td><td>The swap stateless session interface</td></tr><tr><td><viewfile-link file="WEB-INF/classes/example/SwapServlet.java"/> </td><td>The swap servlet</td></tr></deftable></s1><s1 title="Course Entity Definition"><s2 title="Database Schema"><example title="course.sql">CREATE TABLE ejb3_xa_courses ( id INTEGER PRIMARY KEY auto_increment, course VARCHAR(250), teacher VARCHAR(250));INSERT INTO basic_courses VALUES('Potions', 'Severus Snape');INSERT INTO basic_courses VALUES('Transfiguration', 'Minerva McGonagall');</example></s2><s2 title="Bean Implementation"><p>The Course is identical tothe <a href="../cmp-basic-field">basic field bean</a>. It usesFIELD enhancement to define the database columns.<example title="Course.java">@Entity(access=FIELD)@Table(name="ejb3_xa_courses")public class Course { @Id(generate=AUTO) @Column(name="id") private int _id; @Basic @Column(name="course") private String _course; @Basic @Column(name="teacher") private String _teacher;}</example></p></s2></s1><s1 title="Session Bean Implementation"><example title="SwapBean.java">import static javax.ejb.TransactionAttributeType.REQUIRED;@javax.ejb.Stateless(name="swap")public class SwapBean implements Swap { @javax.ejb.TransactionAttribute(REQUIRED) public void swap(Course a, Course b) { String teacher = a.getTeacher(); a.setTeacher(b.getTeacher()); b.setTeacher(teacher); }}</example><s2 title="TransactionAttribute REQUIRED"><p>The TransactionAttribute marks the transaction type ofthe method. The two most common types are REQUIRED and SUPPORTS.A REQUIRED method expects to modify the data and wants to ensurethe update is consistent. A SUPPORTS method will only read data, so itcan avoid the overhead of a transaction.</p><p>A transaction is the database equivalent of a <code>synchronized</code>lock. Transactions are somewhat more complicated locks because they need towork with multiple machines and possibly multiple databases, but they'restill just sophisticated locks. The typical transaction patterns are similarto familiar lock patterns.</p><p>A REQUIRED attribute tells Resin that the method must be protectedby a transaction. In this case, the swap needs protection fromsimultaneous threads trying to swap at the same time.</p><p>A SUPPORTS attribute would tell Resin that the method doesn't need atransaction, but the method should join any transaction that already exists.</p></s2></s1><s1 title="Swap Servlet"><example title="SwapServlet.java">import javax.ejb.EntityManager;import javax.transaction.UserTransaction;public class CourseServlet extends HttpServlet { @javax.ejb.Inject private EntityManager _manager; @javax.ejb.Inject private UserTransaction _uTrans; @javax.ejb.EJB(name="swap") private Swap _swap; ... private void doService(PrintWriter out) throws Exception { CourseBean []course = new CourseBean[2]; course[0] = (CourseBean) _manager.find("CourseBean", new Integer(1)); course[1] = (CourseBean) _manager.find("CourseBean", new Integer(2)); // swap the courses using the session bean _swap.swap(course[0], course[1]); // swap using a user transaction _uTrans.begin(); try { String teacher = course[0].getTeacher(); course[0].setTeacher(course[1].getTeacher()); course[1].setTeacher(teacher); } finally { _uTrans.commit(); } }}</example><s2 title="Dependency Injection"><p>The servlet needs to lookup the EntityManager, UserTransaction,and the Swap bean in JNDI.</p><deftable><tr><th>Object</th><th>JNDI</th></tr><tr><td>EntityManager</td><td>java:comp/EntityManager</td></tr><tr><td>UserTransaction</td><td>java:comp/UserTransaction</td></tr><tr><td>Swap</td><td>java:comp/env/ejb/swap</td></tr></deftable><p>Since Resin's servlets understand the EJB 3.0injection annotations, the tutorial can just annotate the setters andlet Resin configure them. In other cases, it may be necessary toput the JNDI lookup in the servlet's <code>init()</code> method.</p></s2><s2 title="SessionBean swap"><p>The first swap in the tutorial switches the teachers usinga stateless session bean.</p><example>// swap the courses using the session bean_swap.swap(course[0], course[1]);</example><p>Because the <code>swap</code> method was marked as transaction REQUIRED,Resin will start a transaction if none already exists. If the method exits cleanly, Resin will commit the transaction. If the method throws aRuntimeException, Resin will roll the transaction back.</p><p>The <code>swap</code> method will throw a runtime exception if thetransaction fails to commit. For example, the databse might detect adeadlock and roll the transaction back.</p></s2><s2 title="UserTransaction swap"><p>The second swap in the tutorial restores the teachers usingthe underlying <code>UserTransaction</code>. It's essentially identicalto the work that the transaction REQUIRED swap method provides.In fact, Resin implements the REQUIRED annotation using UserTransaction.</p><example>_uTrans.begin();try { String teacher = course[0].getTeacher(); course[0].setTeacher(course[1].getTeacher()); course[1].setTeacher(teacher);} finally { _uTrans.commit();}</example><p>The main differences between the two are the added capabilities of the REQUIRED.</p><ul><li>REQUIRED automatically rolls back on a RuntimeException</li><li>REQUIRED joins any existing transaction. In contrast,UserTransaction throws an exception if called in a transaction.</li></ul></s2></s1> </body></document>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -