⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch03.html

📁 java2高级编程
💻 HTML
📖 第 1 页 / 共 4 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"><HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1"><META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css"><META NAME="GENERATOR" CONTENT="Adobe FrameMaker 6.0/HTML Export Filter"><LINK REL="STYLESHEET" HREF="CH03.css" CHARSET="ISO-8859-1" TYPE="text/css"><TITLE> Covered in this Chapter</TITLE></HEAD><BODY BGCOLOR="#ffffff"><P CLASS="CT"><A NAME="pgfId-1087399"></A>3</P><P CLASS="CT"><A NAME="pgfId-1087401"></A><A NAME="61341"></A>Data and Transaction Management</P><P CLASS="Body"><A NAME="pgfId-1087402"></A>When you use the Enterprise JavaBeans architecture, data is written to and read from the database without your writing any SQL code to do it. But what if you want to write your own SQL commands or manage transactions? You can override the built-in container-managed persistence and implement bean-managed persistence using your own data storage and transaction-management code. </P><P CLASS="Body"><A NAME="pgfId-1087403"></A>Bean-managed persistence comes in handy when you want more control than the container-managed persistence provides. For example, you might want to override the default of most containers to map the data in one bean to one row in a table, implement your own finder methods, or customize caching. </P><P CLASS="Body"><A NAME="pgfId-1087404"></A>This chapter converts the <EM CLASS="CODE">RegistrationBean</EM> class from Chapter 2, Auction House Application, to provide its own SQL commands for reading from and writing to the database. It also explains how you can write your own transaction-management code and implement a more complex search than you can get with the finder-based search described in Chapter 2. </P><DIV><H4 CLASS="A"><A NAME="pgfId-1087405"></A>Covered in this Chapter</H4><UL><LI CLASS="BL"><A NAME="pgfId-1087406"></A>Bean-Managed Persistence and the JDBC Platform (page 38)</LI><LI CLASS="BL"><A NAME="pgfId-1087407"></A>Managing Transactions (page 41) </LI><LI CLASS="BL"><A NAME="pgfId-1087408"></A>Bean-Managed Finder Methods (page 49)</LI></UL></DIV><DIV><H4 CLASS="A"><A NAME="pgfId-1087410"></A><A NAME="89350"></A>Bean-Managed Persistence and the JDBC Platform</H4><P CLASS="Body"><A NAME="pgfId-1087412"></A><A NAME="marker-1087411"></A>There might be times when you want to override container-managed persistence and implement entity or session bean methods to use the <A NAME="marker-1087413"></A><A NAME="marker-1087414"></A>SQL commands you provide. This type of bean-managed persistence can be useful if you need to improve performance or need to map data in multiple beans to one row in a database table. This section shows you how to convert the <EM CLASS="CODE">RegistrationBean</EM><EM CLASS="A"> </EM>class to access the database with the JDBC <EM CLASS="CODE">PreparedStatement</EM> class. </P><DIV><H5 CLASS="B"><A NAME="pgfId-1087415"></A>Connect to Database</H5><P CLASS="Body"><A NAME="pgfId-1087417"></A><A NAME="marker-1087416"></A>This version of the <EM CLASS="CODE">RegistrationBean</EM> (SQL) class establishes a connection to the database by instantiating a static <EM CLASS="CODE">Driver</EM><A NAME="marker-1087418"></A> class and providing the <EM CLASS="CODE">getConnection</EM><A NAME="marker-1087419"></A> method. The <EM CLASS="CODE">getConnection</EM> method queries the static <EM CLASS="CODE">DriverManager</EM><A NAME="marker-1087420"></A> class for a registered database driver that matches the <A NAME="marker-1087421"></A>Uniform Resource Locator (URL). In this case, the URL is <EM CLASS="CODE">weblogic.jdbc.jts.Driver</EM><A NAME="marker-1087422"></A>. </P><PRE CLASS="CODE"><A NAME="pgfId-1087423"></A>//Create static instance of database driverstatic {  new weblogic.jdbc.jts.Driver();}//Get registered driver from static instance</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087428"></A><A NAME="marker-1087424"></A><A NAME="java.sql.DriverManager class"></A><A NAME="DriverManager class"></A><A NAME="getConnection method"></A>public Connection getConnection() throws SQLException{  return DriverManager.getConnection( &quot;jdbc:weblogic:jts:ejbPool&quot;);}</PRE></DIV><DIV><H5 CLASS="B"><A NAME="pgfId-1087429"></A>Create Method</H5><P CLASS="Body"><A NAME="pgfId-1087432"></A><A NAME="marker-1087430"></A>The <EM CLASS="CODE">ejbCreate</EM><A NAME="marker-1087431"></A> method assigns values to data member variables, gets a connection to the database, and creates an instance of the <EM CLASS="CODE">java.sql.PreparedStatement</EM> class to execute the SQL statement for writing the data to the <EM CLASS="CODE">registration</EM> table in the database. </P><P CLASS="Body"><A NAME="pgfId-1087434"></A>A <EM CLASS="CODE">PreparedStatement</EM><A NAME="marker-1087433"></A> object is created from a SQL statement, which is sent to the database and precompiled before any data is sent. You call the appropriate <EM CLASS="CODE">set&lt;type&gt;</EM> statements on the <EM CLASS="CODE">PreparedStatement</EM> object to send the data. Keeping the <EM CLASS="CODE">PreparedStatement</EM> and <EM CLASS="CODE">Connection</EM><A NAME="marker-1087435"></A> objects as private instance variables greatly reduces overhead because the SQL statement does not have to be compiled every time data is sent. </P><P CLASS="Body"><A NAME="pgfId-1087438"></A>The last thing the <EM CLASS="CODE">ejbCreate</EM> method does is to create a <A NAME="marker-1087436"></A><A NAME="marker-1087437"></A>primary key class with the user ID, and then return it to the container. </P><PRE CLASS="CODE"><A NAME="pgfId-1087439"></A>public RegistrationPK ejbCreate(String theuser, String password,                                 String emailaddress, String creditcard)                                 throws CreateException, RemoteException {  this.theuser=theuser;  this.password=password;  this.emailaddress=emailaddress;  this.creditcard=creditcard;  this.balance=0;  try {    con=getConnection();</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087441"></A>//API Ref: <A NAME="31279"></A>PrepareStatement prepareStatement(String sql)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087446"></A>    <A NAME="marker-1087442"></A><A NAME="marker-1087443"></A><A NAME="marker-1087444"></A><A NAME="marker-1087445"></A>ps=con.prepareStatement(&quot;insert into registration (theuser, password,                             emailaddress, creditcard, balance)     values (  ?, ?, ?, ?, ?)&quot;);    ps.setString(1, theuser);    ps.setString(2, password);    ps.setString(3, emailaddress);    ps.setString(4, creditcard);    ps.setDouble(5, balance);    if (ps.executeUpdate() != 1) {      throw new CreateException (&quot;JDBC did not create a row&quot;);    }    RegistrationPK primaryKey = new RegistrationPK();    primaryKey.theuser = theuser;    return primaryKey;    } catch (CreateException ce) {      throw ce;    } catch (SQLException sqe) {      throw new CreateException (sqe.getMessage());    } finally {      try {         ps.close();      } catch (Exception ignore) {}      try {         con.close();      } catch (Exception ignore) {}    }}</PRE></DIV><DIV><H5 CLASS="B"><A NAME="pgfId-1087447"></A>Load Method</H5><P CLASS="Body"><A NAME="pgfId-1087450"></A>The <EM CLASS="CODE">ejbLoad</EM><A NAME="marker-1087448"></A> <A NAME="marker-1087449"></A>method gets the primary key from the entity context and passes it to the <EM CLASS="CODE">refresh</EM> method, which loads the data. </P><PRE CLASS="CODE"><A NAME="pgfId-1087451"></A>  public void ejbLoad() throws RemoteException {    try {      refresh((RegistrationPK) ctx.getPrimaryKey());    } catch (FinderException fe) {      throw new RemoteException (fe.getMessage());    }  }</PRE></DIV><DIV><H5 CLASS="B"><A NAME="pgfId-1087452"></A>Refresh Method</H5><P CLASS="Body"><A NAME="pgfId-1087455"></A>The <EM CLASS="CODE">refresh</EM><A NAME="marker-1087453"></A><A NAME="marker-1087454"></A> method is programmer-supplied code to load the data from the database. It checks the primary key value, gets a connection to the database, and creates a <EM CLASS="CODE">PreparedStatement</EM> object for querying the database for the user specified in the primary key. Data is read from the database into a <EM CLASS="CODE">ResultSet</EM> and assigned to the global member variables so the <EM CLASS="CODE">RegistrationBean</EM> has the most up-to-date information for the user. </P><PRE CLASS="CODE"><A NAME="pgfId-1087456"></A>private void refresh(RegistrationPK pk)throws FinderException, RemoteException {  if (pk == null) {    throw new RemoteException (&quot;primary key cannot be null&quot;);  }  Connection con = null;  PreparedStatement ps = null;  try {     con=getConnection();     ps=con.prepareStatement(&quot;select password, emailaddress, creditcard,                             balance from registration where theuser = ?&quot;);     ps.setString(1, pk.theuser);     ps.executeQuery();</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087458"></A>//API Ref: <A NAME="47794"></A>ResultSet getResultSet()</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087460"></A>     <A NAME="marker-1087459"></A>ResultSet rs = ps.getResultSet();     if (rs.next()) {       theuser = pk.theuser;</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087462"></A>//API Ref: <A NAME="80343"></A>String getString(String columnName)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087467"></A>      <A NAME="marker-1087463"></A> <A NAME="marker-1087464"></A><A NAME="marker-1087465"></A><A NAME="marker-1087466"></A>password = rs.getString(1);       emailaddress = rs.getString(2);       creditcard = rs.getString(3);       balance = rs.getDouble(4);     } else {        throw new FinderException                     (&quot;Refresh: Registration (&quot;+ pk.theuser + &quot;) not found&quot;);     }  } catch (SQLException sqe) {     throw new RemoteException (sqe.getMessage());  }  finally {     try {        ps.close();     } catch (Exception ignore) {}     try {        con.close();     } catch (Exception ignore) {}  }}</PRE></DIV><DIV><H5 CLASS="B"><A NAME="pgfId-1087468"></A>Store Method</H5><P CLASS="Body"><A NAME="pgfId-1087470"></A><A NAME="marker-1087469"></A>This method gets a database connection and creates a <EM CLASS="CODE">PreparedStatement</EM> to update the database. </P><PRE CLASS="CODE"><A NAME="pgfId-1087471"></A>public void ejbStore() throws RemoteException {  Connection con = null;  PreparedStatement ps = null;  try {     con = getConnection();</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087473"></A>//API Ref: <A NAME="62602"></A>PrepareStatement prepareStatement(String sql)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087476"></A>    <A NAME="marker-1087474"></A> <A NAME="marker-1087475"></A>ps = con.prepareStatement(&quot;update registration set password = ?,                    emailaddress = ?, creditcard = ?,                    balance = ? where theuser = ?&quot;);</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087478"></A>//API Ref: <A NAME="13380"></A>void setString(int index, String s)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087483"></A>     <A NAME="marker-1087479"></A><A NAME="marker-1087480"></A><A NAME="marker-1087481"></A><A NAME="marker-1087482"></A>ps.setString(1, password);     ps.setString(2, emailaddress);     ps.setString(3, creditcard);</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087485"></A>//API Ref: <A NAME="85840"></A>void setDouble(int index, double doublevalue)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087490"></A>    <A NAME="marker-1087486"></A> <A NAME="marker-1087487"></A><A NAME="marker-1087488"></A><A NAME="marker-1087489"></A>ps.setDouble(4, balance);     ps.setString(5, theuser);</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087492"></A>//API Ref: <A NAME="87770"></A>int executeUpdate()</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087497"></A>     <A NAME="marker-1087493"></A><A NAME="java.sql.PreparedStatement class"></A><A NAME="PreparedStatement class"></A><A NAME="executeUpdate method"></A>int i = ps.executeUpdate();     if (i == 0) {       throw new RemoteException (&quot;ejbStore: Registration           (&quot; + theuser + &quot;) not updated&quot;);     }  } catch (RemoteException re) {       throw re;  } catch (SQLException sqe) {       throw new RemoteException (sqe.getMessage());  } finally {    try {       ps.close();    } catch (Exception ignore) {}     try {        con.close();     } catch (Exception ignore) {}  }}<EM CLASS="A"></EM><A NAME="find"></A></PRE></DIV><DIV><H5 CLASS="B"><A NAME="pgfId-1087499"></A>Find Method</H5><P CLASS="Body"><A NAME="pgfId-1087501"></A>The <EM CLASS="CODE">ejbFindByPrimaryKey</EM><A NAME="marker-1087500"></A> method matches the signature of the <EM CLASS="CODE">findByPrimaryKey</EM> method in the <EM CLASS="CODE">RegistrationHome</EM> interface. It calls the <EM CLASS="CODE">refresh</EM> method to get or refresh the user data for the user specified by the primary key. The <A NAME="marker-1087502"></A>container-managed version of <EM CLASS="CODE">RegistrationBean</EM> does not implement this method because the container handles getting and refreshing the user data. </P><PRE CLASS="CODE"><A NAME="pgfId-1087503"></A>public RegistrationPK ejbFindByPrimaryKey(RegistrationPK pk)                       throws FinderException, RemoteException {  if ((pk == null) || (pk.theuser == null)) {     throw new FinderException (&quot;primary key cannot be null&quot;);  }  refresh(pk);  return pk;}</PRE></DIV></DIV><DIV>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -