﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-城市猎人-文章分类-EJB3</title><link>http://www.blogjava.net/sailor/category/32872.html</link><description>在一网情深的日子里，谁能说得清是苦是甜，只知道确定了就义无反顾</description><language>zh-cn</language><lastBuildDate>Mon, 14 Jul 2008 10:36:31 GMT</lastBuildDate><pubDate>Mon, 14 Jul 2008 10:36:31 GMT</pubDate><ttl>60</ttl><item><title>3、EJB3.0开发指南之SessionBean（下）---------有状态会话Bean</title><link>http://www.blogjava.net/sailor/articles/214709.html</link><dc:creator>sailor</dc:creator><author>sailor</author><pubDate>Mon, 14 Jul 2008 05:51:00 GMT</pubDate><guid>http://www.blogjava.net/sailor/articles/214709.html</guid><wfw:comment>http://www.blogjava.net/sailor/comments/214709.html</wfw:comment><comments>http://www.blogjava.net/sailor/articles/214709.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sailor/comments/commentRss/214709.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sailor/services/trackbacks/214709.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;原文：http://dev.rdxx.com/Java/EJB/2007/11/2819484113299.shtml<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;和无状态会话Bean一样，一个有状态会话Bean必须有一个业务接口，这个接口由会话Bean来实现，或者也可以由会话Bean来产生。这样，你可以只写一个文件，就可以生成业务逻辑实现类、远程接口、本地接口等。 <br />
<br />
　　在目前jboss的实现中，必须要有一个独立的业务接口。 <br />
<br />
　　这个接口不必实现EJBObject或者EJBLocalObject。 <br />
<br />
　　一个有状态会话Bean 必须使用Statelfull注释，以表明它是一个有状态的会话Bean。EJB容器将根据这个注释来判定它的类型。或者实现javax.ejb.SessionBean接口。 <br />
<br />
　　一个有状态的会话Bean可以实现setSessionContext方法，也可以不实现。 <br />
<br />
　　在EJB2.0中调用EJBObject.remove方法以达到从容器中删除有状态会话Bean的功能。在EJB3.0中只需在一些方法加上Remove注释。一旦这些被标记的方法被调用后，此EJB将从容器中删除。 <br />
<br />
　　一个有状态的会话Bean可以通过依赖注入获取容器的资源和环境属性。 <br />
<br />
　　在<a href="http://dev.rdxx.com/Java/JavaBase/Eclipse/" target="_blank">Eclipse</a>中导入本文提供的例子Stateful。 <br />
<br />
　　这个例子和无状态会话Bean的例子类似，下面只列出了不同的代码。 <br />
<br />
　　这个例子主要有5个文件： <br />
<br />
　　　Counter.java：业务接口。 <br />
<br />
　　　CounterBean.java：业务实现类。将来我们开发的EJB也都是这样命名（在接口名上加上Bean）。 <br />
<br />
　　　Client.java：测试EJB的客户端类。 <br />
<br />
　　　jndi.properties：jndi属性文件，提供访问jdni的基本配置属性。 <br />
<br />
　　　Build.xml：ant 配置文件，用以编译、发布、测试、清除EJB。 <br />
<br />
　　下面针对每个文件的内容做一个介绍。&nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Counter.java
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">&nbsp;1</span><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;javax.ejb.Remove;&nbsp;<br />
</span><span style="color: #008080">&nbsp;2</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />　　&#8230;&#8230;&nbsp;<br />
</span><span style="color: #008080">&nbsp;3</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />　　@Remote&nbsp;<br />
</span><span style="color: #008080">&nbsp;4</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
</span><span style="color: #008080">&nbsp;5</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />　　</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">interface</span><span style="color: #000000">&nbsp;Counter&nbsp;<br />
</span><span style="color: #008080">&nbsp;6</span><span style="color: #000000"><img id="Codehighlighter1_74_120_Open_Image" onclick="this.style.display='none'; Codehighlighter1_74_120_Open_Text.style.display='none'; Codehighlighter1_74_120_Closed_Image.style.display='inline'; Codehighlighter1_74_120_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_74_120_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_74_120_Closed_Text.style.display='none'; Codehighlighter1_74_120_Open_Image.style.display='inline'; Codehighlighter1_74_120_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" />　　</span><span id="Codehighlighter1_74_120_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_74_120_Open_Text"><span style="color: #000000">{&nbsp;<br />
</span><span style="color: #008080">&nbsp;7</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　&#8230;&#8230;&nbsp;<br />
</span><span style="color: #008080">&nbsp;8</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　@Remove&nbsp;<br />
</span><span style="color: #008080">&nbsp;9</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;clean();&nbsp;<br />
</span><span style="color: #008080">10</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />　　}</span></span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">11</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span></div>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这个接口很简单，和无状态会话Bean基本相同，但新增加了一个Clean方法，并为此方法加上Remove注释。一旦此方法被执行完毕，此Bean将被从容器中删除。 <br />
<br />
　　JBOSS默认使用接口的全称作为它的JNDI名。在上面的例子中，它的全称就是：com.kuaff.ejb3.stateful.Counter，你也可以通过Counter.class得到。 <br />
<br />
　　CounterBean.java&nbsp;<br />
</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">&nbsp;1</span><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">　　</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;javax.ejb.Stateful;&nbsp;<br />
</span><span style="color: #008080">&nbsp;2</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />　　&#8230;&#8230;&nbsp;<br />
</span><span style="color: #008080">&nbsp;3</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />　　@Stateful&nbsp;<br />
</span><span style="color: #008080">&nbsp;4</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
</span><span style="color: #008080">&nbsp;5</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />　　</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;CounterBean&nbsp;</span><span style="color: #0000ff">implements</span><span style="color: #000000">&nbsp;Counter&nbsp;<br />
</span><span style="color: #008080">&nbsp;6</span><span style="color: #000000"><img id="Codehighlighter1_99_277_Open_Image" onclick="this.style.display='none'; Codehighlighter1_99_277_Open_Text.style.display='none'; Codehighlighter1_99_277_Closed_Image.style.display='inline'; Codehighlighter1_99_277_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_99_277_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_99_277_Closed_Text.style.display='none'; Codehighlighter1_99_277_Open_Image.style.display='inline'; Codehighlighter1_99_277_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" />　　</span><span id="Codehighlighter1_99_277_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_99_277_Open_Text"><span style="color: #000000">{&nbsp;<br />
</span><span style="color: #008080">&nbsp;7</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　</span><span style="color: #008000">//</span><span style="color: #008000">增加事务支持&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #008080">&nbsp;8</span><span style="color: #008000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">　　@Tx(TxType.REQUIRESNEW)&nbsp;<br />
</span><span style="color: #008080">&nbsp;9</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;getNumber()&nbsp;<br />
</span><span style="color: #008080">10</span><span style="color: #000000"><img id="Codehighlighter1_169_192_Open_Image" onclick="this.style.display='none'; Codehighlighter1_169_192_Open_Text.style.display='none'; Codehighlighter1_169_192_Closed_Image.style.display='inline'; Codehighlighter1_169_192_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_169_192_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_169_192_Closed_Text.style.display='none'; Codehighlighter1_169_192_Open_Image.style.display='inline'; Codehighlighter1_169_192_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />　　</span><span id="Codehighlighter1_169_192_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_169_192_Open_Text"><span style="color: #000000">{&nbsp;<br />
</span><span style="color: #008080">11</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;number;&nbsp;<br />
</span><span style="color: #008080">12</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />　　}</span></span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">13</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
</span><span style="color: #008080">14</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　@Remove&nbsp;<br />
</span><span style="color: #008080">15</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
</span><span style="color: #008080">16</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;clean()&nbsp;<br />
</span><span style="color: #008080">17</span><span style="color: #000000"><img id="Codehighlighter1_233_272_Open_Image" onclick="this.style.display='none'; Codehighlighter1_233_272_Open_Text.style.display='none'; Codehighlighter1_233_272_Closed_Image.style.display='inline'; Codehighlighter1_233_272_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_233_272_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_233_272_Closed_Text.style.display='none'; Codehighlighter1_233_272_Open_Image.style.display='inline'; Codehighlighter1_233_272_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />　　</span><span id="Codehighlighter1_233_272_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_233_272_Open_Text"><span style="color: #000000">{&nbsp;<br />
</span><span style="color: #008080">18</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">我，被删除了!</span><span style="color: #000000">"</span><span style="color: #000000">);&nbsp;<br />
</span><span style="color: #008080">19</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />　　}</span></span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">20</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />　　}</span></span><span style="color: #000000">&nbsp;</span></div>
<p><br />
　　这个是计数器的实现类。注意这个类使用Stateful做了注释，这是必须的。同时，这个例子也演示了如何使用事务。事务的详细用法将在后面的章节中介绍。&nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Client.java</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">&nbsp;1</span><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">package</span><span style="color: #000000">&nbsp;com.kuaff.ejb3.stateful;&nbsp;<br />
</span><span style="color: #008080">&nbsp;2</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
</span><span style="color: #008080">&nbsp;3</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />　　</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;javax.ejb.EJBException;&nbsp;<br />
</span><span style="color: #008080">&nbsp;4</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />　　</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.rmi.NoSuchObjectException;&nbsp;<br />
</span><span style="color: #008080">&nbsp;5</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />　　</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;javax.naming.InitialContext;&nbsp;<br />
</span><span style="color: #008080">&nbsp;6</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />　　</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;javax.naming.NamingException;&nbsp;<br />
</span><span style="color: #008080">&nbsp;7</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
</span><span style="color: #008080">&nbsp;8</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />　　</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Client&nbsp;<br />
</span><span style="color: #008080">&nbsp;9</span><span style="color: #000000"><img id="Codehighlighter1_216_1132_Open_Image" onclick="this.style.display='none'; Codehighlighter1_216_1132_Open_Text.style.display='none'; Codehighlighter1_216_1132_Closed_Image.style.display='inline'; Codehighlighter1_216_1132_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_216_1132_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_216_1132_Closed_Text.style.display='none'; Codehighlighter1_216_1132_Open_Image.style.display='inline'; Codehighlighter1_216_1132_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" />　　</span><span id="Codehighlighter1_216_1132_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_216_1132_Open_Text"><span style="color: #000000">{&nbsp;<br />
</span><span style="color: #008080">10</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;<br />
</span><span style="color: #008080">11</span><span style="color: #000000"><img id="Codehighlighter1_263_1127_Open_Image" onclick="this.style.display='none'; Codehighlighter1_263_1127_Open_Text.style.display='none'; Codehighlighter1_263_1127_Closed_Image.style.display='inline'; Codehighlighter1_263_1127_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_263_1127_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_263_1127_Closed_Text.style.display='none'; Codehighlighter1_263_1127_Open_Image.style.display='inline'; Codehighlighter1_263_1127_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />　　</span><span id="Codehighlighter1_263_1127_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_263_1127_Open_Text"><span style="color: #000000">{&nbsp;<br />
</span><span style="color: #008080">12</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　InitialContext&nbsp;ctx;&nbsp;<br />
</span><span style="color: #008080">13</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　</span><span style="color: #0000ff">try</span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">14</span><span style="color: #000000"><img id="Codehighlighter1_298_1058_Open_Image" onclick="this.style.display='none'; Codehighlighter1_298_1058_Open_Text.style.display='none'; Codehighlighter1_298_1058_Closed_Image.style.display='inline'; Codehighlighter1_298_1058_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_298_1058_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_298_1058_Closed_Text.style.display='none'; Codehighlighter1_298_1058_Open_Image.style.display='inline'; Codehighlighter1_298_1058_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />　　</span><span id="Codehighlighter1_298_1058_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_298_1058_Open_Text"><span style="color: #000000">{&nbsp;<br />
</span><span style="color: #008080">15</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　　ctx&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;InitialContext();&nbsp;<br />
</span><span style="color: #008080">16</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　　Counter&nbsp;counter&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;(Counter)&nbsp;ctx.lookup(Counter.</span><span style="color: #0000ff">class</span><span style="color: #000000">.getName());&nbsp;<br />
</span><span style="color: #008080">17</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　　counter.add(</span><span style="color: #000000">10</span><span style="color: #000000">);&nbsp;<br />
</span><span style="color: #008080">18</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　　System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">当前的number:</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;counter.getNumber());&nbsp;<br />
</span><span style="color: #008080">19</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　　counter.add(</span><span style="color: #000000">10</span><span style="color: #000000">);&nbsp;<br />
</span><span style="color: #008080">20</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　　System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">当前的number:</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;counter.getNumber());&nbsp;<br />
</span><span style="color: #008080">21</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　　Counter&nbsp;counter2&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;(Counter)&nbsp;ctx.lookup(Counter.</span><span style="color: #0000ff">class</span><span style="color: #000000">.getName());&nbsp;<br />
</span><span style="color: #008080">22</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　　counter2.add(</span><span style="color: #000000">10</span><span style="color: #000000">);&nbsp;<br />
</span><span style="color: #008080">23</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　　System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">当前的number:</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;counter2.getNumber());&nbsp;<br />
</span><span style="color: #008080">24</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　　</span><span style="color: #008000">//</span><span style="color: #008000">删除&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #008080">25</span><span style="color: #008000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">　　　counter2.clean();&nbsp;<br />
</span><span style="color: #008080">26</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　　</span><span style="color: #008000">//</span><span style="color: #008000">下面如果再使用counter2,将出错&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #008080">27</span><span style="color: #008000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">try</span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">28</span><span style="color: #000000"><img id="Codehighlighter1_782_850_Open_Image" onclick="this.style.display='none'; Codehighlighter1_782_850_Open_Text.style.display='none'; Codehighlighter1_782_850_Closed_Image.style.display='inline'; Codehighlighter1_782_850_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_782_850_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_782_850_Closed_Text.style.display='none'; Codehighlighter1_782_850_Open_Image.style.display='inline'; Codehighlighter1_782_850_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />　　　</span><span id="Codehighlighter1_782_850_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_782_850_Open_Text"><span style="color: #000000">{&nbsp;<br />
</span><span style="color: #008080">29</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　　　System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">当前的number:</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;counter2.getNumber());&nbsp;<br />
</span><span style="color: #008080">30</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />　　　}</span></span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">31</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　　</span><span style="color: #0000ff">catch</span><span style="color: #000000">(EJBException&nbsp;ex)&nbsp;<br />
</span><span style="color: #008080">32</span><span style="color: #000000"><img id="Codehighlighter1_883_1053_Open_Image" onclick="this.style.display='none'; Codehighlighter1_883_1053_Open_Text.style.display='none'; Codehighlighter1_883_1053_Closed_Image.style.display='inline'; Codehighlighter1_883_1053_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_883_1053_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_883_1053_Closed_Text.style.display='none'; Codehighlighter1_883_1053_Open_Image.style.display='inline'; Codehighlighter1_883_1053_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />　　　</span><span id="Codehighlighter1_883_1053_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_883_1053_Open_Text"><span style="color: #000000">{&nbsp;<br />
</span><span style="color: #008080">33</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　　　</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(ex.getCausedByException()&nbsp;</span><span style="color: #0000ff">instanceof</span><span style="color: #000000">&nbsp;NoSuchObjectException)&nbsp;<br />
</span><span style="color: #008080">34</span><span style="color: #000000"><img id="Codehighlighter1_959_1007_Open_Image" onclick="this.style.display='none'; Codehighlighter1_959_1007_Open_Text.style.display='none'; Codehighlighter1_959_1007_Closed_Image.style.display='inline'; Codehighlighter1_959_1007_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_959_1007_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_959_1007_Closed_Text.style.display='none'; Codehighlighter1_959_1007_Open_Image.style.display='inline'; Codehighlighter1_959_1007_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />　　　　</span><span id="Codehighlighter1_959_1007_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_959_1007_Open_Text"><span style="color: #000000">{&nbsp;<br />
</span><span style="color: #008080">35</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　　　　System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">我都被删除啦，还找我！</span><span style="color: #000000">"</span><span style="color: #000000">);&nbsp;<br />
</span><span style="color: #008080">36</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />　　　　}</span></span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">37</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　　　</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">38</span><span style="color: #000000"><img id="Codehighlighter1_1024_1047_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1024_1047_Open_Text.style.display='none'; Codehighlighter1_1024_1047_Closed_Image.style.display='inline'; Codehighlighter1_1024_1047_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1024_1047_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1024_1047_Closed_Text.style.display='none'; Codehighlighter1_1024_1047_Open_Image.style.display='inline'; Codehighlighter1_1024_1047_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />　　　　</span><span id="Codehighlighter1_1024_1047_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1024_1047_Open_Text"><span style="color: #000000">{&nbsp;<br />
</span><span style="color: #008080">39</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　　　　</span><span style="color: #0000ff">throw</span><span style="color: #000000">&nbsp;ex;&nbsp;<br />
</span><span style="color: #008080">40</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />　　　　}</span></span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">41</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />　　　}</span></span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">42</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />　　}</span></span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">43</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　</span><span style="color: #0000ff">catch</span><span style="color: #000000">&nbsp;(NamingException&nbsp;e)&nbsp;<br />
</span><span style="color: #008080">44</span><span style="color: #000000"><img id="Codehighlighter1_1092_1122_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1092_1122_Open_Text.style.display='none'; Codehighlighter1_1092_1122_Closed_Image.style.display='inline'; Codehighlighter1_1092_1122_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1092_1122_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1092_1122_Closed_Text.style.display='none'; Codehighlighter1_1092_1122_Open_Image.style.display='inline'; Codehighlighter1_1092_1122_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />　　</span><span id="Codehighlighter1_1092_1122_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1092_1122_Open_Text"><span style="color: #000000">{&nbsp;<br />
</span><span style="color: #008080">45</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />　　　e.printStackTrace();&nbsp;<br />
</span><span style="color: #008080">46</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />　　}</span></span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">47</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />　　}</span></span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">48</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />　　}</span></span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #008080">49</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span></div>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这个类用来测试我们发布的计数器EJB。首先通过 <br />
<br />
　　ctx = new InitialContext();得到上下文，然后通过lookup查找计数器，然后给计数器加10，显示当前的计数器信息。最后调用Clean方法，一旦这个方法执行完毕，此EJB将从容器中删除，在使用这个EJB将会出现异常。 <br />
<br />
　　请运行{$JBOSS_HOME}/bin目录下的run.bat: run ?call,启动JBOSS。 <br />
<br />
　　在<a href="http://dev.rdxx.com/Java/JavaBase/Eclipse/" target="_blank">Eclipse</a>的Ant视图中执行ejbjar target。或者在命令行下，进入到此工程目录下，执行ant ejbjar,将编译打包发布此EJB。 <br />
<br />
　　在Eclipse的Ant视图中执行run target。或者在命令行下，进入到此工程目录下，执行ant run,测试这个EJB。</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/sailor/aggbug/214709.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sailor/" target="_blank">sailor</a> 2008-07-14 13:51 <a href="http://www.blogjava.net/sailor/articles/214709.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>2、EJB3.0开发指南之Session Bean(上)--------无状态会话Bean</title><link>http://www.blogjava.net/sailor/articles/214706.html</link><dc:creator>sailor</dc:creator><author>sailor</author><pubDate>Mon, 14 Jul 2008 05:36:00 GMT</pubDate><guid>http://www.blogjava.net/sailor/articles/214706.html</guid><wfw:comment>http://www.blogjava.net/sailor/comments/214706.html</wfw:comment><comments>http://www.blogjava.net/sailor/articles/214706.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sailor/comments/commentRss/214706.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sailor/services/trackbacks/214706.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在所有的EJB3.0规范中定义的EJB，都不必实现Home接口。 　　一个会话Bean必须有一个业务接口，这个接口由会话Bean来实现，或者也可以由会话Bean来产生。这样，你可以只写一个文件，就...&nbsp;&nbsp;<a href='http://www.blogjava.net/sailor/articles/214706.html'>阅读全文</a><img src ="http://www.blogjava.net/sailor/aggbug/214706.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sailor/" target="_blank">sailor</a> 2008-07-14 13:36 <a href="http://www.blogjava.net/sailor/articles/214706.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>1、JavaBean(EJB) 3.0 全新体验</title><link>http://www.blogjava.net/sailor/articles/214704.html</link><dc:creator>sailor</dc:creator><author>sailor</author><pubDate>Mon, 14 Jul 2008 05:24:00 GMT</pubDate><guid>http://www.blogjava.net/sailor/articles/214704.html</guid><wfw:comment>http://www.blogjava.net/sailor/comments/214704.html</wfw:comment><comments>http://www.blogjava.net/sailor/articles/214704.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sailor/comments/commentRss/214704.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sailor/services/trackbacks/214704.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;原文：<a href="http://dev.rdxx.com/Java/EJB/2007/12/2213122560946.shtml">http://dev.rdxx.com/Java/EJB/2007/12/2213122560946.shtml</a><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;引言 <br />
<br />
　　期待以久的EJB3.0规范在最近发布了它的初稿。在本文中将对新的规范进行一个概要性的介绍，包括新增的元数据支持，EJBQL的修改，实体Bean模型访问bean上下文的新方法和运行时环境等等。作者还讨论了EJB在未来要作出的调整以及EJB3.0与其他开发规范之间的关系。 <br />
<br />
　　<strong>开始 <br />
</strong><br />
　　无论如何由于EJB的复杂性使之在<a href="http://dev.rdxx.com/Java/J2EE/" target="_blank">J2EE</a>架构中的表现一直不是很好。EJB大概是J2EE架构中唯一一个没有兑现其能够简单开发并提高生产力的组建。EJB3.0规范正尝试在这方面作出努力以减轻其开发的复杂性。EJB3.0减轻了开发人员进行底层开发的工作量，它取消或最小化了很多（以前这些是必须实现）回调方法的实现，并且降低了实体Bean及O/R映射模型的复杂性。 <br />
<br />
　　在本文中，我首先会介绍EJB3.0中几个主要的改变。它对进一步深入了解EJB3.0是非常重要的。随后，我会从更高的层面来描述已经被提交到EJB3.0规范中的细节，并一个个的讲解新的规范中的改变：实体Bean,O/R映射模型，实体关系模型和EJB QL(EJB查询语言)等等。 <br />
<br />
<strong>　　背景</strong> <br />
<br />
　　EJB3.0中两个重要的变更分别是：使用了Java5中的程序注释工具和基于<a href="http://dev.rdxx.com/Java/Struts/" target="_blank">Hibernate</a>的O/R映射模型。 <br />
<br />
　<strong>　Java5中的元数据工具</strong> <br />
<br />
　　Java5（以前叫<a href="http://dev.rdxx.com/Java/J2SE/" target="_blank">J2SE</a>1.5或Tiger）中加入了一种新的程序注释工具。通过这个工具你可以自定义注释标记，通过这些自定义标记来注释字段、方法、类等等。这些注释并不会影响程序的语义，但是可以通过工具（编译时或运行时）来解释这些标记并产生附加的内容（比如部署描述文件），或者强制某些必须的运行时行为（比如EJB组件的状态特性）。注释的解析可以通过源文件的解析（比如编译器或这IDE工具）或者使用Java5中的APIs反射机制。注释只能被定义在源代码层。由于所有被提交到EJB3.0草案中的注释标记都有一个运行时的RetentionPolicy，因此会增加类文件占用的存储空间，但这却给容器制造商和工具制造商带来了方便。 <br />
<br />
　<strong>　Hibernate</strong> <br />
<br />
　　目前Hibernate非常受欢迎，它是开发源代码的Java O/R映射框架，目的是把开发人员从繁琐的数据持久化<a href="http://dev.rdxx.com/" target="_blank">编程</a>中解脱出来。它也有一个标准的HQL（Hibernate 查询语言）语言，你可以在新的EJB QL中看到它的影子。Hibernate在处理如数据查询、更新、连接池、事务处理、实体关系处理等方面非常简单。 <br />
<br />
　<strong>　概览</strong> <br />
　　 <br />
　　在已经提交的EJB3.0规范中主要涉及两个方面的改变： <br />
<br />
　　1. 一套以注释为基础的EJB编程模型，再加上EJB2.1中定义的通过部署描述符和几个接口定义的应用程序行为。 <br />
<br />
　　2. 新的实体Bean持久化模型，EJBQL也有许多重要的改变。 <br />
<br />
　　还有一些有关上述的提议，比如：一个新的客户端编程模型，业务接口的使用以及实体Bean的生命周期。请注意EJB2.1编程模型（包括部署描述符和home/remote接口）仍然是有效的。新的简化模型并没有完全取代EJB2.1模型。 <br />
<br />
　　<strong>EJB注释</strong> <br />
<br />
　　EJB规范组织一个重要的目标是减轻原始代码的数量，并且他们为此给出了一个完美而简介的办法。在EJB3.0的里，任何类型的企业级Bean只是一个加了适当注释的简单Java对象(POJO)。注释可以用于定义bean的业务接口、O/R映射信息、资源引用信息，效果与在EJB2.1中定义部署描述符和接口是一样的。在EJB3.0中部署描述符不再是必须的了；home接口也没有了，你也不必实现业务接口（容器可以为你完成这些事情）。 <br />
<br />
　　比如，你可以使用@Stateless注释标记类把Java类声明为一个无状态回话bean。对于有状态回话bean来说，@Remove注释可以用来标记一个特定的方法，通过这个注释来说明在调用这个方法之后bean的实例将被清除掉。 <br />
<br />
　　为了减少描述组件的说明信息，规范组织还采纳了由异常进行配置（configuration-by-exception）的手段，意思是你可以为所有的注释提供一个明确的缺省值，这样多数常规信息就可以据此推断得出。 <br />
<br />
<strong>　　新的持久化模型</strong> <br />
<br />
　　新的实体bean也是一个加了注释的简单Java对象(POJO)。一旦它被EntityManager访问它就成为了一个持久化对象，并且成为了持久化上下文（context）的一部分。一个持久化上下文与一个事务上下文是松耦合的；严格的讲，它隐含的与一个事务会话共存。 <br />
<br />
　　实体关系也是通过注释来定义的，O/R映射也是，并提供几种不同的<a href="http://db.rdxx.com/" target="_blank">数据库</a>规范操作，在EJB2.1中这些要通过开发人员自己的<a href="http://soft.rdxx.com/Design/" target="_blank">设计</a>模式或者其它技术来完成的（比如，自增长主键策略）。 <br />
<br />
　<strong>　深入研究</strong> <br />
<br />
　　现在是时候详细了解EJB3.0草案了。让我们开始探讨所有EJB中四种企业级bean，并看看他们在新的规范中是什么样子。 <br />
<br />
<strong>　　无状态回话bean </strong><br />
<br />
　　在EJB3.0规范中，写一个无状态回话bean(SLSB)只需要一个简单的Java文件并在类层加上@Stateless注释就可以了。这个bean可以扩展javax.ejb.SessionBean接口，但这些不是必须的。 <br />
<br />
　　一个SLSB不再需要home接口，没有哪类EJB再需要它了。Bean类可以实现业务接口也可以不实现它。如果没有实现任何业务接口，业务接口会由任意public的方法产生。如果只有几个业务方法会被暴露在业务接口中，这些方法可以使用@BusinessMethod注释。缺省情况下所有产生的接口都是local（本地）接口，你也可以使用@Remote注释来声明这个接口为remote（远程）接口。 <br />
<br />
　　下面的几行代码就可以定义一个HelloWorldbean了。而在EJB2.1中同样的bean至少需要两个接口，一个实现类和几个空的实现方法，再加上部署描述符。 <br />
<br />
　　import javax.ejb.*; <br />
<br />
　　/** <br />
　　* A stateless session bean requesting that a remote business <br />
　　* interface be generated for it. <br />
　　*/ <br />
　　@Stateless <br />
　　@Remote <br />
　　public class HelloWorldBean { <br />
　　public String sayHello() { <br />
　　return "Hello World!!!"; <br />
　　} <br />
　　} <br />
<br />
　　 <strong>有状态回话bean</strong> <br />
<br />
　　除了几个SFSB的特别说明之外，有状态回话bean(SFSB)和SLSB一样精简： <br />
<br />
　　 一个SFSB应该有一个方法来初始化自己（在EJB2.1中是通过ejbCreate()来实现的）。在EJB3.0的规范中建议这些初始化操作可以通过自定义方法完成，并把他们暴露在业务接口中。在使用这个bean之前由客户端来调用相应的初始化方法。目前规范组织就是否提供一个注释来标记某个方法用于初始化还存在争议。 <br />
<br />
　　 Bean的提供者可以用@Remove注释来标记任何SFSB的方法，以说明这个方法被调用之后bean的实例将被移除。同样，规范组织仍然在讨论是否要有一种机制来处理这种特殊的情况，即当这个方法出现异常的情况下bean的实例是否被移除。 <br />
<br />
　　下面是对以上问题我个人的观点： <br />
<br />
　　1) 是否应该有一个注释来标明一个方法进行初始化呢？我的观点是――应该有，这样容器就可以在调用其他方法之前至少调用一个方法来进行初始化。这不仅可以避免不必要的错误(由于没有调用初始化方法)而且可以使容器更明确的判断是否可以重用SFSB实例。我暂且把这个问题放一放，规范组织只考虑为一个方法提供一个注释来声明它是一个初始化方法。 <br />
<br />
　　2) 对于第二个问题我的观点也是肯定的。这有利于Bean的提供者合客户端程序对其进行控制。只有一个遗留的问题：那就是一旦调用这个方法失败，是否能移除这个bean 的实例？答案是不能，但是它将会在回话结束的时候被移除。 <br />
<br />
<strong>　　消息驱动Bean</strong> <br />
<br />
　　消息驱动Bean是唯一一种必须实现一个业务接口的Bean。这个接口指出bean支持的是哪一种消息系统。对于以JMS为基础的MDB来说，这个接口是javax.jms.MessageListener。注意MDB业务接口不是一个真正意义上的业务接口，它只是一个消息接口。 <br />
<br />
　<strong>　实体Bean</strong> <br />
<br />
　　 实体Bean使用@Entity注释来标记，所有实体bean中的属性/字段不必使用@Transient注释来标记。实体bean的持久化字段可以通过JavaBean-style机制或者声明为public/protected字段来实现。 <br />
<br />
　　 实体bean可以使用助手类来描述其状态，但是这些类的实例并没有持久化唯一性（persistent identity）的特性(即，唯一标识这个bean的字段等)，实际上这些助手类与他们的实体bean实例是紧密结合的；并且这些对象还是以非共享方式来访问实体对象的。 <br />
<br />
<strong>　　实体关联</strong> <br />
<br />
　　EJB3.0同时支持Bean之间双向的合单向的关联，它们可以是一对一、一对多、多对一或者是多对多的关联。然而双向关联的两端还要分为自身端（owning side）和对方端（inverse side）不同的端。自身端负责向数据库通告关联的变更。对于多对多的关联自身端必须明确的声明。实际上对方端通过isInverse=true进行注释（由此自身端就不必说明了而是由另一段推断出）。看来上面的描述，规范组织还能说让EJB变的简单了吗？ <br />
<br />
<strong>　　O/R映射</strong> <br />
<br />
　　EJB3.0中的O/R映射模型也有了重要的改变，它从原来的abstract-persistence-schema-based变成了现在的Hibernate-inspired模式。尽管目前规范组织还在就此进行讨论但是一个明确的模型将会出现在下一个版本的草案中。 <br />
<br />
　　举例来说，O/R映射模型将通过bean类中的注释来声明。而且此方法还会指出对应的具体表和字段。O/R映射模型提供了一套自有的SQL；而且除了提供一些基本的SQL外还支持某些高层开发的功能。比如，有一个通过@Column注释声明的字段columnDefinition，那么可以写这样的SQL：columnDefinition="BLOB NOT NULL" <br />
<br />
　<strong>　客户端程序模型 <br />
</strong><br />
　　一个EJB客户端可以通过@Inject注释以一种&#8220;注入&#8221;的方式获得一个bean的业务接口引用。你也可以使用另一个注释@javax.ejb.EJBContext.lookup()来完成上面的操作，但是规范中没有告诉我们一个普通的Java客户端怎样获得一个Bean的实例，因为这个普通的Java客户端是运行在一个客户端容器中，它无法访问@javax.ejb.EJBContex对象。现在还有另外一种机制来完成上面的工作那就是使用一个超级上下文环境对象：@javax.ejb.Context()。但是规范中没有指出该如何在客户端中使用这个对象。 <br />
<br />
　　<strong>EJB QL <br />
</strong><br />
　　EJB QL可以通过@NamedQuery来注释。这个注释有两个成员属性分别是name和queryString.一旦定义了这些属性，就可以通过EntityManager.createNamedQuery(name)来指向这个查询。你也可以创建一个标准的JDBC风格的查询并使用EntityManager.createQuery(ejbqlString)或EntityManager.createNativeQuery(nativeSqlString)(这个方法用于执行一个本地查询)来执行查询。 <br />
<br />
　　EJB QL有两个地方可以定义其参数。javax.ejb.Query接口提供了定义参数、指向查询、更新数据等等方法。下面是一个EJBQL指向查询的例子： <br />
<br />
<br />
　　.. .. <br />
　　@NamedQuery( <br />
　　name="findAllCustomersWithName", <br />
　　queryString="SELECT c FROM Customer c WHERE c.name LIKE :custName" <br />
　　) <br />
　　.. .. <br />
　　@Inject public EntityManager em; <br />
　　customers = em.createNamedQuery("findAllCustomersWithName") <br />
　　.setParameter("custName", "Smith") <br />
　　.listResults(); <br />
<br />
<br />
　　下面列出了一些EJB QL的增强特性： <br />
<br />
　　1) 支持批量更新和删除。 <br />
<br />
　　2) 直接支持内连接和外连接。FETCH JOIN运行你指出关联的实体，Order可以指定只查询某个字段。 <br />
<br />
　　3) 查询语句可以返回一个以上的结果值。实际上，你可以返回一个依赖的类比如下面这样： <br />
<br />
　　SELECT new CustomerDetails(c.id, c.status, o.count) <br />
　　FROM Customer c JOIN c.orders o <br />
　　WHERE o.count &gt; 100 <br />
<br />
　　4) 支持group by 和having。 <br />
<br />
　　5) 支持where子句的嵌套子查询。 <br />
<br />
　　在提交的EJB3.0草案中，EJB QL与标准SQL非常的接近。实际上规范中甚至直接支持本地的SQL(就像我们上面提到的那样)。这一点对某些程序员来说也许有些不是很清楚，我们将在下面进行更详细的讲解。&nbsp;<br />
<strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;多样性 <br />
</strong><br />
　　方法许可(Method permissions)可以通过@MethodPermissions或@Unchecked注释来声明；同样的，事务属性也可以通过@TransactionAttribute注释来声明。规范中仍然保留资源引用和资源环境引用。这些一样可以通过注释来声明，但是有一些细微的差别。比如，上下文(context)环境要通过注入工具控制。容器根据bean对外部环境引用自动初始化一个适当的已经声明的实例变量。比如，你可以象下面这样获得一个数据源（DataSource）： <br />
<br />
　　@Resource(name="myDataSource") //Type is inferred from variable <br />
　　public DataSource customerDB; <br />
<br />
　　在上面的例子中如果你不指定引用资源的名称(name)那么其中的customerDB会被认为是默认值。当所有的引用属性都可得到时，@Injec注释就可以这样写： <br />
<br />
　　@Inject public DataSource customerDB; <br />
<br />
　　容器负责在运行时初始化customerDB数据源实例。部署人员必须在此之前在容器中定义好这些资源属性。 <br />
<br />
　　更好的消息是：那些以前必须检测的异常将一去不复返。你可以声明任意的应用程序异常，而不必在再抛出或捕获其他类似CreateException和FinderException这样的异常。容器会抛出封装在javax.ejb.<a href="http://dev.rdxx.com/Java/EJB/" target="_blank">EJB</a>Exception中的系统级异常或者只在必要时候抛出IllegalArgumentException或IllegalStateException异常。 <br />
<br />
　　<strong>EJB文件处理模式 <br />
</strong><br />
　　在我们结束本节之前，让我的快速的浏览一下容器提供商在EJB处理模式方面可能的变更。规范中对此并没有明确的表态，但我可以想到至少两种模式。 <br />
<br />
　　 一种办法是首先利用EJB文件生成类似于EJB2.1部署模式的文件（包括必要的接口和部署描述符）然后再用类似于EJB2.1的方式来部署这个EJB组件。当然，这样产生的部署描述符可能并不标准但是它可以解决同一个容器对EJB2.1和EJB3.0兼容的问题。下面这幅图描述了这一过程。 <br />
<br />
　　 另一种方法是一种类似于<a href="http://web.rdxx.com/JSP/" target="_blank">JSP</a>托放的部署模式。你可以把一个EJB文件放到一个预先定义的目录下，然后容器会识别这个EJB并处理它，然后部署并使之可以使用。这种方法可以建立于上面那种方法之上，在支持反复部署时有很大的帮助。考虑到部署的简单性也是EJB3.0规范的目的之一，我真诚的希望在下一个草案出来时能够确定一个模式(至少能有一个非正式的)。 <br />
<br />
　　你有什么想法？ <br />
<br />
　　EJB3.0规范的制定正在有序的进行，为了使EJB的开发变得更加容易，EJB规范组织作出的努力是有目共睹的。就像他们说的那样，一切对会变得简单，但做到这一点并不容易。目前已经定义了50个注释标记(还有几个将在下一个草案中发布)，每一个都有自己的缺省规则和其他的操作。当然，我真的不希望EJB3.0变成EJB2.1的一个翻版"EJB 3.0 = EJB 2.1 for dummies"（希望这个等式不要成立）。最后，我还是忍不住要提一些我自己的观点： <br />
<br />
　　1) 首先，规范确实使反复部署变得容易了，并且有一个简单的模式来访问运行时环境。我还是觉得home接口应该放弃。 <br />
<br />
　　2) 在早期的EJB规范中，实体bean用于映射一个持久化存储。理论上(也许只是理论上)可能需要把实体bean映射到一个遗留的EIS(enterprise information system)系统中。出于将来扩展的考虑这样作是有好处的，并且可以使更多的业务数据模型采用实体bean。也因此其伴随的复杂性使得实体bean不被看好。在本次提交的草案中，一个实体bean只是一个<a href="http://db.rdxx.com/" target="_blank">数据库</a>的映射。并且是基于非抽象持久化模式和简单的数据访问模式的更加简单开发。 <br />
<br />
　　3) 我对模型变更持保留态度，我认为在EJB中包含SQL脚本片断并不是个好注意。一些开发人员完全反对包含某些&#8220;SQL片段（SQLness）&#8221;（比如@Table 和 @Column注释）。我的观点是这些SQLness是好的，据此我们可以清楚的知道我们到底要数据库作些什么。但是某些SQL段我看来并不是很好，比如columnDefinition="BLOB NOT NULL"，这使得EJB代码和SQL之间的耦合太过紧密了。 <br />
<br />
　　4) 尽管对于本地SQL的支持看似很诱人，其实在EJB代码中嵌入SQL是一个非常糟糕的主意。当然，有些办法可以避免在EJB中硬编码SQL，但是这应该在规范中说明，而不能是某些开发人员自己定义的模式。 <br />
<br />
　　5) 假设@Table注释只用于类。在运行时通过@Table注释的name属性定义的表名称将必须对应一个实际的数据库表。规范对此应该给予清楚的说明和一致的模式。 <br />
<br />
　　6) 规范还需要更清楚的说明客户端<a href="http://dev.rdxx.com/" target="_blank">编程</a>模型，尤其是普通java客户端。规范中所有的参考都假设或者隐含的使用EJB客户端。而且规范中对客户端的向后兼容方面也没有给出明确的说法。 <br />
<br />
　　7) Transient注释应该重新命名以避免和已有的transient关键字发生冲突。事实上，在这一点上我们更乐于稍微的背离一下configuration-by-exception原则并且定义一个@Persistent注释来明确的定义持久化字段。@Persistent注释可以仅仅是一个标记注释或者它可以有几个属性来关联O/R映射注释。 <br />
<br />
<strong>　　与其他规范的关联</strong> <br />
<br />
　　目前可能影响到EJB3.0的JSR有JSR175（java语言元数据工具）和JSR181（<a href="http://dev.rdxx.com/Java/" target="_blank">Java</a> Web服务元数据） <br />
<br />
　　JSR175已经初步完成并且不会和EJB3.0有太大的冲突；但是JSR181与EJB3.0有两个关联的地方： <br />
<br />
　　1) Web service接口：EJB规范将采用一种机制适应JSR181以便可以把一个bean实现为一个Web service并告诉Web service如何被客户端调用。 <br />
<br />
　　2) JSR 181计划采用不同的机制来处理<a href="http://net.rdxx.com/Safe/SafeTech/" target="_blank">安全</a>问题。在早期的规范中EJB建议使用一个一致的机制（MethodPermissions），但是JSR 181计划使用一个稍微不同的方式（SecurityRoles和SecurityIdentity注释）。同样的RunAs注释的定义也存在这些许差别。这一问题还在解决中最终会在<a href="http://dev.rdxx.com/Java/J2EE/" target="_blank">J2EE</a>层的规范中维持其一致性。 <br />
<br />
　　在J2EE 1.5中的一些开发规范可能与EJB3.0有关联。除了上面说到的几个关联之外现在没有其他的开发规范与EJB3.0有冲突。 <br />
<br />
<strong>　　结束语</strong> <br />
<br />
　　在使EJB的开发变得简单高效之前，我们还有很长一段路要走。规范组织在降低EJB的开发难度方面起了个好头。O/R映射模型的提议还处在早期阶段，规范组织正在完善它。我希望它不要太复杂也不要与SQL过分的耦合。让我们不要只是停留在期望、希望、思考和请求中：提出你的想法并把你的建议发送给规范组织ejb3-feedback@sun.com。JCP并不是很民主的组织，但是你的建议一定是有价值的。 <br />
<br />
　　本文的观点是作者的个人主张与作者所在的公司没有任何关系。作者非常感谢Hemant Khandelwal对发表此文的帮助。 <br />
<br />
　　提供下载的代码是EJB3.0草案的示例代码。由于没有工具和环境的支持这个例子是没有经过验证的。这些代码只是示例了未来的EJB3.0大概的样子。 <br />
<br />
　　Anil Sharma是BEA System公司开发Weblogic Integration产品的资深程序员。在加入BEA之前曾就职于<a href="http://db.rdxx.com/Oracle/" target="_blank">Oracle</a> 和 Pramati，并一直致力于研究J2EE技术。在业余时间它喜欢听音乐看电影；他还参加一些开源项目的开发工作。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<img src ="http://www.blogjava.net/sailor/aggbug/214704.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sailor/" target="_blank">sailor</a> 2008-07-14 13:24 <a href="http://www.blogjava.net/sailor/articles/214704.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3.0的各应用服务器提供的JNDI接口（转）</title><link>http://www.blogjava.net/sailor/articles/214358.html</link><dc:creator>sailor</dc:creator><author>sailor</author><pubDate>Fri, 11 Jul 2008 15:27:00 GMT</pubDate><guid>http://www.blogjava.net/sailor/articles/214358.html</guid><wfw:comment>http://www.blogjava.net/sailor/comments/214358.html</wfw:comment><comments>http://www.blogjava.net/sailor/articles/214358.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sailor/comments/commentRss/214358.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sailor/services/trackbacks/214358.html</trackback:ping><description><![CDATA[<a href="http://blog.163.com/e_adon/blog/static/338840452007721831904/"><font color="#000000">来源：</font>http://blog.163.com/e_adon/blog/static/338840452007721831904/</a><br />
<br />
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在分布式开发中，JAVA客户端程序是通过JNDI去查询EJB的，而JNDI的全名是：The Java Naming and Directory Interface。因为JNDI 是一组接口，所以我们只需根据接口规范编程就可以。要通过JNDI 进行资源访问，我们必须设置初始化上下文的参数，主要是设置JNDI 驱动的类名(java.naming.factory.initial)和提供命名服务的URL<br />
(java.naming.provider.url)。因为Jndi 的实现产品有很多。所以java.naming.factory.initial 的值因提供JNDI 服务器<br />
的不同而不同，java.naming.provider.url 的值包括提供命名服务的主机地址和端口号。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;大家在编程时，最令人气愤的就是EJB程序写好了，而客户端却不知道如何去调用它，一般书上只是介绍一种应用服务器的访问代码其它的不会提到，找这方面资料又比较麻烦，当误大家许多时间和精力，因此我就把已经找到的代码贴出来，方便大家查找。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;暂且提供以下三种服务器的代码，今后再慢慢补充吧。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下面是访问Jboss 服务器的<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;例子代码：<br />
</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">1</span><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">Properties&nbsp;props&nbsp;</span><span style="color: #808080">=</span><span style="color: #000000">&nbsp;new&nbsp;Properties();<br />
</span><span style="color: #008080">2</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />props.setProperty("java.naming.factory.initial",&nbsp;"org.jnp.interfaces.NamingContextFactory");<br />
</span><span style="color: #008080">3</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />props.setProperty("java.naming.provider.url",&nbsp;"localhost:</span><span style="font-weight: bold; color: #800000">1099</span><span style="color: #000000">");<br />
</span><span style="color: #008080">4</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />InitialContext&nbsp;</span><span style="color: #808080">=</span><span style="color: #000000">&nbsp;new&nbsp;InitialContext(props);<br />
</span><span style="color: #008080">5</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />HelloWorld&nbsp;helloworld&nbsp;</span><span style="color: #808080">=</span><span style="color: #000000">&nbsp;(HelloWorld)&nbsp;ctx.lookup("HelloWorldBean</span><span style="color: #808080">/</span><span style="color: #000000">remote");<br />
</span><span style="color: #008080">6</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下面是访问Sun ApplicationServer 及glassfish&nbsp;应用服务器的例子代码：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">1</span><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">Properties&nbsp;props&nbsp;</span><span style="color: #808080">=</span><span style="color: #000000">&nbsp;new&nbsp;Properties();<br />
</span><span style="color: #008080">2</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />props.setProperty("java.naming.factory.initial",<br />
</span><span style="color: #008080">3</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />"com.sun.enterprise.naming.SerialInitContextFactory");<br />
</span><span style="color: #008080">4</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />props.setProperty("java.naming.provider.url",&nbsp;"localhost:</span><span style="font-weight: bold; color: #800000">3700</span><span style="color: #000000">");<br />
</span><span style="color: #008080">5</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />InitialContext&nbsp;</span><span style="color: #808080">=</span><span style="color: #000000">&nbsp;new&nbsp;InitialContext(props);<br />
</span><span style="color: #008080">6</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />HelloWorld&nbsp;helloworld&nbsp;</span><span style="color: #808080">=</span><span style="color: #000000">&nbsp;(HelloWorld)&nbsp;ctx.lookup("com.0735jb.ejb3.HelloWorld");</span></div>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下面是访问Weblogic10 应用服务器的例子代码：<br />
</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">1</span><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">Properties&nbsp;props&nbsp;</span><span style="color: #808080">=</span><span style="color: #000000">&nbsp;new&nbsp;Properties();<br />
</span><span style="color: #008080">2</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />props.setProperty("java.naming.factory.initial",&nbsp;"weblogic.jndi.WLInitialContextFactory");<br />
</span><span style="color: #008080">3</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />props.setProperty("java.naming.provider.url",&nbsp;"t3:</span><span style="color: #808080">//</span><span style="color: #000000">localhost:</span><span style="font-weight: bold; color: #800000">7001</span><span style="color: #000000">");<br />
</span><span style="color: #008080">4</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />InitialContext&nbsp;</span><span style="color: #808080">=</span><span style="color: #000000">&nbsp;new&nbsp;InitialContext(props);<br />
</span><span style="color: #008080">5</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />HelloWorld&nbsp;helloworld&nbsp;</span><span style="color: #808080">=</span><span style="color: #000000">&nbsp;(HelloWorld)&nbsp;ctx.lookup("HelloWorldBean<br />
</span><span style="color: #008080">6</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />#com.0735jb.ejb3.HelloWorld");</span></div>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;上面是服务器默认的JNDI命名规则,那么如何修改它呢.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在Jboss 中要自定义JNDI 名称，可以使<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用@LocalBinding 和@RemoteBinding 注释，@LocalBinding 注释指定Session Bean 的Local 接口的JNDI 名称，<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@RemoteBinding 注释指定Session Bean 的Remote 接口的JNDI 名称，下面的代码展示了如何自定义JNDI 名：</p>
<p>&nbsp;</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">1</span><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #008000">@Stateless</span><span style="color: #000000"><br />
</span><span style="color: #008080">2</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #008000">@Remote</span><span style="color: #000000">&nbsp;({Operation.class})<br />
</span><span style="color: #008080">3</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #008000">@RemoteBinding</span><span style="color: #000000">&nbsp;(jndiBinding</span><span style="color: #808080">=</span><span style="color: #000000">"0735jb</span><span style="color: #808080">/</span><span style="color: #000000">RemoteOperation")<br />
</span><span style="color: #008080">4</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #008000">@Local</span><span style="color: #000000">&nbsp;({LocalOperation.class})<br />
</span><span style="color: #008080">5</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #008000">@LocalBinding</span><span style="color: #000000">&nbsp;(jndiBinding</span><span style="color: #808080">=</span><span style="color: #000000">"0735jb</span><span style="color: #808080">/</span><span style="color: #000000">LocalOperation")</span></div>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在JSP 客户端调用上面EJB 的代码片断如下：<br />
</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">1</span><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">InitialContext&nbsp;ctx&nbsp;</span><span style="color: #808080">=</span><span style="color: #000000">&nbsp;new&nbsp;InitialContext(props);<br />
</span><span style="color: #008080">2</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />Operation&nbsp;operation&nbsp;</span><span style="color: #808080">=</span><span style="color: #000000">&nbsp;(Operation)&nbsp;ctx.lookup("0735jb</span><span style="color: #808080">/</span><span style="color: #000000">RemoteOperation");<br />
</span><span style="color: #008080">3</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />在weblogic10&nbsp;中，你可以通过</span><span style="color: #008000">@Stateless</span><span style="color: #000000">.mappedName()设置全局JNDI&nbsp;名称，如：<br />
</span><span style="color: #008080">4</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #008000">@Stateless</span><span style="color: #000000">(mappedName</span><span style="color: #808080">=</span><span style="color: #000000">"OperationBeanRemote")<br />
</span><span style="color: #008080">5</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;class&nbsp;OperationBean&nbsp;implements&nbsp;Operation,&nbsp;LocalOperation&nbsp;{<br />
</span><span style="color: #008080">6</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span></div>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;客户端调用EJB 的代码片断如下：<br />
</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">1</span><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">InitialContext&nbsp;ctx&nbsp;</span><span style="color: #808080">=</span><span style="color: #000000">&nbsp;new&nbsp;InitialContext(props);<br />
</span><span style="color: #008080">2</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />Operation&nbsp;operation&nbsp;</span><span style="color: #808080">=</span><span style="color: #000000">&nbsp;(Operation)&nbsp;ctx.lookup("OperationBeanRemote#com.0735jb.ejb3.Operation");</span></div>
 <img src ="http://www.blogjava.net/sailor/aggbug/214358.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sailor/" target="_blank">sailor</a> 2008-07-11 23:27 <a href="http://www.blogjava.net/sailor/articles/214358.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3 Persistence API标准化持久性(转)</title><link>http://www.blogjava.net/sailor/articles/214187.html</link><dc:creator>sailor</dc:creator><author>sailor</author><pubDate>Fri, 11 Jul 2008 02:26:00 GMT</pubDate><guid>http://www.blogjava.net/sailor/articles/214187.html</guid><wfw:comment>http://www.blogjava.net/sailor/comments/214187.html</wfw:comment><comments>http://www.blogjava.net/sailor/articles/214187.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sailor/comments/commentRss/214187.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sailor/services/trackbacks/214187.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;持久性对于大多数企业应用程序都非常关键，因为它们需要访问关系数据库（例如Oracle Database 10g）。如果您正在使用Java开发应用程序，您可能需要完成一些常规任务（例如数据库更新和检索），这是通过编写JDBC和SQL来完成的。最近几年，几种对象关系(O-R)映射框架（例如Oracle TopLink、JBoss Hibernate和BEA Kodo）开始流行，因为它们简化了持久性问题，将Java开发人员从编写JDBC代码的工作中解放出来，从而使他们能够将精力集中于业务逻辑。一些Java标准（例如EJB 2.x容器管理持久性(CMP)实体bean）也试图解决持久性挑战，但是不那么成功。 <br />
<br />
　　虽然存在多种构建应用程序持久层的选择，但是还没有一种面向Java平台的、在Java EE和Java SE环境下均可使用的持久性标准。好消息是EJB3 Java Persistence API (JPA)（它是EJB 3.0规范JSR-220的一部分）的出现，它标准化了面向Java平台的持久性API。JSR-220为O-R映射供应商（例如TopLink、Hibernate和Kodo）以及其他领先的应用服务器供应商和JDO供应商所广泛接受。EJB3规范提供了一种极有吸引力的选择，用于构建企业Java应用程序的持久层。<br />
<br />
　　在本文中，我将介绍EJB3 Java Persistence API，我将使用一个简单的域对象模型作为示例。 <br />
<br />
　　<strong>域模型</strong><br />
<br />
　　在构建企业应用程序时，我们首先会设计希望将其保存在数据库中的域对象模型；然后，与数据库设计人员合作，确定数据库模式。域模型表示了持久性对象或实体。实体可以是人、地方或事物，您存储关于它们的数据。它包含数据和行为。富域模型具有所有面向对象的行为特征，例如继承性和多态性。<br />
<br />
　　我们的简单域模型（图1）具有Department与Employee实体之间的双向一对多关系。FullTime和Contractor实体继承自Employee实体。<br />
<br />
<table width="90%" align="center">
    <tbody>
        <tr>
            <td>
            <div align="center"><img height="153" alt="图1.示例域对象模型 " src="http://dev.yesky.com/imagelist/06/29/3fru003n4u9i.gif" width="348" border="0" /><br />
            图1.示例域对象模型 </div>
            </td>
        </tr>
    </tbody>
</table>
<br />
　　<strong>O-R框架和EJB3 JPA基础知识</strong><br />
<br />
　　如果使用过O-R映射框架（例如Oracle TopLink）构建应用程序持久层，您就会注意到，每种框架都提供三种工具： <br />
<br />
　　一种声明式地执行O-R映射的方式。这种方法（称为O-R映射元数据）允许将对象映射到一个或多个数据库表。通常，大多数O-R框架使用XML存储O-R映射元数据。 <br />
<br />
　　一个用于操作实体（例如，执行CRUD操作）的API。此API允许持久化、检索、更新或移除对象。基于API和O-R映射元数据的使用，O-R框架代表开发人员执行数据库操作。此API将开发人员从编写JDBC或SQL代码以持久化域对象的工作中解放出来。 <br />
<br />
　　一种用于检索对象的查询语言。这是持久性最重要的方面，因为非法的SQL语句可能会降低数据库的速度。此方法也对应用程序屏蔽了混乱地遍布应用程序的的专有SQL。查询语言允许检索实体或对象，并将开发人员从编写SQL SELECT语句的工作中解放出来。 <br />
<br />
　　EJB3 Java Persistence API (JPA)提供一种标准O-R映射机制、一个执行CRUD操作的EntityManager API以及一种扩展EJB-QL以检索实体的方式，从而标准化了面向Java平台的持久性的使用。我将在后面讨论这三个方面。 <br />
<br />
　　<strong>启用元数据注释</strong><br />
<br />
　　Java SE 5.0引入了元数据注释。Java EE的所有组件（包括EJB3 JPA）大量使用元数据注释以简化企业Java开发。要了解关于元数据注释的更多信息，请参阅Kyle Downey所著的Bridging the Gap: J2SE 5.0 Annotations。在EJB3 JPA中，注释可以用于定义对象、关系、O-R映射和持久性上下文的注入。JPA还提供使用XML描述符来代替的选择。我将主要介绍元数据注释的使用，因为它们大大简化了开发。不过，您可能更倾向于在生产部署环境中使用XML<br />
<strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;标准化JPA中的O-R映射</strong><br />
<br />
　　定义持久对象：实体<br />
<br />
　　实体是轻量级的域对象——您希望将其保存在关系数据库中的Plain Old Java Object (POJO)。像任何POJO一样，实体可以是抽象或具体类，它能够扩展另一个POJO。可以使用javax.persistence.Entity注释将POJO标记为实体。<br />
<br />
　　以下代码将使域模型中的Department对象成为实体： <br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e1e1e1" border="1">
    <tbody>
        <tr>
            <td>package onjava;<br />
            import java.io.Serializable;<br />
            import java.util.Collection;<br />
            import javax.persistence.*;<br />
            @Entity<br />
            @NamedQuery(name="findAllDepartment", query="select o from Department o")<br />
            @Table(name="DEPT")<br />
            public class Department implements Serializable {<br />
            @Id<br />
            @Column(nullable=false)<br />
            protected Long deptNo;<br />
            @Column(name="DNAME")<br />
            protected String name;<br />
            @Column(name="LOC")<br />
            protected String location;<br />
            @OneToMany(mappedBy="department")<br />
            protected Collection employees;<br />
            public Department() {<br />
            }<br />
            ...<br />
            public Collection getEmployees() {<br />
            return employees;<br />
            }<br />
            public void setEmployees(Collection employees) {<br />
            this.employees = employees;<br />
            }<br />
            public Employee addEmployee(Employee employee) {<br />
            getEmployees().add(employee);<br />
            employee.setDepartment(this);<br />
            return employee;<br />
            }<br />
            public Employee removeEmployee(Employee employee) {<br />
            getEmployees().remove(employee);<br />
            employee.setDepartment(null);<br />
            return employee;<br />
            }<br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
　　每个实体都有一个主键；可以在持久字段或属性上使用Id注释将其标记为主键。实体通过使用字段或属性（通过setter和getter方法）来保存其状态。这取决于在哪里使用O-R映射注释。以上示例使用基于字段的访问；我们已经使用了具有deptNo字段的Id注释。要使用基于属性的访问，就要使用属性标记注释（例如Id），如下所示： <br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e1e1e1" border="1">
    <tbody>
        <tr>
            <td>@Id<br />
            public Long getDeptNo() {<br />
            return deptNo;<br />
            }<br />
            public void setDeptNo(Long deptNo) {<br />
            this.deptNo = deptNo;<br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
　　请记住，对一个实体层次结构中的所有实体，必须应用相同的访问类型（字段或属性）。<br />
<br />
　　默认情况下，定义在实体中的每个字段天然就是持久的；如果不希望保存字段/属性的状态，则必须将字段/属性定义为瞬态的，方法是使用@Transient注释或transient修饰符标记它。 <br />
<br />
　　<strong>可嵌入对象</strong><br />
<br />
　　可嵌入对象是不具有自己标识的持久对象；它是另一个实体的一部分。例如，我们可以假定Address没有自己的标识，且作为Employee实体的一部分存储。因此，Address是可嵌入对象的候选。<br />
<br />
　　可以如下所示创建可嵌入对象： <br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e1e1e1" border="1">
    <tbody>
        <tr>
            <td>@Embeddable <br />
            public class Address { <br />
            protected String streetAddr1; <br />
            protected String streetAddr2; <br />
            protected String city; <br />
            protected String state; <br />
            ..<br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
　　以下是将对象定义为目标实体中的可嵌入对象的方法： <br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e1e1e1" border="1">
    <tbody>
        <tr>
            <td>@Entity<br />
            public class Employee {<br />
            @Id<br />
            @GeneratedValue(strategy=GenerationType.AUTO)<br />
            protected Long id; <br />
            ...<br />
            @Embedded<br />
            protected Address address; <br />
            ...<br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
描述符，因为可以使用它们重写注释。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>关系</strong><br />
<br />
　　在一个典型的域模型中，实体是彼此关联的，或者它们相互之间存在着关系。两个实体之间的关系可以是一对一、一对多、多对一和多对多的。这些关系可以分别使用OneToOne、OneToMany、ManyToOne或ManyToMany注释表示。在我们的示例中，Department和Employee实体之间具有双向OneToMany关系。<br />
<br />
　　既然我们在实体中使用了基于字段的访问，我们就在Department实体的关系字段上指定注释，如下所示： <br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e1e1e1" border="1">
    <tbody>
        <tr>
            <td>@OneToMany(mappedBy="department")<br />
            protected Collection＜Employee＞ employees ;</td>
        </tr>
    </tbody>
</table>
<br />
　　对于双向关系，必须在关系的另一方指定mappedBy元素（如上），方法是指向拥有此关系的字段或属性的名称。 <br />
<br />
　　<strong>标准化O-R映射</strong><br />
<br />
　　可以使用Java元数据注释或XML实现实体的O-R映射。EJB3 JPA定义了多种用于O-R映射的注释，例如Table、SecondaryTable、Column、JoinColumn和PrimaryKeyJoinColumn。请参阅EJB3 JPA规范，以获得关于所有注释的信息。<br />
<br />
　　在我们的示例中，可以使用Table注释定义实体被映射到的表，如下所示： <br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e1e1e1" border="1">
    <tbody>
        <tr>
            <td>@Table(name="DEPT")<br />
            public class Department implements Serializable { </td>
        </tr>
    </tbody>
</table>
<br />
　　EJB3 JPA严重依赖于默认设置，因此如果未定义表映射，则持久性提供程序会假定此实体被映射到与实体类同名的表（在我们的示例中是DEPARTMENT）。如果实体被映射到多个表，则可以使用SecondaryTable注释。<br />
<br />
　　可以使用Column注释将持久字段或属性映射到数据库列，如下所示： <br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e1e1e1" border="1">
    <tbody>
        <tr>
            <td>@Column(name="DNAME")<br />
            protected String name;</td>
        </tr>
    </tbody>
</table>
<br />
　　这里，DNAME是持久字段名称所映射到的列的名称。如果未使用Column注释定义O-R映射，则持久性引擎会尝试将其状态保存在列中（使用与字段或属性相同的名称）。 <br />
<br />
　　<strong>实体继承性</strong><br />
<br />
　　EJB3 JPA支持多种实体继承性方法。它需要两种类型的继承性表映射策略：Single-table-per-entity层次结构策略和Joined-Subclass策略。最好避免使用可选的table-per-class层次结构。<br />
<br />
　　Single-table-per-entity (SINGLE_TABLE)层次结构策略允许将层次结构中的所有实体映射到一个表。在我们的示例中，FullTime和Contractor扩展了Employee，所有这些都可以映射到一个名为EMP的表。换句话说，所有与Employee、FullTime和Contractor有关的数据都被存储于相同的表内。<br />
<br />
　　如果使用Joined Subclass策略，则可以将公共持久数据存储在超类所映射到的表中（例如Employee），并且可以为层次结构中每个子类创建表，以便存储特定于子类的持久字段。<br />
<br />
　　必须在超类中使用Inheritance注释，以指定继承类型，如以下代码所示。此示例展示了使用single-table-per-entity层次结构策略的实体层次结构。 <br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e1e1e1" border="1">
    <tbody>
        <tr>
            <td>@Entity <br />
            @Table(name="EMP") <br />
            @Inheritance(strategy=InheritanceType.SINGLE_TABLE) <br />
            @DiscriminatorColumn(name="EMPLOYEE_TYPE",<br />
            discriminatorType=DiscriminatorType.STRING, length=1) <br />
            public abstract class Employee implements Serializable { <br />
            ...<br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
　　每个子类必须指定用于该实体类型的鉴别器值，如下所示： <br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e1e1e1" border="1">
    <tbody>
        <tr>
            <td>@Entity <br />
            @DiscriminatorValue(value="F") <br />
            public class FullTime extends Employee { <br />
            @Column(name="SAL") <br />
            protected Double salary; <br />
            @Column(name="COMM") <br />
            protected Double commission; <br />
            @Column(name="DESIG")<br />
            protected String designation;<br />
            ...<br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
　　Entity Manager API：用于实体操作的标准API<br />
<br />
　　javax.persistence.EntityManager管理实体生命周期，并公开了多个在实体上执行CRUD操作的方法。<br />
<br />
　　EntityManager API在事务上下文中调用。可以在EJB容器外部（例如，从一个Web应用程序）调用它，而无需会话bean外观。<br />
<br />
　　在执行任何实体操作之前，必须获取EntityManager实例。可以使用容器管理或应用程序管理的实体管理器，可以使用JNDI查找或依赖注入来获取EntityManager实例。正如其名称所暗示的，Java EE容器管理着容器管理实体管理器的生命周期。它可能主要在企业Java应用程序中使用。<br />
<br />
　　可以使用PersistenceContext注入获取容器管理实体管理器实例，如下所示： <br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e1e1e1" border="1">
    <tbody>
        <tr>
            <td>@PersistenceContext(unitName="onjava")<br />
            private EntityManager em;</td>
        </tr>
    </tbody>
</table>
<br />
　　如果使用应用程序管理的实体管理器，则必须管理其生命周期。可以创建一个应用程序管理实体管理器实例，如下所示： <br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e1e1e1" border="1">
    <tbody>
        <tr>
            <td>@PersistenceUnit(unitName="onjava")<br />
            private EntityManagerFactory emf;<br />
            private EntityManager em = emf.createEntityManager();</td>
        </tr>
    </tbody>
</table>
<br />
　　然后可以使用EntityManager实例在实体上执行CRUD操作。要关闭应用程序管理实体管理器实例，请在完成工作后调用em.close()方法。<br />
<br />
　　如前所述，必须在事务上下文中执行涉及任何数据库更改的实体管理器操作。<br />
<br />
　　下表列出了EntityManager接口的一些用于执行实体操作的关键方法。 <br />
<br />
<table cellspacing="0" cellpadding="0" width="90%" align="center" border="1">
    <tbody>
        <tr>
            <td width="65%">方法</td>
            <td width="35%">用途</td>
        </tr>
        <tr>
            <td>public void persist(Object entity);</td>
            <td>持久化实体实例。</td>
        </tr>
        <tr>
            <td>public ＜T＞ T merge(T entity); </td>
            <td>合并分离的实体实例。</td>
        </tr>
        <tr>
            <td>public void remove(Object entity);</td>
            <td>移除实体实例。</td>
        </tr>
        <tr>
            <td>public ＜T＞ T find(Class＜T＞ entityClass, Object primaryKey); </td>
            <td>通过主键检索实体实例。</td>
        </tr>
        <tr>
            <td>public void flush();</td>
            <td>使实体状态与数据库同步。 </td>
        </tr>
    </tbody>
</table>
<br />
　　可以使用persist()方法持久化实体实例。例如，如果想持久化Contractor实例，请使用以下代码： <br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e1e1e1" border="1">
    <tbody>
        <tr>
            <td>@PersistenceContext(unitName="onjava")<br />
            private EntityManager em; <br />
            ... <br />
            Contractor pte = new Contractor(); <br />
            pte.setName("Nistha")<br />
            pte.setHourlyRate(new Double(100.0)); <br />
            em.persist(pte); </td>
        </tr>
    </tbody>
</table>
<br />
　　在持久化实体时，如果此关系的CascadeType被设置为PERSIST或ALL，则任何对关联实体的状态更改也将被持久化。除非正在使用扩展的持久上下文，否则实体将在事务终止后分离。合并操作允许将分离的实体实例与持久上下文合并；分离实体的状态将与数据库同步。这将有助于摆脱EJB 2.x中常见的数据传输对象(Data Transfer Object，DTO)反模式，因为作为POJO的实体可以在层与层之间传输。惟一的要求是实体类必须实现java.io.Serializable接口。&nbsp;<br />
<br />
<strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;查询API</strong><br />
<br />
　　对实体的检索是持久性的一个重要方面。使用EJB3 JPA时，使用Java持久化查询语言(Java Persistence Query Language，JPQL)表示查询。JPQL是EJBQL的扩展，它是作为EJB 2.0规范的一部分而引入的。然而，EJB3 JPA解决了EJBQL的所有局限性，并添加了许多新特性，从而成为一种功能强大的查询语言。 <br />
<br />
　　<strong>JPQL较之EJBQL 2.x的改进</strong><br />
<br />
　　以下是EJB3 JPA中的JPQL的新特性： <br />
<br />
　　&#183;简化了的查询语法 <br />
<br />
　　&#183;JOIN操作 <br />
<br />
　　&#183;Group By和Having Clause <br />
<br />
　　&#183;子查询 <br />
<br />
　　&#183;动态查询 <br />
<br />
　　&#183;指定参数(named parameter) <br />
<br />
　　&#183;批量更新和删除 <br />
<br />
　　此外，如果希望从特定于数据库的查询扩展中获益，则必须对查询实体使用原生(native ) SQL。 <br />
<br />
　　<strong>动态查询与指定查询</strong><br />
<br />
　　可以使用动态查询或指定查询(named query)。指定查询随实体存储，可从应用程序重用。<br />
<br />
　　要创建动态查询，请使用实体管理器接口的createQuery方法，如下所示： <br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e1e1e1" border="1">
    <tbody>
        <tr>
            <td>Query query = em.createQuery( <br />
            "select e from Employee e where e.empNo ＞ 1"); <br />
            query.setParameter(1,100); <br />
            return query.getResultList();</td>
        </tr>
    </tbody>
</table>
<br />
　　如果希望将此查询用作指定查询，请在实体中使用NamedQuery注释，如下所示： <br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e1e1e1" border="1">
    <tbody>
        <tr>
            <td>@Entity <br />
            @NamedQuery(name="findAllEmployee", <br />
            query="select e from Employee e where e.empNo ＞ 1")<br />
            public abstract class Employee implements Serializable { <br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
　　要执行指定查询，首先使用EntityManager接口上的createNamedQuery方法创建一个Query实例，如下所示： <br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e1e1e1" border="1">
    <tbody>
        <tr>
            <td>query = em.createNamedQuery(" findAllEmployee");<br />
            query.setParameter(1,100); <br />
            return query.getResultList();</td>
        </tr>
    </tbody>
</table>
<br />
　　<strong>指定参数</strong><br />
<br />
　　可以在EJBQL查询中使用指定参数(named parameter)代替位置参数(positional parameter)。例如，可以将以上查询重写如下：<br />
<br />
　　"select e from Employee e where e.empNo ＞ :empNo "<br />
<br />
　　如果在查询中使用指定参数，则必须设置此参数如下： <br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e1e1e1" border="1">
    <tbody>
        <tr>
            <td>query = em.createNamedQuery("findAllEmployee");<br />
            query.setParameter("empNo",100);<br />
            return query.getResultList();</td>
        </tr>
    </tbody>
</table>
<br />
　　<strong>打包</strong><br />
<br />
　　EJB3 JPA标准化了POJO持久性。因此，实体并不局限于EJB模块；它们能够打包到Web模块、ejb-jar模块、EAR级中的库模块或标准jar文件中。也可以在Java SE中使用实体。必须在包含实体的档案文件中打包描述符(persistence.xml)，如下所示： <br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e1e1e1" border="1">
    <tbody>
        <tr>
            <td>＜persistence＞ <br />
            ＜persistence-unit name="onjava"＞ <br />
            ＜provider＞oracle.toplink.essentials.PersistenceProvider＜/provider＞<br />
            ＜jta-data-source＞jdbc/OracleDS＜/jta-data-source＞ <br />
            ...<br />
            ＜/persistence-unit＞ <br />
            ＜/persistence＞</td>
        </tr>
    </tbody>
</table>
<br />
　　此描述符标识持久性提供程序、持久单元和持久单元所使用的数据源。正如其名称所暗示的，持久单元是集中管理的实体的集合。如果有一个定义在特定模块中的持久单元，就不需要在persistence.xml中标识实体类；它将由持久性提供程序动态发现。 <br />
<br />
　　<strong>参考实现</strong><br />
<br />
　　BEA Kodo以及Oracle TopLink的TopLink Essentials都提供了EJB3 JPA的参考实现。它可分别从Open JPA和GlassFish开源项目中得到。<br />
<br />
　　您可以在参考实现服务器或其他任何服从EJB3 JPA的应用服务器上使用本文中的代码。 <br />
<br />
　　<strong>EJB3 JPA工具</strong><br />
<br />
　　开发工具确实能够帮助构建更好的应用程序，而如果使用XML实现O-R映射，情况可能就不太妙了。<a class="bluekey" href="http://dev.yesky.com/eclipse/" target="_blank">Eclipse</a> Dali O-R映射项目，Oracle JDeveloper 10.1.3和BEA Workshop studio之类的工具都支持EJB3 JPA。 <br />
<br />
　　<strong>结束语</strong><br />
<br />
　　EJB3 Java Persistence API标准化了面向Java平台的持久性API。它通过使用元数据注释和异常配置方法，简化了透明持久性的使用。多种应用服务器已支持EJB3规范（编者注：BEA已经发布WebLogic Server EJB 3.0 Tech Preview ）。随着Java EE 5.0和EJB 3.0规范的完成，您将很快看到许多一流的应用服务器和持久性提供程序会实现EJB3 Java Persistence API。您可以使用来自GlassFish项目的 参考实现 来启用EJB3 Persistence。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;原文：http://dev.yesky.com/396/2498396.shtml
<img src ="http://www.blogjava.net/sailor/aggbug/214187.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sailor/" target="_blank">sailor</a> 2008-07-11 10:26 <a href="http://www.blogjava.net/sailor/articles/214187.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>