??xml version="1.0" encoding="utf-8" standalone="yes"?>欧美精品久久久久久,国模极品一区二区三区,亚洲高清在线观看http://www.aygfsteel.com/liaojiyong/category/12588.htmlzh-cnWed, 28 Feb 2007 19:04:41 GMTWed, 28 Feb 2007 19:04:41 GMT60Z么要使用EJBQ??http://www.aygfsteel.com/liaojiyong/archive/2006/08/02/61344.htmlliaojiyongliaojiyongWed, 02 Aug 2006 07:56:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2006/08/02/61344.htmlhttp://www.aygfsteel.com/liaojiyong/comments/61344.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2006/08/02/61344.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/61344.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/61344.html 

板桥里h http://www.jdon.com 2004/03/08

  首先Q我们必L,Z么要使用J2EEQJ2EE优点是什么?使用J2EE的主要原因是多层l构Q传l的两层C/Sl构难于l护Q稳定性极差,界面代码和数据库代码h在一P牵一动百Q多层结构得界面和数据库完全分,q且诞生了中间gq样的技术,如下图:

Web+EJB能组成真正的多层l构

  Z么用EJB我原先认不是一个讨论的话题Q因为EJB是J2EE重要的组成部分,可以说没有EJB的J2EE只是一UWebpȝQ这Lpȝ非常Ҏ(gu)丧失了多层结构的大部分优点(仔细x那些混合多种层次功能JavaBeans和传l两层结构有什么区别?Q?/p>

   当然Q可以h为地在Javabeans之间q行层次划分Q例如Hibernate数据持久层Q某些JavaBeans是业务核心层Q但是因为都是普?JavaBeansQ这U划分没有一U强制性和明显标志性,q样的系l更换了d人员或设计师Q可能就会被新的E序员修改得非常混ؕ?/p>

  我们先看看一个包含EJB的J2EEpȝ是如何清晰地表达层次。如下图Q?/p>

  Web完全只是一个MVC模式的实玎ͼ关键业务核心是在EJB的服务层实现Q这样做的优Ҏ(gu)QWeb只负责界面相关部分,因ؓQ如果是一个智能客LQ如Swing或J2MEQ在不需要修改Q何业务核心的情况下能够方便地更换。同P提供Web Services功能Q也只是?Web层修改,不会涉及EJB斚w的修改,同样保证了系l的E_性,保证了系l升U和未来的扩展性?/p>

  如果不用EJBQ在EJB服务层实现的业务核心?yu)由普通JavaBeans实现Q用何U架构或设计能够保证负责MVC的JavaBeans和负责业务核心的JavaBeans清晰地分开Q又如何保证在新的程序员不会破坏和打׃_ֿ布局的JavaBeans架构Q?/p>

EJB提供性能优化支持

  最主要的是性能问题Q由于以前国内中文Java|站有些人弯曲EJBQ认为EJB性能低,其实q是一U非常肤错误的认识Q我们首先看看在一般Java环境中是如何提高性能?/p>

  假定一个JavaBeans为AQ那么一般用这个JavaBeans命o如下Q?/p>

  A a = new A();

   但是Q在高访问量的环境中Qnew A()其实是很Ҏ(gu)消耗系l性能的,因此Q能不能在Y件系l启动时候就预先建立一些对象,q样Q系l运行时Q从q些已经生成的对象池中借用一个,q样Q就 无需在用时q行NewQ节U了开销Q提高了性能Q因此,真正成熟性能解决Ҏ(gu)都是需要对象池{支持?/p>

   在一个纯Webl构的系l(也就是只能运行在Tomat环境中)Q例如Struts + Hibernate{这LpȝQ除非自己动手做Q一般是没有对象池技术支持的Q因此他们的性能只能是Demo演示版本的性能Q根本无法承受大定wq发 讉KQ也无法UCؓ一个成熟的pȝQ所以,我们研究成熟的开源WebpȝQ如Jive、OFBizeQLifeRay{,他们都在Web层拥有自q对象?和缓存池?/p>

  对象池和~存机制是J2EE必须的吗Q当Ӟ是所有成熟系l必ȝQWindowspȝ如果L~存会变得怎样Q?/p>

  自己动手开发对象池和缓存机制ƈ不是一件简单的事情Q需要对多线E以及同步锁{底层原理有深层ơ的把握Q这其实也是一门非常深入的Java研究分支Q所以,你可以抛开你的客户焦急的催促Q精心研I开发自q对象池和~存池?/p>

   但是QEJB容器Q如JBossQ已l提供了对象池和~存机制Q所以,没有事务机制的无状态Session Bean的性能肯定要强于普通JavaBeans。EJB容器不但在单Z提供了对象池和缓存,而且可以跨服务器实现动态负载^衡,q些都无需开发者自?开发Q何Y件代码,l构如下Q?/p>

EJBlg能提供真正的可重用框?/h3>

  每一个jar包代表一个EJBlgQ一个系l可以由多个可重用的EJBlg构成Q例如:树Şl构EJBlgQ自增序号EJBlgQ用戯料EJBlg{,q样的EJBlg可以象积木一h配在大部分应用系l中Q提高了pȝ的开发效率,保证了开发质量?/p>

  下图是某个新的具体系l时应用到的EJBlg图,在这个新的应用中Q由于用了以前大量可重用的EJBlgQ新的开发工作基本集中在界面设计和流E安排上Q?/p>

EJB提供了事务机?/h3>

  事务机制对于一些关键事务是很重要的Q例如ATM机提ƾ,提款有多个动作:修改数据库以及数qQ如果这其中有Q何一个环节出错,那么其它已经实现的操作必还原,否则Q就会出玎ͼ提款人没有拿到钱Q但是卡上已l扣Ƅ不可思议的事情发生?/p>

   EJB提供的事务机刉常周全,但事务机制带来的~点是性能的降低,因此Q有些h认ؓEJB很重Q因为在实际应用中,有的用户pȝ可能不需要事务机Ӟ 只是需要EJB提供的性能优化机制Q这P如果使用EJBQ就象叫一个h来背东西Q他除了背着我要的东西外Q还背着我不要的东西?/p>

  除非你是一个完主义,在一般企业应用或数据库系l应用中QEJB不会对你构成很重的包袱?/p>

CMP独特的优?/h3>

  开源以及一些数据库持久层技术崇拜者,一直抨击CMPQ认为CMP慢无用,实际最大的问题是他们的设计和用问题?/p>

   ׃EJB容器Q如JBossQ对CMP实现有事务机制的~存优化Q因此,CMP特别适合多个用户同时更新同一个数据源的情况,CMPq种严格的事务完 整性保证多个用户同时操作一个数据记录时Q能够保证性能优化和数据的完整性,如果q个数据记录是是软gpȝ的状态标志,它的状态会影响pȝ中很多的环节Q?那么状态更改的重要性不a而喻?/p>

  如果没有事务完整性支持,你的软gpȝ在用戯问量变大Q就会变得发生各U不可能发生的逻辑错误Q查看程序逻辑是正的Q那么问题出在哪里?出在数据完整性上?/p>

   ׃每个CMP在内存中都有一个缓存,在实际应用中Q如果用CMP扚wL据库数据Q几万条查询完毕Q内存中充满了几万条CMP~存Q如果这时你?EJB容器讄不当Q如使用JBoss~省配置Q,那么JVM的垃圑֛收机制就会频J启动,D你的pȝ变慢甚至LQ这也是一些h抨击CMP慢的原因所 在,其实他们使用Ҏ(gu)不当Q或者没有正配|EJB容器CMP~存?/p>

  对于q种情况Q根据J2EE核心模式Q推荐用DAO+JDBC方式?/p>

   除非你对设计模式非常_深Q能够将自己pȝ中的JavaBeans使用模式或某U框架进行固定分层,同时Q你孜孜不倦研发出对象池,又熟l于JTA{事 务机Ӟ你可以选择没有EJB的纯Webl构Q就象Jive、OFBiz那样。当然还有一个前提,老板不懂或者非常有挑战性(做与IBM SUN 微Y齐名的公司和技术)?/p>

  不要再被TSS那些狂热的开源先生误|他们有时间有保障可以做他们喜Ƣ的事情Q作Z业的J2EEE序员,按照J2EE标准d习去行动Q也不要认ؓQ只要用了J2EE其中某个技术如Jsp或JavaBeans心安理得认qpȝ是J2EE了?/p>

  当然Q我q不是说UWebpȝ不能实现多层l构Q但是至在很多斚w没有Web+EJBl构完善和清晎ͼ所以,EJB不是J2EE可以忽视的部分,而是主要的重要的部分Q重要业务功能核心都装在EJB中,相反Web层是一U次要的、和界面相关的层ơ?/p>

  补充Q什么情况下不需要EJBQ在SUN的SECA架构师试卷中回答Q小型系l和不需要事务。另外过去那U认为“EJB有性能问题”根本是一U缪误,具体可参考下面有关问题?/p> 

liaojiyong 2006-08-02 15:56 发表评论
]]>
EJB 3.0 学习W记——Entity BeanQ{Q?/title><link>http://www.aygfsteel.com/liaojiyong/archive/2006/07/21/59317.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Thu, 20 Jul 2006 17:39:00 GMT</pubDate><guid>http://www.aygfsteel.com/liaojiyong/archive/2006/07/21/59317.html</guid><wfw:comment>http://www.aygfsteel.com/liaojiyong/comments/59317.html</wfw:comment><comments>http://www.aygfsteel.com/liaojiyong/archive/2006/07/21/59317.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/liaojiyong/comments/commentRss/59317.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/liaojiyong/services/trackbacks/59317.html</trackback:ping><description><![CDATA[ <p>在EJB 3.0 学习W记——准备工作中只是单的搭好了EJB3.0开发的基本环境Q之</p> <p>后就可以开发最单的Session Bean了,我感兴趣的还是Entity BeanQ所以接下来</p> <p>我想先试验一下Entity Bean?br /> <br />一、在JBoss中配|好Data Source<br />我用的是MySQL数据库,所以首先将MySQL的JDBC驱动复制?br />jboss-4.0.3SP1\server\all\lib目录Q然后将jboss-4.0.3SP1\docs\examples\jca</p> <p>下的mysql-ds.xml作出适当修改后复制到jboss-4.0.3SP1\server\all\deploy目录</p> <p>下,q是我修改后的mysql-ds.xml文gQ?/p> <p><?xml version="1.0" encoding="UTF-8"?></p> <p><!-- $Id: mysql-ds.xml,v 1.3.2.1 2004/12/01 11:46:00 schrouf Exp $ --><br /><!--  Datasource config for MySQL using 3.0.9 available from:<br /><a ><font color="#000080">http://www.mysql.com/downloads/api-jdbc-stable.html</font></a><br />--></p> <p><datasources><br />  <local-tx-datasource><br />    <jndi-name>MySqlDS</jndi-name><br />    <connection-url>jdbc:mysql://localhost:3306/test</connection-url><br />    <driver-class>com.mysql.jdbc.Driver</driver-class><br />    <user-name>test</user-name><br />    <password></password><br />    <exception-sorter-class-</p> <p>name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</excepti</p> <p>on-sorter-class-name><br />    <!-- sql to call when connection is created<br />    <new-connection-sql>some arbitrary sql</new-connection-sql><br />      --><br />    <!-- sql to call on an existing pooled connection when it is obtained </p> <p>from pool <br />    <check-valid-connection-sql>some arbitrary sql</check-valid-</p> <p>connection-sql><br />      --></p> <p>    <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml </p> <p>(optional) --><br />    <metadata><br />       <type-mapping>mySQL</type-mapping><br />    </metadata><br />  </local-tx-datasource><br /></datasources><br />q样之后QJBoss下的MySQL Data Source配置完成?/p> <p>二、创建数据库q编写Entity Bean代码</p> <p>create table book(<br />id int not null auto_increment primary key,<br />title varchar(20) not null,<br />author varchar(40) not null<br />);<br />新徏Java ProjectQ导入User LibraryQEJB3_JBossQ以下是cM码?/p> <p>//Book.java<br />package ejb.bean.entity;</p> <p>import java.io.Serializable;</p> <p>import javax.persistence.Entity;<br />import javax.persistence.GeneratedValue;<br />import javax.persistence.GenerationType;<br />import javax.persistence.Id;<br />import javax.persistence.Table;</p> <p>@Entity<br />@Table(name="book")<br />public class Book implements Serializable {<br /> /**<br />  * <br />  */<br /> private static final long serialVersionUID = 1L;<br /> private Integer id; <br /> private String title; <br /> private String author;<br /> <br /> public Book() {  <br />  super(); <br /> } <br /> public Book(Integer id, String title, String author) { <br />  super();  <br />  this.id = id;  <br />  this.title = title;  <br />  this.author = author; <br />  }<br /> @Override<br /> public String toString() { <br />  <br />  return "Book: " + getId() + " Title " + getTitle() + " </p> <p>Author " + getAuthor(); <br /> }<br /> public String getAuthor() {<br />  return author;<br /> }<br /> <br /> @Id @GeneratedValue(strategy=GenerationType.AUTO)<br /> public Integer getId() {<br />  return id;<br /> }<br /> public String getTitle() {<br />  return title;<br /> }<br /> public void setAuthor(String author) {<br />  this.author = author;<br /> }<br /> public void setId(Integer id) {<br />  this.id = id;<br /> }<br /> public void setTitle(String title) {<br />  this.title = title;<br /> }</p> <p>}</p> <p>三、编写一个简单的Stateless Session Bean q进行测?/p> <p>//BookTestLocal.java<br />package ejb.bean.entity;</p> <p>import javax.ejb.Local;</p> <p>@Local<br />public interface BookTestLocal {</p> <p> public void test();<br />}</p> <p>//BookTestRemote.java<br />package ejb.bean.entity;</p> <p>import javax.ejb.Remote;<br />@Remote<br />public interface BookTestRemote {<br /> <br /> public void test();</p> <p>}</p> <p>//BookTestBean.java<br />package ejb.bean.entity;</p> <p>import javax.ejb.Stateless;<br />import javax.persistence.EntityManager;<br />import javax.persistence.PersistenceContext;</p> <p>@Stateless<br />public class BookTestBean implements BookTestLocal, BookTestRemote {</p> <p> @PersistenceContext<br /> EntityManager em;<br /> public void test() {<br />  // TODO Auto-generated method stub<br />  Book book = new Book(null, "My first bean book", </p> <p>"Sebastian");<br />  em.persist(book);</p> <p> }</p> <p>}</p> <p> <br />//Client.java<br />package ejb.client.entity;</p> <p>import ejb.bean.entity.*;</p> <p> <br />import javax.naming.InitialContext;</p> <p>/**<br /> * Comment<br /> *<br /> * @author <a href="<a href="mailto:bill@jboss.org">Bill"><font color="#000080">mailto:bill@jboss.org">Bill</font></a> Burke</a><br /> * @version $Revision: 1.1.6.7 $<br /> */<br />public class Client<br />{<br />   public static void main(String[] args) throws Exception<br />   {<br />      InitialContext ctx = new InitialContext();<br />      BookTestRemote book = (BookTestRemote) ctx.lookup</p> <p>("BookTestBean/remote");</p> <p>     </p> <p>   <br />      book.test();<br />      <br />      System.out.println("test successful! ");</p> <p>   }<br />}</p> <p>三、其他文?br />jboss-EJB-3.0_RC5-PFD\docs\tutorial中的扑ֈ的jndi.properties、log4j.xml</p> <p>、builder.xml{复制到当前工程中,其中builder.xml需要修攏V?br />//builder.xml<br /><?xml version="1.0"?></p> <p><!-- </p> <p>======================================================================= </p> <p>--><br /><!-- JBoss build file                                                     </p> <p>  --><br /><!-- </p> <p>======================================================================= </p> <p>--></p> <p><project name="JBoss" default="ejbjar" basedir="."></p> <p>   <property file="../local.properties" /><br />   <property environment="env"/><br />   <property name="src.dir" value="${basedir}/src"/><br />   <property name="jboss.home" value="E:/Programming/Servers/jboss-</p> <p>4.0.3SP1/"/><br />   <property name="jboss.server.config" value="all"/><br />   <property name="build.dir" value="${basedir}/build"/><br />   <property name="build.classes.dir" value="${build.dir}/classes"/></p> <p>   <!-- Build classpath --><br />   <path id="classpath"><br />      <!-- So that we can get jndi.properties for InitialContext --><br />      <pathelement location="${basedir}"/><br />      <fileset dir="${jboss.home}/lib"><br />         <include name="**/*.jar"/><br />      </fileset><br />      <fileset dir="${jboss.home}/server/${jboss.server.config}/lib"><br />         <include name="**/*.jar"/><br />      </fileset><br />      <fileset dir="${jboss.home}/server/</p> <p>${jboss.server.config}/deploy/ejb3.deployer"><br />         <include name="*.jar"/><br />      </fileset><br />      <fileset dir="${jboss.home}/server/</p> <p>${jboss.server.config}/deploy/jboss-aop-jdk50.deployer"><br />         <include name="*.jar"/><br />      </fileset><br />      <pathelement location="${build.classes.dir}"/><br />   </path></p> <p>   <property name="build.classpath" refid="classpath"/></p> <p>   <!-- </p> <p>=================================================================== --><br />   <!-- Prepares the build directory                                      </p> <p>  --><br />   <!-- </p> <p>=================================================================== --><br />   <target name="prepare"><br />      <mkdir dir="${build.dir}"/><br />      <mkdir dir="${build.classes.dir}"/><br />   </target></p> <p>   <!-- </p> <p>=================================================================== --><br />   <!-- Compiles the source code                                          </p> <p>  --><br />   <!-- </p> <p>=================================================================== --><br />   <target name="compile" depends="prepare"><br />      <javac srcdir="${src.dir}"<br />         destdir="${build.classes.dir}"<br />         debug="on"<br />         deprecation="on"<br />         optimize="off"<br />         includes="**"><br />         <classpath refid="classpath"/><br />      </javac><br />   </target></p> <p>   <target name="ejbjar" depends="compile"><br />      <jar jarfile="build/tutorial.jar"><br />         <fileset dir="${build.classes.dir}"><br />            <include name="**/*.class"/><br />         </fileset><br />        <fileset dir="."><br />           <include name="META-INF/persistence.xml"/><br />        </fileset><br />      </jar><br />      <copy file="build/tutorial.jar" todir="${jboss.home}/server/</p> <p>${jboss.server.config}/deploy"/><br />   </target></p> <p>   <target name="run.stateless" depends="ejbjar"><br />      <java classname="ejb.client.stateless.Client" fork="yes" dir="."><br />         <classpath refid="classpath"/><br />      </java><br />   </target><br /> <br /> <target name="run.stateful" depends="ejbjar"><br />       <java classname="ejb.client.stateful.Client" fork="yes" </p> <p>dir="."><br />          <classpath refid="classpath"/><br />       </java><br /> </target><br /> <br /> <target name="run.timer" depends="ejbjar"><br />       <java classname="ejb.client.timer.Client" fork="yes" </p> <p>dir="."><br />          <classpath refid="classpath"/><br />       </java><br /> </target><br /> <br /> <target name="run.entity" depends="ejbjar"><br />        <java classname="ejb.client.entity.Client" </p> <p>fork="yes" dir="."><br />           <classpath refid="classpath"/><br />        </java><br />  </target><br /> </p> <p>   <!-- </p> <p>=================================================================== --><br />   <!-- Cleans up generated stuff                                         </p> <p>  --><br />   <!-- </p> <p>=================================================================== --><br />   <target name="clean.db"><br />      <delete dir="${jboss.home}/server/</p> <p>${jboss.server.config}/data/hypersonic"/><br />   </target></p> <p>   <target name="clean"><br />      <delete dir="${build.dir}"/><br />      <delete file="${jboss.home}/server/</p> <p>${jboss.server.config}/deploy/tutorial.jar"/><br />   </target></p> <p> <br /></project></p> <p>最后,在工E目录下新徏目录META-INFQ在目录META-INF新徏persistence.xml文g</p> <p>Q以下是文g内容Q?br /><?xml version="1.0" encoding="UTF-8"?><br /><persistence><br />   <persistence-unit name="test"><br />      <jta-data-source>java:/MySqlDS</jta-data-source><br />      <properties><br />       <property name="hibernate.dialect" </p> <p>value="org.hibernate.dialect.MySQLDialect"/>       <br />        <property name="hibernate.hbm2ddl.auto" value="update"/><br />      </properties><br />   </persistence-unit><br /></persistence></p> <p>四、运行测?br />run as->ant build后,选择q行目标为run.entity->run?br />q行l果Q?br />Buildfile: D:\Programs\Java\EclipseWork\EJB3\build.xml<br />prepare:<br />compile:<br />ejbjar:<br />run.entity:<br />     [java] test successful!<br />BUILD SUCCESSFUL<br />Total time: 9 seconds</p> <p> <br />MySQL中select * from book;<br />id        title                     author<br />1        My first bean book         Sebastian<br />已经成功写入?/p> <p> </p> <img src ="http://www.aygfsteel.com/liaojiyong/aggbug/59317.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/liaojiyong/" target="_blank">liaojiyong</a> 2006-07-21 01:39 <a href="http://www.aygfsteel.com/liaojiyong/archive/2006/07/21/59317.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB 3.0开发指南之l合主键http://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56460.htmlliaojiyongliaojiyongTue, 04 Jul 2006 01:28:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56460.htmlhttp://www.aygfsteel.com/liaojiyong/comments/56460.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56460.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/56460.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/56460.html
  ?

@Id(generate = GeneratorType.AUTO)
public int getId()
{
 return id;
}

  事实?主键可以是Q意的java基本cd、或者是基本cd的包装类Q如Integer、Stringcd、或者是带字D|属性的主键cR注意,如果q样使用主键,你需要将主键的注释中的生成规则改为NONE。就是由E序生成主键倹{?br />
  主键cdd现hashCode和equalsҎ(gu)?br />
  q个例子前面举例q,是一个存储学生信息的实体beanQ在那个例子中,使用NamecM为属性,q且以Id作ؓ主键Q在q个例子中,我们用name作ؓ主键Q注意name的类型一个javacR和前面的例子一P我们q是使用Client试?br />
  Name.javaQ主键?br />
  Student.javaQ实体BeancR?br />
  StudentDAO.javaQ会话Bean的业务接?br />
  StudentDAOBean.javaQ会话Bean的实现类

  Client.javaQ测试EJB的客LcR?br />
  jndi.propertiesQjndi属性文Ӟ提供讉Kjdni的基本配|属性?br />
  Build.xmlQant 配置文gQ用以编译、发布、测试、清除EJB?br />
  下面针对每个文g的内容做一个介l?br />
  Name.java

package com.kuaff.ejb3.composite;

import java.io.Serializable;
import javax.ejb.AccessType;
import javax.ejb.DependentObject;

@DependentObject(access = AccessType.PROPERTY)

public class Name implements java.io.Serializable
{
 private String first;
 private String last;

 public Name()
 {
 }

 public Name(String first, String last)
 {
  this.first = first;
  this.last = last;
 }

 public String getFirst()
 {
  return first;
 }

 public void setFirst(String first)
 {
  this.first = first;
 }

 public String getLast()
 {
  return last;
 }

 public void setLast(String last)
 {
  this.last = last;
 }

 public int hashCode()
 {
  return (first+last).hashCode();
 }

 public boolean equals(Object object)
 {
  if (this == object) return true;
  if (object == null) return false;
  if (! (object instanceof Name)) return false;
  Name name = (Name)object;
  if ((name.first.equals(first)) && (name.last.equals(last)))
   return true;
  else
   return false;
 }

}

  Student.java

package com.kuaff.ejb3.composite;

import javax.ejb.Dependent;
import javax.ejb.DependentAttribute;
import javax.ejb.Column;
import javax.ejb.Entity;
import javax.ejb.GeneratorType;
import javax.ejb.Id;
import javax.ejb.Table;

@Entity @Table(name = "STUDENT") public class Student implements java.io.Serializable
{
 private Name name;
 private String grade;
 private String email;

 public void setName(Name name)
 {
  this.name = name;
 }

 @Id(generate = GeneratorType.NONE)
 @Dependent(
  { @DependentAttribute(name = "first", column ={ @Column(name = "FIRST") }),
   @DependentAttribute(name = "last", column ={ @Column(name = "LAST") }) })
   public Name getName()
   {
    return name;
   }

 public void setGrade(String grade)
 {
  this.grade = grade;
 }

 @Column(name = "GRADE")
 public String getGrade()
 {
  return grade;
 }

 public void setEmail(String email)
 {
  this.email = email;
 }

 @Column(name = "EMAIL")

 public String getEmail()
 {
  return email;

  StudentDAO.java

package com.kuaff.ejb3.composite;

import javax.ejb.Remote;
import java.util.List;

@Remote

public interface StudentDAO

{

void create(String first, String last, String grade, String email);



Student find(Name name);

List findByFirstName(String name);

List findByLastName(String name);

List findByEmail(String email);



void merge(Student s);

}

  StudentDAOBean.java

package com.kuaff.ejb3.composite;

import java.util.List;
import javax.ejb.EntityManager;
import javax.ejb.Inject;
import javax.ejb.Stateless;

@Stateless

public class StudentDAOBean implements StudentDAO
{
 @Inject
 private EntityManager manager;

 public void create(String first, String last, String grade, String email)
 {
  Student student = new Student();
  student.setName(new Name(first,last));
  student.setGrade(grade);
  student.setEmail(email);
  manager.create(student);
 }

 public Student find(Name name)
 {
  return manager.find(Student.class, name);
 }

 public List findByFirstName(String name)
 {
  return manager.createQuery("from Student s where s.name.last = :name").setParameter("name", name).listResults();

 }

 public List findByLastName(String name)
 {
  return manager.createQuery("from Student s where s.name.first = :name").setParameter("name", name).listResults();
 }

 public List findByEmail(String email)
 {
  return manager.createQuery("from Student s where s.email = :email").setParameter("email", email).listResults();
 }

 public void merge(Student s)
 {
  manager.merge(s);
 }

}

  Client.java

package com.kuaff.ejb3.composite;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.List;

public class Client
{
 public static void main(String[] args) throws NamingException
 {
  InitialContext ctx = new InitialContext();
  StudentDAO dao = (StudentDAO) ctx.lookup(StudentDAO.class.getName());
  dao.create("?,"x","8","smallnest@kuaff.com");
  dao.create("?,"立焕","6","zhuzhu@kuaff.com");
  Name name = new Name("?,"立焕");

  //List list = dao.findByEmail("zhuzhu@kuaff.com");

  Student s = dao.find(name);
  System.out.printf("%s %s的email:%s%n",s.getName().getFirst(),s.getName().getLast(),s.getEmail());
  /*
   for(Object o:list)
   {
    Student s = (Student)o;
    System.out.printf("%s %s的email:%s%n",s.getName().getFirst(),s.getName().getLast(),s.getEmail());
   }
  */
 }
}

  q个客户端用来测试?br />
  误行{$JBOSS_HOME}/bin目录下的run.bat: run –c all,启动JBOSS?br />
http://localhost:8080/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss%3Aservice%3DHypersonic%2Cdatabase%3DlocalDBQ然后调用startDatabaseManager()Ҏ(gu)Q打开HSQL理工具理数据库?br />
  在Eclipse的Ant视图中执行ejbjar target。或者在命o行下Q进入到此工E目录下Q执行ant ejbjar,编译打包发布此EJB?br />
  在Eclipse的Ant视图中执行run target。或者在命o行下Q进入到此工E目录下Q执行ant run,试q个EJB?br />

liaojiyong 2006-07-04 09:28 发表评论
]]>
EJB3.0开发指南之多对多和一对一http://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56459.htmlliaojiyongliaojiyongTue, 04 Jul 2006 01:27:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56459.htmlhttp://www.aygfsteel.com/liaojiyong/comments/56459.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56459.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/56459.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/56459.html
  学生和老师是多对多的关系。一个学生有多个老师Q一个老师教多个学生?br />
  学生和档案就是一对一的关p(不知道国外的学生有没有档案?Q?br />
  Z实现多对多的关系Q数据库中需要关联表Q用以在两个实体间徏立关联。JBoss可以自动生成兌表,你也可以@AssociationTable来指定关联表的信息?br />
  ?

@ManyToMany(cascade = {CascadeType.CREATE, CascadeType.MERGE}, fetch = FetchType.EAGER, isInverse = true)
@AssociationTable(table = @Table(name = "STUDENT_TEACHER"),

joinColumns = {@JoinColumn(name = "TEACHER_ID")},inverseJoinColumns = {@JoinColumn(name = "STUDENT_ID")})

@ AssociationTable的注释声明如下:
@Target({METHOD, FIELD})

public @interface AssociationTable {
 Table table() default @Table(specified=false);
 JoinColumn[] joinColumns() default {};
 JoinColumn[] inverseJoinColumns() default {};
}

  兌表注释指定了兌表的名称、主表的列和从表的列?br />
  Z实现一对一的关p,需要用@OneToOne来注释?

  ?

@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "DOSSIER_ID")

public Dossier getDossier()
{
 return dossier;
}

  q定义了一个单向的一对一的关pR如果在Dossier也定义了相关的关联,那么它就是双向的。双向的意思就是通过一个Student实体可以查扑ֈ一个DossierQ通过一个Dossier可以查扑ֈ一个Student?br />
@ OneToOne的注释声明如下:
@Target({METHOD, FIELD}) @Retention(RUNTIME)

public @interface OneToOne {
 String targetEntity() default "";
 CascadeType[] cascade() default {};
 FetchType fetch() default EAGER;
 boolean optional() default true;
}

  q个例子主要有以下几个文Ӟq个例子主要实现了学生和老师、学生和档案之间的关pRStudent、Teacher、Dossier都是实体Bean。Student和Dossier是一个双向的OneToOne之间的关p,Student和Teacher是ManyToMany的关p,也是双向的。和前面的例子一P我们q是使用Client试?br />
  Student.javaQ实体Bean?br />
  Dossier.javaQ实体Bean所依赖的类?br />
  Teacher.javaQ实体Bean所依赖的类?br />
  EntityTest.javaQ会话Bean的业务接?br />
  EntityTest Bean.javaQ会话Bean的实现类

  Client.javaQ测试EJB的客LcR?br />
  jndi.propertiesQjndi属性文Ӟ提供讉Kjdni的基本配|属性?br />
  Build.xmlQant 配置文gQ用以编译、发布、测试、清除EJB?br />
  下面针对每个文g的内容做一个介l?br />
  Student.java

package com.kuaff.ejb3.relationships;
import javax.ejb.CascadeType;
import javax.ejb.Entity;
import javax.ejb.FetchType;
import javax.ejb.GeneratorType;
import javax.ejb.Id;
import javax.ejb.JoinColumn;
import javax.ejb.OneToOne;
import javax.ejb.ManyToMany;
import javax.ejb.Table;
import javax.ejb.AssociationTable;
import java.util.ArrayList;
import java.util.Set;
import java.util.Collection;
import java.io.Serializable;

@Entity

@Table(name = "STUDENT")

public class Student implements Serializable

{
 private int id;
 private String first;
 private String last;
 private Dossier dossier;
 private Set<Teacher> teachers;

 @Id(generate = GeneratorType.AUTO)

 public int getId()
 {
  return id;
 }

 public void setId(int id)
 {
  this.id = id;
 }

 public void setFirst(String first)
 {
  this.first = first;
 }

 public String getFirst()
 {
  return first;
 }

 public void setLast(String last)
 {
  this.last = last;
 }

 public String getLast()
 {
  return last;
 }

 public void setDossier(Dossier dossier)
 {
  this.dossier = dossier;
 }

@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "DOSSIER_ID")

public Dossier getDossier()
{
 return dossier;
}

public void setTeacher(Set<Teacher> teachers)
{
 this.teachers = teachers;
}

@ManyToMany(cascade = {CascadeType.CREATE, CascadeType.MERGE}, fetch = FetchType.EAGER, isInverse = true)
@AssociationTable(table = @Table(name = "STUDENT_TEACHER"),

joinColumns = {@JoinColumn(name = "TEACHER_ID")},inverseJoinColumns = {@JoinColumn(name = "STUDENT_ID")})

public Set<Teacher> getTeacher()
{
 return teachers;
}
}


  Dossier.java

package com.kuaff.ejb3.relationships;

import javax.ejb.Entity;
import javax.ejb.GeneratorType;
import javax.ejb.Id;

@Entity

public class Dossier implements java.io.Serializable
{
 private Long id;
 private String resume;

 @Id(generate = GeneratorType.AUTO)
 public Long getId()
 {
  return id;
 }

 public void setId(Long id)
 {
  this.id = id;
 }

 public void setResume(String resume)
 {
  this.resume = resume;
 }

 public String getResume()
 {
  return resume;
 }
}


  Teacher.java

package com.kuaff.ejb3.relationships;

import javax.ejb.AssociationTable;
import javax.ejb.Basic;
import javax.ejb.CascadeType;
import javax.ejb.Column;
import javax.ejb.Entity;
import javax.ejb.FetchType;
import javax.ejb.Id;
import javax.ejb.JoinColumn;
import javax.ejb.ManyToMany;
import javax.ejb.Table;
import javax.ejb.Transient;
import javax.ejb.Version;
import java.util.Set;
import javax.ejb.GeneratorType;

@Entity

public class Teacher implements java.io.Serializable
{
 private Long id;
 private String resume;
 private String name;
 private String info;
 private Set<Student> students;

 @Id(generate = GeneratorType.IDENTITY)

 public Long getId()
 {
  return id;
 }

 public void setId(Long id)
 {
  this.id = id;
 }

 public void setName(String name)
 {
  this.name = name;
 }

 public String getName()
 {
  return name;
 }

 public void setInfo(String info)
 {
  this.info = info;
 }

 public String getInfo()
 {
  return info;
 }

 public void setStudents(Set<Student> students)
 {
  this.students = students;
 }

 @ManyToMany(cascade = {CascadeType.CREATE, CascadeType.MERGE}, fetch = FetchType.EAGER)
 @AssociationTable(table = @Table(name = "STUDENT_TEACHER"),

 joinColumns = {@JoinColumn(name = "TEACHER_ID",referencedColumnName="ID")},
 inverseJoinColumns = {@JoinColumn(name = "STUDENT_ID",referencedColumnName="ID")})

 public Set<Student> getStudents()
 {
  return students;
 }
}

  EntityTest.java

package com.kuaff.ejb3.relationships;

import javax.ejb.Remote;
import java.util.List;

@Remote

public interface EntityTest
{
 public void createData();
 public List findByName(String name);
}

  EntityTestBean.java
 
package com.kuaff.ejb3.relationships;

import javax.ejb.EntityManager;
import javax.ejb.Inject;
import javax.ejb.Stateless;
import java.util.HashSet;
import java.util.Set;
import java.util.List;

@Stateless

public class EntityTestBean implements EntityTest
{
 private @Inject EntityManager manager;
 public void createData()
 {
  Teacher teacher1 = new Teacher();
  Teacher teacher2 = new Teacher();

  Set<Student> students1 = new HashSet<Student>();
  Set<Student> students2 = new HashSet<Student>();
  Student student1 = new Student();
  Student student2 = new Student();
  Student student3 = new Student();

  Dossier dossier1 = new Dossier();
  Dossier dossier2 = new Dossier();
  Dossier dossier3 = new Dossier();
  teacher1.setId(new Long(1));
  teacher1.setName("hushisheng");
  teacher1.setInfo("胡时胜教授,博士生导?);
  manager.create(teacher1);
  teacher2.setId(new Long(2));
  teacher2.setName("liyongchi");
  teacher2.setInfo("李永池教授,博士生导?);
  manager.create(teacher2);

  student1.setFirst("?);
  student1.setLast("x");
  dossier1.setResume("q是晁岳攀的档?);
  student1.setDossier(dossier1);
  students1.add(student1);

  student2.setFirst("?);
  student2.setLast("志伟");
  dossier2.setResume("q是赵志伟的档案");
  student2.setDossier(dossier2);
  students1.add(student2);

  student3.setFirst("?);
  student3.setLast("?);

  dossier3.setResume("q是田明的档?);
  student3.setDossier(dossier3);
  students2.add(student3);

  teacher1.setStudents(students1);
  teacher2.setStudents(students2);

 }

 public List findByName(String name)
 {
  return manager.createQuery("from Teacher t where t.name = :name").setParameter("name", name).listResults();
 }

}

  在这个会话Bean中提供了创徏各个实体Bean的方法,q提供了查找老师的方法?br />
  Client.java

package com.kuaff.ejb3.secondary;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.List;

public class Client
{
 public static void main(String[] args) throws NamingException
 {
  InitialContext ctx = new InitialContext();
  StudentDAO dao = (StudentDAO) ctx.lookup(StudentDAO.class.getName());
  int id = dao.create("?,"x","8","smallnest@kuaff.com","?);
  dao.create("?,"立焕","6","zhuzhu@kuaff.com","?);
  List list = dao.findAll();
  for(Object o:list)
  {
   Student s = (Student)o;
   System.out.printf("%s%s的性别:%s%n",s.getName().getFirst(),s.getName().getLast(),s.getGender());
   dao.evict(s);
  }
 }
}

  q个客户端用来测试?br />
  误行{$JBOSS_HOME}/bin目录下的run.bat: run –c all,启动JBOSS?br />
  http://localhost:8080/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss%3Aservice%3DHypersonic%2Cdatabase%3DlocalDBQ然后调用startDatabaseManager()Ҏ(gu)Q打开HSQL理工具理数据库?br />
  在Eclipse的Ant视图中执行ejbjar target。或者在命o行下Q进入到此工E目录下Q执行ant ejbjar,编译打包发布此EJB?br />
  在Eclipse的Ant视图中执行run target。或者在命o行下Q进入到此工E目录下Q执行ant run,试q个EJB?/span>


liaojiyong 2006-07-04 09:27 发表评论
]]>
EJB 3.0开发指南之多表映射http://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56458.htmlliaojiyongliaojiyongTue, 04 Jul 2006 01:26:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56458.htmlhttp://www.aygfsteel.com/liaojiyong/comments/56458.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56458.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/56458.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/56458.html
  从表可以使用@SecondaryTable来注释:

@Target({TYPE}) @Retention(RUNTIME)

public @interface SecondaryTable {
 String name();
 String catalog() default "";
 String schema() default "";
 JoinColumn[] join() default {};
 UniqueConstraint[] uniqueConstraints() default {};
}

  q个注释可以指定表名、分cRschema、联合列、约束等。假如你使用多张表,你可以用下面的注释来声明多张表:

@SecondaryTable
@Target({TYPE}) @Retention(RUNTIME)

public @interface SecondaryTables {
 SecondaryTable[] value() default {};
}

  q个例子主要有以下几个文Ӟq个例子主要实现了管理学生的功能。Student是一个实体BeanQ这个Bean的name属性是一个类Q也是Namec,q个Namecd是一个依赖值对象。学生的性别映射到第二张表中。StudentDAOBean是一个无状态的会话BeanQ用来调用实体Bean。和前面的例子一P我们q是使用Client试?br />
  q个例子和上一个例子基本相同,只是Student.java和Client有所不同?br />
   Student.javaQ实体Bean?br />
   Name.javaQ实体Bean所依赖的类?br />
   StudentDAO.javaQ会话Bean的业务接?br />
   StudentDAOBean.javaQ会话Bean的实现类

   Client.javaQ测试EJB的客LcR?br />
   jndi.propertiesQjndi属性文Ӟ提供讉Kjdni的基本配|属性?br />
   Build.xmlQant 配置文gQ用以编译、发布、测试、清除EJB?br />
  下面针对每个文g的内容做一个介l?br />
Student.java

package com.kuaff.ejb3.secondary;

import javax.ejb.Dependent;
import javax.ejb.DependentAttribute;
import javax.ejb.Column;
import javax.ejb.Entity;
import javax.ejb.GeneratorType;
import javax.ejb.Id;
import javax.ejb.Table;
import javax.ejb.SecondaryTables;
import javax.ejb.SecondaryTable;
import javax.ejb.JoinColumn;

@Entity
@Table(name = "STUDENT")
@SecondaryTables({
@SecondaryTable(name = "GENDER", join = {@JoinColumn(name = "GENDER_ID")})
})

public class Student implements java.io.Serializable
{
 private int id;
 private Name name;
 private String grade;
 private String email;
 private String gender;

 @Id(generate = GeneratorType.AUTO)

 public int getId()
 {
  return id;
 }

 public void setId(int id)
 {
  this.id = id;
 }

 public void setName(Name name)
 {
  this.name = name;
 }

@Dependent({ @DependentAttribute(name = "first", column ={ @Column(name = "FIRST") }),

@DependentAttribute(name = "last", column ={ @Column(name = "LAST") }) })

public Name getName()
{
 return name;
}

public void setGrade(String grade)
{
 this.grade = grade;
}

@Column(name = "GRADE")

public String getGrade()
{
 return grade;
}

public void setEmail(String email)
{
 this.email = email;
}

@Column(name = "EMAIL")

public String getEmail()
{
 return email;
}

public void setGender(String gender)
{
 this.gender = gender;
}

@Column(name = "gender", secondaryTable = "GENDER")

public String getGender()
{
 return gender;
}

}

  Student.java实现了Student实体BeanQ它提供学生的基本情c在cM声明上加上了W二张表的注释:

@SecondaryTables({
@SecondaryTable(name = "GENDER", join = {@JoinColumn(name = "GENDER_ID")})
})

  在gender属性上加上了映第二张的注释:

@Column(name = "gender", secondaryTable = "GENDER")

Client.java

package com.kuaff.ejb3.secondary;

import javax.naming.InitialContext;

import javax.naming.NamingException;

import java.util.List;


public class Client
{
public static void main(String[] args) throws NamingException

{

InitialContext ctx = new InitialContext();

StudentDAO dao = (StudentDAO) ctx.lookup(StudentDAO.class.getName());

int id = dao.create("?,"x","8","smallnest@kuaff.com","?);

dao.create("?,"立焕","6","zhuzhu@kuaff.com","?);



List list = dao.findAll();

for(Object o:list)

{

Student s = (Student)o;

System.out.printf("%s%s的性别:%s%n",s.getName().getFirst(),s.getName().getLast(),s.getGender());

dao.evict(s);

}

  q个客户端增加学生的分数Qƈ且测试显C个学生的email?br />
  误行{$JBOSS_HOME}/bin目录下的run.bat: run –c all,启动JBOSS?br />
http://localhost:8080/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss%3Aservice%3DHypersonic%2Cdatabase%3DlocalDBQ?br />
  然后调用startDatabaseManager()Ҏ(gu)Q打开HSQL理工具理数据库?br />
  在Eclipse的Ant视图中执行ejbjar target。或者在命o行下Q进入到此工E目录下Q执行ant ejbjar,编译打包发布此EJB?br />
  在Eclipse的Ant视图中执行run target。或者在命o行下Q进入到此工E目录下Q执行ant run,试q个EJB?br />

liaojiyong 2006-07-04 09:26 发表评论
]]>
EJB 3.0开发指南之使用实体Beanhttp://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56456.htmlliaojiyongliaojiyongTue, 04 Jul 2006 01:25:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56456.htmlhttp://www.aygfsteel.com/liaojiyong/comments/56456.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56456.html#Feedback2http://www.aygfsteel.com/liaojiyong/comments/commentRss/56456.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/56456.htmlColumn的声明如下:

@Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)
public @interface Column {
 String name() default "";
 boolean primaryKey() default false;
 boolean unique() default false;
 boolean nullable() default true;
 boolean insertable() default true;
 boolean updatable() default true;
 String columnDefinition() default "";
 String secondaryTable() default "";
 int length() default 255;
 int precision() default 0;
 int scale() default 0;
 boolean specified() default true; // For internal use only
}

  EntityManager 是用来处理实体Bean的辅助类。它可以用来产生/删除持久化的实体BeanQ通过主键查找实体beanQ通过查询语言来查询实体Bean?br />
  下面是EntityManager接口的声明:

package javax.ejb;

import java.sql.Connection;
/**
* 用来和持久化上下文交互的接口
*/

public interface EntityManager {

 /**
 * 使实体bean受持久化理
 * @param entity
 */

 public void create(Object entity);
 
 /**
 * 给定的实体Bean的状态和持久化上下文l合。类似数据库的更新操作?br /> * @param entity
 * @return 被结合的实体实例
 */

 public <T> T merge(T entity);

 /**
 * 删除实例
 * @param entity
 */

 public void remove(Object entity);
 /**
 * Ҏ(gu)主键查找.
 * @param entityName
 * @param primaryKey
 * @return 查询实例
 */

 public Object find(String entityName, Object primaryKey);
 /**
 * Ҏ(gu)主键查找
 * @param primaryKey
 * @return 查询实例
 */

 public <T> T find(Class<T> entityClass, Object primaryKey);
 /**
 * 持久化上下文与底层数据库的同?br /> */

 public void flush();
 /**
 * 执行一个EJBQL查询
 * @param ejbqlString EJBQL查询语句
 * @return the new query instance
 */

 public Query createQuery(String ejbqlString);
 /**
 * 执行命名的查?br /> * @param name 预定义的查询名称
 * @return 查询实例
 */

 public Query createNamedQuery(String name);
 /**
 * 执行一个本地SQL查询语句
 * @param sqlString 本地查询语句
 * @return q回查询实例
 */

 public Query createNativeQuery(String sqlString);
 /**
 * 更新到数据库?br /> * @param entity
 */

 public void refresh(Object entity);
 /**
 * 持久化上下文中删除实?br /> * @param entity
 */

 public void evict(Object entity);
 /**
 * 查当前上下文中是否包含此实体
 * context.
 * @param entity
 * @return
 */

 public boolean contains(Object entity);
}

  @JoinColumns

  用来指示W合主键Q在后面的章节中介绍?br />
   q个例子主要有以下几个文Ӟq个例子主要实现了管理学生分数的功能。Student是一个实体BeanQ管理学生的基本信息Q姓名和各课分数Q,其中学生的分数又是一个实体Bean。TacherBean是一个无状态的会话BeanQ用来调用实体Bean。和前面的例子一P我们q是使用Client试?br />
  ·Student.javaQ实体Bean?br />
  ·Score.javaQ实体Bean?br />
  ·Teacher.javaQ会话Bean的业务接?br />
  ·TeacherBean.javaQ会话Bean的实现类

  ·Client.javaQ测试EJB的客LcR?br />
  ·jndi.propertiesQjndi属性文Ӟ提供讉Kjdni的基本配|属性?br />
  ·Build.xmlQant 配置文gQ用以编译、发布、测试、清除EJB?br />
  下面针对每个文g的内容做一个介l?br />
  Student.java

package com.kuaff.ejb3.entity;

import javax.ejb.CascadeType;
import javax.ejb.Entity;
import javax.ejb.FetchType;
import javax.ejb.GeneratorType;
import javax.ejb.Id;
import javax.ejb.JoinColumn;
import javax.ejb.OneToMany;
import javax.ejb.Table;
import java.util.ArrayList;
import java.util.Collection;
import java.io.Serializable;

@Entity
@Table(name = "STUDENT")

public class Student implements Serializable
{
 //主键
 private int id;
 //学生?br /> private String name;
 //学生的分?br /> private Collection<Score> scores;
 //主键自动产生

 @Id(generate = GeneratorType.AUTO)

 public int getId()
 {
  return id;
 }

 public void setId(int id)
 {
  this.id = id;
 }

 public String getName()
 {
  return name;
 }

 public void setName(String name)
 {
  this.name = name;
 }

 public void addScores(String name,int number)
 {
  if (scores == null)
  {
   scores = new ArrayList<Score>();
  }
  Score score = new Score();
  score.setName(name);
  score.setNumber(number);
  score.setStudent(this);
  scores.add(score);
 }

 @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
 @JoinColumn(name = "student_id")

 public Collection<Score> getScores()
 {
  return scores;
 }

 public void setScores(Collection<Score> scores)
 {
  this.scores = scores;
 }
}

  Student.java实现了Student实体BeanQ它提供学生的基本情况以及学生的得分情况Q得分是另外一个实体Bean。Student实体Bean和Score实体Bean是一对多的关p,站在Score的角度看是多对一的关pR?br />
  实体Bean需要用@Entity做注释,另外它指定这个实体Bean与表STUDENT对应Q通过注释@Table(name = "STUDENT")Q,你可以在JBOSS的数据库中看到这个表?br />
  Score.java

package com.kuaff.ejb3.entity;

import java.io.Serializable;
import javax.ejb.Entity;
import javax.ejb.GeneratorType;
import javax.ejb.Id;
import javax.ejb.JoinColumn;
import javax.ejb.ManyToOne;
import javax.ejb.Table;

@Entity
@Table(name = "Score")

public class Score implements Serializable
{
 private int id;
 private String name;
 private int number;
 private Student student;

 //主键自动产生

 @Id(generate = GeneratorType.AUTO)

 public int getId()
 {
  return id;
 }

 public void setId(int id)
 {
  this.id = id;
 }

 public String getName()
 {
  return name;
 }

 public void setName(String name)
 {
  this.name = name;
 }

 public int getNumber()
 {
  return number;
 }

 public void setNumber(int number)
 {
  this.number = number;
 }

 @ManyToOne
 @JoinColumn(name = "student_id")

 public Student getStudent()
 {
  return student;
 }

 public void setStudent(Student student)
 {
  this.student = student;
 }

}

  q个实体Bean存放学生的分数?br />
  Teacher.java

package com.kuaff.ejb3.entity;



import javax.ejb.Remote;

import javax.ejb.Remove;

import java.util.Map;



@Remote

public interface Teacher

{

public void addScore(String studentName,Map<String,Integer> map);



public Student getStudent();



@Remove

public void leave();

}

  q个会话Bean接口提供增加分数和得到用LҎ(gu)?br />
  TeacherBean.java

package com.kuaff.ejb3.entity;

import javax.ejb.EntityManager;
import javax.ejb.Inject;
import javax.ejb.Remove;
import javax.ejb.Stateful;
import java.util.Map;
import java.util.Set;

@Stateful

public class TeacherBean implements Teacher
{
 @Inject
 private EntityManager manager;
 private Student student;

 public Student getStudent()
 {
  return student;
 }

 public void addScore(String studentName, Map<String,Integer> map)
 {
  if (student == null)
  {
   student = new Student();
  }
  student.setName(studentName);
  Set<String> set = map.keySet();
  for (String sname:set)
  {
   student.addScores(sname,map.get(sname).intValue());
  }
 }

 @Remove

 public void leave()
 {
  manager.create(student);
 }



}

  q个是会话Bean的实现类?br />
  Client.java

package com.kuaff.ejb3.entity;

import java.util.Map;
import java.util.HashMap;
import java.util.Collection;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class Client
{
 public static void main(String[] args) throws NamingException
 {
  InitialContext ctx = new InitialContext();
  Teacher teacher = (Teacher) ctx.lookup(Teacher.class.getName());
  Map<String,Integer> map = new HashMap<String,Integer>();
  map.put("语文",new Integer(98));
  map.put("化学",new Integer(149));
  map.put("物理",new Integer(143));
  teacher.addScore("smallnest",map);
  Student student = teacher.getStudent();
  String name = student.getName();
  System.out.printf("昄%s的分?%n",name);
  Collection<Score> c = student.getScores();

  for (Score score:c)
  {
   System.out.printf("%s:%s%n",score.getName(),score.getNumber()+"");
  }
 }
}

  q个客户端增加学生的分数Qƈ且测试显C个学生的相关信息?br />
  误行{$JBOSS_HOME}/bin目录下的run.bat: run –c all,启动JBOSS?br />
http://localhost:8080/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss%3Aservice%3DHypersonic%2Cdatabase%3DlocalDBQ然后调用startDatabaseManager()Ҏ(gu)Q打开HSQL理工具理数据库?br />
  在Eclipse的Ant视图中执行ejbjar target。或者在命o行下Q进入到此工E目录下Q执行ant ejbjar,编译打包发布此EJB?br />
  在Eclipse的Ant视图中执行run target。或者在命o行下Q进入到此工E目录下Q执行ant run,试q个EJB?br />

liaojiyong 2006-07-04 09:25 发表评论
]]>
EJB 3.0 开发指南之依赖值对?/title><link>http://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56457.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Tue, 04 Jul 2006 01:25:00 GMT</pubDate><guid>http://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56457.html</guid><wfw:comment>http://www.aygfsteel.com/liaojiyong/comments/56457.html</wfw:comment><comments>http://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56457.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/liaojiyong/comments/commentRss/56457.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/liaojiyong/services/trackbacks/56457.html</trackback:ping><description><![CDATA[在上面的章节我们提到Q实体bean的属性可以是java基本对象、Date{,事实上,实体Bean的属性也可以是其他的java对象。这些Java对象不能直接从持久化上下文中dQ它依赖于主实体bean。不象关联实体BeanQ在EJB3.0中不支持依赖值对象的集合?<br /><br />  依赖值对象不支持l承Q这在EJB3.1中在讨论?br /><br />  依赖c需要用◎DependentObject来注释:<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>@Target({TYPE}) @Retention(RUNTIME)<br />public @interface DependentObject {<br /> AccessType access() default PROPERTY;<br />}</td></tr></tbody></table><br />  q个注释可以指定容器讉Kq个cȝҎ(gu)Q是通过属性还是直接通过字段来访问?br /><br />  在实体Bean的一个属性需要用依赖值对象,那么q个属性的getҎ(gu)需要用@Dependent注释Q?br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>@Target({METHOD, FIELD}) @Retention(RUNTIME)<br />public @interface Dependent {<br /> DependentAttribute[] value() default {};<br />}</td></tr></tbody></table><br />  q个注释可以指定依赖的属性DependentAttributeQ?br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>@Target({}) @Retention(RUNTIME)<br /><br />public @interface DependentAttribute {<br /> String name();<br /> Column[] column() default {};<br />}</td></tr></tbody></table><br />  可以指定属性名U和映射的列名。这里,一个主实体Bean的属性可以映到数据表中的多列?br /><br />  如果你还不太明白Q看下面的例子?br /><br />  q个例子主要有以下几个文Ӟq个例子主要实现了管理学生的功能。Student是一个实体BeanQ这个Bean的name属性是一个类Q也是Namec,q个Namecd是一个依赖值对象。StudentDAOBean是一个无状态的会话BeanQ用来调用实体Bean。和前面的例子一P我们q是使用Client试?br /><br />  ·Student.javaQ实体Bean?br /><br />  ·Name.javaQ实体Bean所依赖的类?br /><br />  ·StudentDAO.javaQ会话Bean的业务接?br /><br />  ·StudentDAOBean.javaQ会话Bean的实现类<br /><br />  ·Client.javaQ测试EJB的客LcR?br /><br />  ·jndi.propertiesQjndi属性文Ӟ提供讉Kjdni的基本配|属性?br /><br />  ·Build.xmlQant 配置文gQ用以编译、发布、测试、清除EJB?br /><br />  下面针对每个文g的内容做一个介l?br /><br />  Student.java<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>package com.kuaff.ejb3.dependent;<br /><br />import javax.ejb.Dependent;<br />import javax.ejb.DependentAttribute;<br />import javax.ejb.Column;<br />import javax.ejb.Entity;<br />import javax.ejb.GeneratorType;<br />import javax.ejb.Id;<br />import javax.ejb.Table;<br /><br />@Entity @Table(name = "STUDENT") public class Student implements java.io.Serializable<br />{<br /> private int id;<br /> private Name name;<br /> private String grade;<br /> private String email;<br /><br /> @Id(generate = GeneratorType.AUTO) <br /><br /> public int getId()<br /> {<br />  return id;<br /> }<br /><br /> public void setId(int id)<br /> {<br />  this.id = id;<br /> }<br /><br /> public void setName(Name name)<br /> {<br />  this.name = name;<br /> }<br /><br />@Dependent(<br />{ @DependentAttribute(name = "first", column ={ @Column(name = "FIRST") }), <br /> @DependentAttribute(name = "last", column ={ @Column(name = "LAST") }) }) <br /> public Name getName()<br /> {<br />  return name;<br /> }<br /><br /> public void setGrade(String grade)<br /> {<br />  this.grade = grade;<br /> }<br /><br /> @Column(name = "GRADE") <br /><br /> public String getGrade()<br /> {<br />  return grade;<br /> }<br /><br /> public void setEmail(String email)<br /> {<br />  this.email = email;<br /> }<br /><br /> @Column(name = "EMAIL") <br /><br /> public String getEmail()<br /> {<br />  return email;<br /> }<br />}<br /></td></tr></tbody></table><br />  Student.java实现了Student实体BeanQ它提供学生的基本情c学生的姓名是Namec,通过@Dependent(<br /><br />{ @DependentAttribute(name = "first", column ={ @Column(name = "FIRST") }), <br /><br />@DependentAttribute(name = "last", column ={ @Column(name = "LAST") }) }) <br /><br />来声明,q指定这个依赖类的两个属性first和lastQƈ映射到数据表的FIRST和LAST列上?br /><br />  Name.java<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>package com.kuaff.ejb3.dependent;<br /><br />import java.io.Serializable;<br />import javax.ejb.AccessType;<br />import javax.ejb.DependentObject;<br /><br />@DependentObject(access = AccessType.PROPERTY)<br /><br />public class Name implements java.io.Serializable<br />{<br /> private String first;<br /> private String last;<br /><br /> public Name()<br /> {}<br /><br /> public Name(String first, String last)<br /> {<br />  this.first = first;<br />  this.last = last;<br /> }<br /><br /> public String getFirst()<br /> {<br />  return first;<br /> }<br /><br /> public void setFirst(String first)<br /> {<br />  this.first = first;<br /> }<br /><br /> public String getLast()<br /> {<br />  return last;<br /> }<br /><br /> public void setLast(String last)<br /> {<br />  this.last = last;<br /> }<br />}</td></tr></tbody></table><br />  q个值对象也很简单,和一般的javaBean差不多,但有两个地方需要注意:<br /><br />  1Q?q个cdCjava.io.Serializable接口<br /><br />  2Q?q个cM用@DependentObject做了注释<br /><br />  StudentDAO.java<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>package com.kuaff.ejb3.dependent;<br /><br />import javax.ejb.Remote;<br />import java.util.List;<br /><br />@Remote<br /><br />public interface StudentDAO<br />{<br /> int create(String first, String last, String grade, String email);<br /> Student find(int id);<br /> List findByFirstName(String name);<br /> List findByLastName(String name);<br /> List findByEmail(String email);<br /><br /> void merge(Student s);<br />}</td></tr></tbody></table><br />  q个会话Bean接口提供查找用户的方法?br /><br />  StudentDAOBean.java<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>package com.kuaff.ejb3.dependent;<br /><br />import java.util.List;<br />import javax.ejb.EntityManager;<br />import javax.ejb.Inject;<br />import javax.ejb.Stateless;<br /><br />@Stateless<br /><br />public class StudentDAOBean implements StudentDAO<br />{<br /> @Inject<br /> private EntityManager manager;<br /><br /> public int create(String first, String last, String grade, String email)<br /> {<br />  Student student = new Student();<br />  student.setName(new Name(first,last));<br />  student.setGrade(grade);<br />  student.setEmail(email);<br />  manager.create(student);<br />  return student.getId();<br /> }<br /><br /> public Student find(int id)<br /> {<br />  return manager.find(Student.class, id);<br /> }<br /><br /> public List findByFirstName(String name)<br /> {<br />  return manager.createQuery("from Student s where s.name.last = :name").setParameter("name", name).listResults();<br /> }<br /> public List findByLastName(String name)<br /> {<br />  return manager.createQuery("from Student s where s.name.first = :name").setParameter("name", name).listResults();<br /> }<br /><br /> public List findByEmail(String email)<br /> {<br />   return manager.createQuery("from Student s where s.email = :email").setParameter("email", email).listResults();<br /> }<br /><br /> public void merge(Student s)<br /> {<br />  manager.merge(s);<br /> }<br /><br />}</td></tr></tbody></table><br />  q个是会话Bean的实现类。可以看到根据值对象的属性查找主实体Bean?br /><br />  Client.java<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>package com.kuaff.ejb3.dependent;<br /><br />import javax.naming.InitialContext;<br />import javax.naming.NamingException;<br />import java.util.List;<br /><br />public class Client<br />{<br /> public static void main(String[] args) throws NamingException<br /> {<br />  InitialContext ctx = new InitialContext();<br />  StudentDAO dao = (StudentDAO) ctx.lookup(StudentDAO.class.getName());<br />  int id = dao.create("?,"x","8","smallnest@kuaff.com");<br />  dao.create("?,"立焕","6","zhuzhu@kuaff.com");<br />  List list = dao.findByEmail("zhuzhu@kuaff.com");<br />  for(Object o:list)<br />  {<br />   Student s = (Student)o;<br />   System.out.printf("%s %s的email:%s%n",s.getName().getFirst(),s.getName().getLast(),s.getEmail());<br />  }<br /> }<br />}<br /></td></tr></tbody></table><br />  q个客户端增加学生的分数Qƈ且测试显C个学生的email?br /><br />  误行{$JBOSS_HOME}/bin目录下的run.bat: run –c all,启动JBOSS?br /><br />http://localhost:8080/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss%3Aservice%3DHypersonic%2Cdatabase%3DlocalDBQ然后调用startDatabaseManager()Ҏ(gu)Q打开HSQL理工具理数据库?br /><br />  在Eclipse的Ant视图中执行ejbjar target。或者在命o行下Q进入到此工E目录下Q执行ant ejbjar,编译打包发布此EJB?br /><br />  在Eclipse的Ant视图中执行run target。或者在命o行下Q进入到此工E目录下Q执行ant run,试q个EJB?br /><img src ="http://www.aygfsteel.com/liaojiyong/aggbug/56457.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/liaojiyong/" target="_blank">liaojiyong</a> 2006-07-04 09:25 <a href="http://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56457.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB 3.0 开发指南之定时服务http://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56455.htmlliaojiyongliaojiyongTue, 04 Jul 2006 01:24:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56455.htmlhttp://www.aygfsteel.com/liaojiyong/comments/56455.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56455.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/56455.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/56455.html
  q个例子主要?个文Ӟq个例子的Bean是一个无状态会话BeanQ?br />
  NewsTimer.javaQ业务接口?br />
  NewsTimer.javaQ业务实现类。将来我们开发的EJB也都是这样命名(在接口名上加上BeanQ?br />
  Client.javaQ测试EJB的客LcR?br />
  jndi.propertiesQjndi属性文Ӟ提供讉Kjdni的基本配|属性?br />
  Build.xmlQant 配置文gQ用以编译、发布、测试、清除EJB?br />
  下面针对每个文g的内容做一个介l?br />
NewsTimer.java

package com.kuaff.ejb3.schedule;
import javax.ejb.Remote;
@Remote

public interface NewsTimer
{
 public void fiveNews();
}

  q个接口定义了fiveNewsҎ(gu)Q如果这个方法被调用Q?分钟后将往控制C输出一条新闅R?br />
  你不必配|它的JNDI名称Q也不必写它的配|文件。在JBOSS实现的EJB3.0中,你不必写M的EJB部v文g和jboss部v文g。JBOSS默认使用接口的全UC为它的JNDI名。在上面的例子中Q它的全U可以通过NewsTimerclass.forName()得到?br />
NewsTimerBean.java

package com.kuaff.ejb3.schedule;
import java.util.Date;
import javax.ejb.Inject;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.ejb.Timer;

@Stateless

public class NewsTimerBean implements NewsTimer
{
 private @Inject SessionContext ctx;
 public void fiveNews()
 {
  ctx.getTimerService().createTimer(new Date(new Date().getTime() + 300000), "子虚乌有?sh)视?分钟新闻栏目:现在q?分钟Q又到即时新闻节目的旉了?);
 }

 public void ejbTimeout(Timer timer)
 {
  System.out.printf("旉?%n%s%n" , timer.getInfo());
  timer.cancel();
 }
}

Client.java

package com.kuaff.ejb3.schedule;

import javax.naming.InitialContext;
import javax.naming.NamingException;

public class Client
{
 public static void main(String[] args) throws NamingException
 {
  InitialContext ctx = new InitialContext();
  NewsTimer timer = (NewsTimer) ctx.lookup(NewsTimer.class.getName());
  timer.fiveNews();
 }
}


  q个cȝ来测试我们发布的计数器EJB。首先通过

ctx = new InitialContext();

  得到上下文,然后通过lookup查找NewsTimerQ然后启动计时。?br />
  误行{$JBOSS_HOME}/bin目录下的run.bat: run –c all,启动JBOSS?br />
  在Eclipse的Ant视图中执行ejbjar target。或者在命o行下Q进入到此工E目录下Q执行ant ejbjar,编译打包发布此EJB?br />
  在Eclipse的Ant视图中执行run target。或者在命o行下Q进入到此工E目录下Q执行ant run,试q个EJB?br />

liaojiyong 2006-07-04 09:24 发表评论
]]>
EJB 3.0开发指南之依赖注入http://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56453.htmlliaojiyongliaojiyongTue, 04 Jul 2006 01:23:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56453.htmlhttp://www.aygfsteel.com/liaojiyong/comments/56453.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56453.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/56453.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/56453.html
  在EJB3.0中,可以通过在字D和讄Ҏ(gu)上加上注释注入依赖,我想在很快会有新的项目,或者在原来的项目的基础上,一些IOC容器会采用注释的方式注入依赖QJDK5.0加入的注释的是一个很强大的功能,相对而言Q在.net中的属性却没有发挥那么大的价倹{这是开源的威力Q成千上万的在开源javaE序员不断涌现出新的x新的功能?br />
  看下面的例子Q我们知?JBOSS中已l默认配|了一个数据源Q它的JNDI名称?java:/DefaultDS"。下面这个例子声明了一个数据源Q通过注释Q就可以JBOSS的这个默认的数据源赋值给它?br />
@Resource(jndiName="java:/DefaultDS")
public DataSource customerDB;
Resource注释的声?br />@Target({TYPE, METHOD, FIELD, PARAMETER}) @Retention(RUNTIME)

public @interface Resource {

String name() default "";

String resourceType() default "";

AuthenticationType authenticationType() default CONTAINER;

boolean shareable() default true;

String jndiName() default "";

}


public enum Authentication Type {

CONTAINER,

APPLICATION

}

@Target(TYPE) @Retention(RUNTIME)

public @interface Resources {

Resource[] value();

}

  Resource的name指向一个在环境属性中命名的资源,AuthenticationType用来指定是容器还是EJBlg来进行n份验证,sharebale指定是否׃n,jndiName用来指定JDNI中的名称。resourceType()用来指定资源的类型?br />
  如果name和resourceType都指向被注释的程序成员,AuthenticationType和resourceType都是~省的,则可以用Inject注释Q?br />
@Inject(jndiName="java:/DefaultDS")

public DataSource customerDB;

  对于单例的成员,你可以更化:

@Inject javax.ejb.SessionContext ctx;

@Inject javax.ejb.TimerService timer;

@Inject javax.ejb.UserTransaction ut;

@Inject javax.ejb.EntityManager manager;

  Resources注释可以注入多个资源?br />
  在Eclipse中导入本文提供的例子DI?br />
  q个例子从数据库中读取JMS_USER表,q显C中的内容。这个例子用依赖注入的方式得到JBOSS默认的数据源?br />
  q个例子主要?个文Ӟ

   JmsUsers.javaQ业务接口?br />
   JmsUsersBean.javaQ业务实现类。将来我们开发的EJB也都是这样命名(在接口名上加上BeanQ?br />
   Client.javaQ测试EJB的客LcR?br />
   jndi.propertiesQjndi属性文Ӟ提供讉Kjdni的基本配|属性?br />
   Build.xmlQant 配置文gQ用以编译、发布、测试、清除EJB?br />
  下面针对每个文g的内容做一个介l?br />
JmsUsers.java

package com.kuaff.ejb3.di;
import java.util.List;
import javax.ejb.Remote;
import javax.sql.*;

@Remote
public interface JmsUsers
{
 public List<String> getUsers();
}

  q个接口很简单,定义了一个得到全部用LҎ(gu)QJBOSS默认使用接口的全UC为它的JNDI名。在上面的例子中Q它的全U可以通过JmsUsers.class。getNameQ)得到?br />
CounterBean.java

package com.kuaff.ejb3.di;
import java.util.List;
import java.util.ArrayList;
import javax.ejb.Stateless;
import javax.ejb.Resource;
import javax.sql.*;
import java.sql.*;


@Stateless
public class JmsUsersBean implements JmsUsers
{
 @Resource(jndiName="java:/DefaultDS",resourceType="javax.sql.DataSource")
 public DataSource customerDB;
 public List<String> getUsers()
 {
  List<String> list = new ArrayList<String>();
  try
  {
   Connection conn = customerDB.getConnection();
   Statement st = conn.createStatement();
   ResultSet rs = st.executeQuery("select * from jms_users");
   while(rs.next())
   {
    list.add(rs.getString("userid"));
   }
  }
  catch(SQLException e)
  {}
  return list;
 }
}

  q个是业务逻辑的具体实现。一旦这个EJB被容器生,则容器将JBOSS的数据源注入到customerDB变量上,所以不要以为customerDB没有被初始化Q这些工作是容器做的?br />
Client.java

package com.kuaff.ejb3.di;
import java.util.List;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class Client
{
 public static void main(String[] args)
 {
  InitialContext ctx;
  try
  {
   ctx = new InitialContext();
   JmsUsers users = (JmsUsers) ctx.lookup(JmsUsers.class.getName());
   List<String> jmsUsers = users.getUsers();
   for(String user:jmsUsers)
   {
    System.out.printf("用户?%s%n",user);
   }
  }
  catch (NamingException e)
  {
   e.printStackTrace();
  }
 }
}

  q个cȝ来测试我们发布的EJBlg。显CZJMS_USERS表中d的数据?br />
  误行{$JBOSS_HOME}/bin目录下的run.bat: run ?call,启动JBOSS?br />
  在Eclipse的Ant视图中执行ejbjar target。或者在命o行下Q进入到此工E目录下Q执行ant ejbjar,编译打包发布此EJB

  在Eclipse的Ant视图中执行run target。或者在命o行下Q进入到此工E目录下Q执行ant run,试q个EJB?br />

liaojiyong 2006-07-04 09:23 发表评论
]]>
EJB 3.0开发指南之消息驱动Beanhttp://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56454.htmlliaojiyongliaojiyongTue, 04 Jul 2006 01:23:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56454.htmlhttp://www.aygfsteel.com/liaojiyong/comments/56454.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2006/07/04/56454.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/56454.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/56454.html
  实现cdM用MessageDriven注释。可以实C可以不实现setMessageDrivenContext和ejbRemoveҎ(gu)?br />
  在JBOSS中,通过ConnectionConfig指定消息的队列的JNDI名称?br />
@ConnectionConfig(destinationType = javax.jms.Queue.class, destinationJndiName = "queue/kuaffejb3/sample", durable = true, subscriptionId = "kuaffMessage")

  在Eclipse中导入本文提供的例子Messager?br />
  q个例子从客L发送一个TextMessageQ这个Beanlg接收到这个消息后Q将把这个消息输出到控制C?br />
  q个例子主要?个文Ӟ

   Messager.javaQ业务组件?br />  
   Client.javaQ测试EJB的客LcR?br /> 
   jndi.propertiesQjndi属性文Ӟ提供讉Kjdni的基本配|属性?br />
   Build.xmlQant 配置文gQ用以编译、发布、测试、清除EJB?br />
   queue-example-service.xmlQ消息服务,用来试消息?br />
  下面针对每个文g的内容做一个介l?br />
Messager.java

package com.kuaff.ejb3.messager;

import org.jboss.ejb3.mdb.ConnectionConfig;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.TextMessage;
import javax.jms.MessageListener;

@MessageDriven
@ConnectionConfig(destinationType = javax.jms.Queue.class, destinationJndiName = "queue/kuaffejb3/sample", durable = true, subscriptionId = "kuaffMessage")

public class Messager implements MessageListener
{
 public void onMessage(Message recvMsg)
 {
  System.out.println("接收到的消息:");
  try
  {
   TextMessage message = (TextMessage)recvMsg;
   System.out.println(message.getText());
  }
  catch (JMSException e)
  {
   e.printStackTrace();
  }
 }
}

  q个消息Bean很简单,接收到消息后不做什么处理,是消息内容输出到控制CQ?br />
Client.java

package com.kuaff.ejb3.messager;

import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.TextMessage;
import javax.naming.InitialContext;

public class Client
{
 public static void main(String[] args) throws Exception
 {
  QueueConnection cnn = null;
  QueueSender sender = null;
  QueueSession session = null;
  InitialContext ctx = new InitialContext();
  Queue queue = (Queue) ctx.lookup("queue/kuaffejb3/sample");
  QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup("ConnectionFactory");
  cnn = factory.createQueueConnection();
  session = cnn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
  TextMessage msg = session.createTextMessage("江湖快报:玉树临风风流倜傥的公子小巢又出现了?);
  sender = session.createSender(queue);
  sender.send(msg);
  System.out.println("消息已经发出");
 }
}

  q个客户端将发送一个文本消息到队列中?br />
queue-example-service.xml
Q?xml version="1.0" encoding="UTF-8"?Q?br />QserverQ?br />Qmbean code="org.jboss.mq.server.jmx.Queue" name="jboss.mq.destination:service=Queue,name=kuaffMessage"Q?br /> Qattribute name="JNDIName"Qqueue/kuaffejb3/sampleQ?attributeQ?br /> Qdepends optional-attribute-name="DestinationManager"Qjboss.mq:service=DestinationManagerQ?dependsQ?br />Q?mbeanQ?br />Q?serverQ?/td>

  配置q个E序所需的消息服务?br />
  误行{$JBOSS_HOME}/bin目录下的run.bat: run ?call,启动JBOSS?br />
  在Eclipse的Ant视图中执行ejbjar target。或者在命o行下Q进入到此工E目录下Q执行ant ejbjar,编译打包发布此EJB?br />
  在Eclipse的Ant视图中执行run target。或者在命o行下Q进入到此工E目录下Q执行ant run,试q个EJB?




liaojiyong 2006-07-04 09:23 发表评论
]]>
EJB3.0开发指南之有状态会话Bean(?http://www.aygfsteel.com/liaojiyong/archive/2006/07/03/56244.htmlliaojiyongliaojiyongMon, 03 Jul 2006 01:43:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2006/07/03/56244.htmlhttp://www.aygfsteel.com/liaojiyong/comments/56244.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2006/07/03/56244.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/56244.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/56244.html
  在目前jboss的实CQ必要有一个独立的业务接口?br />
  q个接口不必实现EJBObject或者EJBLocalObject?br />
  一个有状态会话Bean 必须使用Statelfull注释Q以表明它是一个有状态的会话Bean。EJB容器根据这个注释来判定它的cd。或者实现javax.ejb.SessionBean接口?br />
  一个有状态的会话Bean可以实现setSessionContextҎ(gu)Q也可以不实现?br />
  在EJB2.0中调用EJBObject.removeҎ(gu)以达C容器中删除有状态会话Bean的功能。在EJB3.0中只需在一些方法加上Remove注释。一旦这些被标记的方法被调用后,此EJB从容器中删除?br />
  一个有状态的会话Bean可以通过依赖注入获取容器的资源和环境属性?br />
  在Eclipse中导入本文提供的例子Stateful?br />
  q个例子和无状态会话Bean的例子类|下面只列Z不同的代码?br />
  q个例子主要?个文Ӟ

   Counter.javaQ业务接口?br />
   CounterBean.javaQ业务实现类。将来我们开发的EJB也都是这样命名(在接口名上加上BeanQ?br />
   Client.javaQ测试EJB的客LcR?br />
   jndi.propertiesQjndi属性文Ӟ提供讉Kjdni的基本配|属性?br />
   Build.xmlQant 配置文gQ用以编译、发布、测试、清除EJB?br />
  下面针对每个文g的内容做一个介l?br />
Counter.java
…?br />import javax.ejb.Remove;
…?br />@Remote

public interface Counter
{
 …?br /> @Remove
 public void clean();
}


  q个接口很简单,和无状态会话Bean基本相同Q但新增加了一个CleanҎ(gu)Qƈ为此Ҏ(gu)加上Remove注释。一旦此Ҏ(gu)被执行完毕,此Bean被从容器中删除?br />
  JBOSS默认使用接口的全UC为它的JNDI名。在上面的例子中Q它的全U就是:com.kuaff.ejb3.stateful.CounterQ你也可以通过Counter.class得到?br />
CounterBean.java
…?br />import javax.ejb.Stateful;
…?br />@Stateful

public class CounterBean implements Counter
{
 //增加事务支持
 @Tx(TxType.REQUIRESNEW)
 public int getNumber()
 {
  return number;
 }

 @Remove

 public void clean()
 {
  System.out.println("我,被删除了!");
 }
}

  q个是计数器的实现类。注意这个类使用Stateful做了注释Q这是必ȝ。同Ӟq个例子也演CZ如何使用事务。事务的详细用法在后面的章节中介绍?br />
Client.java
package com.kuaff.ejb3.stateful;

import javax.ejb.EJBException;
import java.rmi.NoSuchObjectException;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class Client
{
 public static void main(String[] args)
 {
  InitialContext ctx;
  try
  {
   ctx = new InitialContext();
   Counter counter = (Counter) ctx.lookup(Counter.class.getName());
   counter.add(10);
   System.out.println("当前的number:" + counter.getNumber());
   counter.add(10);
   System.out.println("当前的number:" + counter.getNumber());
   Counter counter2 = (Counter) ctx.lookup(Counter.class.getName());
   counter2.add(10);
   System.out.println("当前的number:" + counter2.getNumber());
   //删除
   counter2.clean();
   //下面如果再用counter2,出?br />   try
   {
    System.out.println("当前的number:" + counter2.getNumber());
   }
   catch(EJBException ex)
   {
    if (ex.getCausedByException() instanceof NoSuchObjectException)
    {
     System.out.println("我都被删除啦Q还找我Q?);
    }
    else
    {
     throw ex;
    }
   }
  }
  catch (NamingException e)
  {
   e.printStackTrace();
  }
 }
}

  q个cȝ来测试我们发布的计数器EJB。首先通过

  ctx = new InitialContext();得到上下文,然后通过lookup查找计数器,然后l计数器?0Q显C当前的计数器信息。最后调用CleanҎ(gu)Q一旦这个方法执行完毕,此EJB从容器中删除,在用这个EJB会出现异常?br />
  误行{$JBOSS_HOME}/bin目录下的run.bat: run ?call,启动JBOSS?br />
  在Eclipse的Ant视图中执行ejbjar target。或者在命o行下Q进入到此工E目录下Q执行ant ejbjar,编译打包发布此EJB?br />
  在Eclipse的Ant视图中执行run target。或者在命o行下Q进入到此工E目录下Q执行ant run,试q个EJB?br />

 



liaojiyong 2006-07-03 09:43 发表评论
]]>
EJB设计模式概述Q{Q?/title><link>http://www.aygfsteel.com/liaojiyong/archive/2006/07/03/56241.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Mon, 03 Jul 2006 01:30:00 GMT</pubDate><guid>http://www.aygfsteel.com/liaojiyong/archive/2006/07/03/56241.html</guid><wfw:comment>http://www.aygfsteel.com/liaojiyong/comments/56241.html</wfw:comment><comments>http://www.aygfsteel.com/liaojiyong/archive/2006/07/03/56241.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/liaojiyong/comments/commentRss/56241.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/liaojiyong/services/trackbacks/56241.html</trackback:ping><description><![CDATA[ <br /> <br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td height="64"> <br /> <script language="JavaScript" src="http://203.81.25.103/cgi-bin/beadevcount.cgi?d_id=85" type="text/JavaScript"> </script> <br />本文关键字:<a >EJB</a>, <a >设计模式</a>, <a >pattern</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&keywords=session bean">session bean</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&keywords=entity bean">entity bean</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&keywords=message driven bean">message driven bean</a>, <a >command</a>, <a >dto</a>, <a >factory</a></td> <td> <table class="box_content" cellspacing="0" cellpadding="0" border="0"> <tbody> <tr> <td> <span id="wmqeeuq" class="h2b">文章工具</span> <br /> <img height="10" alt="推荐l朋? src="http://dev2dev.bea.com.cn/images/letter001.gif" width="19" align="absMiddle" /> <a href="javascript:sendmail()">推荐l朋?/a><br /><img height="18" alt="打印文章" src="http://dev2dev.bea.com.cn/images/print001.gif" width="19" align="absMiddle" /> <a href="javascript:window.print()">打印文章</a></td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <!-- 提取技术文?--> <div id="wmqeeuq" class="beas"> <img height="1" alt="" src="http://dev2dev.bea.com.cn/images/dot6B6B6B.gif" width="100%" /> </div>一Q?设计模式重要?br />采用QJQ技术的Q2QI目中,QJQ架构的设计好坏直接媄响系l的性能、可扩展性、可l护性、组件可重用性及开发效率。项目越复杂Q项目队伍越庞大则越能体现良好设计的重要性? <p>二. 常见EJB设计模式<br /><br />Session Facade Pattern <br />通常目中,客户端往往需要频J的Ҏ(gu)务器端数据进行操作。当采用实体QJQ作为数据的抽象层时Q如果直接让客户端程序与实体QJQ交互,会生实C个业务需求便需要大量的QJQ属性操作(如下图1Q。这直接D如下问题Q网l负载大Q远E客LӞ、ƈ发性能低、客L与服务器端关联度大、可重用性和可维护性差、性能 <br />因此有必要在客户端与实体QJQ层间加入Session QJQ层Q在Sessino EJB中实现商业逻辑q封装对实体QJQ的操作。(如下图2Q?br /><img height="384" src="http://dev2dev.bea.com.cn/images/article/other031028/image001.jpg" width="573" /><br />图1Q客L直接与实体IQ交互<br /><img height="407" src="http://dev2dev.bea.com.cn/images/article/other031028/image002.gif" width="543" /><br />图2Q通过SessionEJB层实?br />Session Fa?ade模式的好处是Q降低了|络负蝲QSessionEjb可以调用实体QJQ的本地接口Q将商业逻辑与商业数据隔;l护与开发方便;显著提高性能?br />Session Fa?ade模式因其单用,是目前用很q的模式。但具体应用q程中应注意Q避免将所有的操作装C个很大的SessionEJB内;服务器端数据l构应由实体EJB实现,除非特例否则避免直接的数据库操作QSessionEjb内某些系l通用操作的代码容易重复(比如权限查等Q解军_法是系l通用服务装在Java Class内)?/p><p><b>Message Facade Pattern</b><br />很多时候,一ơRequest需要操作多个IQ又不需要得到即时返回。对q种异步调用Q通常应用Message Fa?ade Pattern.<br />q种时候,如采用Session Fa?ade Pattern存在如下问题Q?br />1. 客户端等待返回的旉q长。一个SessionEjb的实例在完成客户hq程中中涉及到的每一ơ对其他实体Ejb的调用过E中都会被锁定直到得到实体EJBq回信息后才能进行下一步操作。这样造成客户不必要的{待Qƈ很容易因旉D整个事务p|?br />2. pȝ可靠性和定w性低。如果需要调用不同系l或服务器上或多个异构数据源的多个IQӞM一个环节出错,均导致客戯求失败?br />以Message-Driven Bean为基的Message Facade Pattern则可以解决上q异步请求需求。具体架构见下图Q?<br /><img height="427" src="http://dev2dev.bea.com.cn/images/article/other031028/image004.jpg" width="672" /><br /> 图3Q用Message Facade Pattern</p><p>Message Facade Pattern的不之处在于:<br />Q. Message-Driven Bean没有q回倹{这样通知客户执行l果只能依赖于Imail或h工等其他手段?br />Q. Message-Driven Bean执行q程中无法将捕获的异常直接返回给客户端,x法客户端直接直到错误信息?br />Q. Message-Driven Bean通过接收Message响应客户hQ对Message内容的合法性(比如对象的类型等Q依赖与客户?Ҏ(gu)产生q行旉误?br />Message Facade Patternl常与Session Facade Pattern在同一个项目里共同使用?/p><p><b>EJB Command Pattern</b></p><p>Session Facade Pattern中将商业逻辑实现装在Session EJB中,q种做法带来诸多益处之外也带来如下问题:<br />Q. ׃业务l常的变化,Dl常需要更新Session EJB代码?br />Q. 客户端代码不得不包含大量EJB相关的AQ;Q不利于后期目l护?br />Q. 目开发测试需要经常的EJB重部|过E?br />引v上述问题的重要根l就是Session EJB本n重量U组Ӟ其开发测试部|工作量较大Q开发周期较ѝ以上不_以通过EJB Command Pattern克服?br />EJB Command Pattern中将商业逻辑实现装在普通的Java ClassQ称之ؓCommand BeanQ中。该模式的具体实现有很多U,通常的框枉包括三部分: <br />Q. Command Bean.由应用开发者写的具体实现某商业操作的Java Class.主要包含getXXX(),setXXX(),execute()Ҏ(gu)?br />Q. Client-Side Routing Logic.由多个Classl成Q用于将h转发至Command SeverQ这个过E对客户是透明的。这部分代码可以跨项目用。\p则中可以考虑用QL技术?br />Q. Remote Command Server.实际执行商业操作h。通常可以用Session EJB层实现?/p><p> 整个框架见下图4Q?br /></p><p><br /><img height="415" src="http://dev2dev.bea.com.cn/images/article/other031028/image006.jpg" width="684" /><br /> 图4QCommand的基本框?br />EJB Command Patternh如下好处Q?br />Q. 适应与需要快速开发环境。因Command Bean是轻量的Java ClassQ其~译和调试比较方ѝ?br />Q. 表现层与商业实现层隔离Q同时将客户端代码与EJB层隔R?br />Q. 客L代码开发与服务器端代码开发相Ҏ(gu)晰。早期可以创建空的Command Bean方便客户端代码调试?br />    EJB Command Pattern的弱处在于:<br />Q. Command Bean中对事务的控制不如Session EJB中?br />Q. Command Bean是无状态的?br />Q. 无法异常直接返回给客户?br />Q. 在大目中,׃商业逻辑复杂Q常D大数量的Command Bean存在.<br />Q. 作ؓCommand Server的Session EJB打包时必d含Command Bean以致存在l护上的不便?br />  EJB Command Pattern的一个实际实现可以参考IBM's Command Framework.</p><p><br /><b>Data Transfer Object Factory</b><br />ZEJB的J2EE目Q经帔R要在客户端与服务器端传输大量数据。数据的l织形式常用的是DTO(Data Transfer ObjectQ服务器端数据对象的抽象)。但因ؓ客户端表现层l常是变化的Q所需要服务器端数据也变动频繁Q换句话_DTO的数量和属性经常要更改。因此如何以及在何处生成和维护DTO便是需要考虑的问题?br />一U解x案是直接在Entity EJB中直接处理,卛_Entity EJB的BeancM加入getXXXDTO()、setXXXDTO(){。但q样做导致EJB与DTO层紧紧绑定。一旦DTO更改Q与该DTO相关的EJB即需要重~译打包。EJB层与客户端层相关联不仅ɾl护困难而且DEJB的重用性大大降低?br />更好的解x案是利用Data Transfer Object Factory装对DTO的操作逻辑Q如下图Q)?br /></p><p><img height="293" src="http://dev2dev.bea.com.cn/images/article/other031028/image008.jpg" width="278" /><br />图6QDTO FactoryCZ<br />DTO Factory具体实现方式通常有两U:<br />Q. 普通Java Class实现Q用于Session Facade Pattern使用DTO环境下?br />Q. Stateless Session EJB实现Q用于非EJB客户端用DTO环境下(见图Q)?br /></p><p><img height="382" src="http://dev2dev.bea.com.cn/images/article/other031028/image010.jpg" width="624" /><br />图7QSessionEJB实现DTOFactory<br />DTO Factory带来如下好处Q?br />Q. 使Entity EJB的重用成为可能。由于不含DTO处理逻辑QEntity EJB功能单一化,只作为数据源。不通客L通过各自的DTO Factory可以从同一个Entity EJB得到各自所需的个性化数据Q自定义DTOQ?br />Q. 提高可维护性和性能?br />Q. 可以Ҏ(gu)在DTO Factory层生成很复杂的DTOl构Q诸如ѝ关联关pȝQ而对客户端提供一个透明、细化的数据接口?br />   使用DTO Factory旉要注意的是:不需为每个Entity EJB定义一个Factory。可以ؓ一pd相关的Entity EJB创徏一个FactoryQ或者只创徏一个Factory?/p><p><b>Generic Attribute Access</b></p><p>使用Entity EJB作ؓ商业数据层时Q我们首先需要从数据库加载数据,创徏对应的Entity EJB实例Q之后对内存中Entity EJB实例的属性进行相应操作。对属性的操作比较直接的做法是Q直接调用Entity EJB的getXXX()/setXXX()Q通常利用EJB2.0的本地接口;通过DTO Factory生成DTO。但q两U做法都存在如下问题Q?br />Q. 当Entity EJB的属性特别多时候,以上做法会带来复杂罗嗦的代码QEJB变的庞大无比?br />Q. 使Entity EJB的客LQ比如Session EJBQ和Entity EJB的接口紧密关联。Entity EJB属性的增删都需要更改客L代码Q给目开发和l护带来不便?br />事实上可以利用更通用的方式访问Entity EJB的属性,卛_义Generic Attribute Access Interface。见下图Q:<br /></p><p><img height="118" src="http://dev2dev.bea.com.cn/images/article/other031028/image012.jpg" width="588" /><br /> 图8QGeneric Attribute Access InterfaceCZ</p><p>Generic Attribute Access Interface由Entity EJB的本地或q程接口实现Qƈ利用Hash Maps传输数据。实现方式常见如下:<br />Q. BMPcd实体EJB可以在BeancM定义包含所有属性的U有成员变量HashMap?br />Q. CMPcd实体EJB可以在BeancM可以适用Java Reflection API实现?br />Q. 建立一个父c,在不同的情况下定义子c重载父cL法?br />使用Generic Attribute Access Interface需要在客户端与服务器端对属性以及对应的关键字徏立统一的命名习惯。常见的做法如下Q?br />Q. 建立q保持良好的文档记录和命名约定?br />Q. 在实体EJB的实现类中定义静态成员映属性?br />Q. 创徏׃n静态类Q通过成员变量映射实体EJB属性?br />Q. 通过JNDI在服务器端保存属性映关pR?br />Generic Attribute Access Interface的运用带来一下益处:<br />Q. 接口实现后对不通实体EJB都适用?br />Q. 对属性较多实体EJB能精代码Qƈ更具l护性?br />Q. 使运行中动态增删实体EJB属性成为可能?br />Generic Attribute Access Interface的缺点在于:<br />Q. 讉KEJB属性时增加了额外的操作。需要通过关键字映属性,最后还需q行cd转换?br />Q. 需要徏立客L与服务器端的命名U定?<br />Q. 因ؓ通过HashMap操作时候需要进行类型{换,Ҏ(gu)产生q行时类型不匚w异常?/p><p><b><br />Business Interface </b></p><p>EJB规范要求Bean实现cdd现所有在q程Q或本地Q接口中定义的所有方法,同时不允许Bean实现cȝ接承远E(或本圎ͼ接口。这导致编译时候很Ҏ(gu)产生两者不一致的问题Q即q程Q或本地Q接口中定义的某Ҏ(gu)为在Bean实现cM被实现等错误。ؓ避免上诉错误Q可以利用应用服务器厂商所提供的工兗但也可以应用EJB的设计架构来实现Q定义商业接口?br />Business Interface卛_定义商业接口Q在接口中定义所有EJB提供的商业方法,q让Bean实现cdq程Q或本地Q接口都实现该商业接口。其l承关系见下图9Q?br /></p><p><img height="464" src="http://dev2dev.bea.com.cn/images/article/other031028/image014.jpg" width="552" /><br />图9Q商业接口的使用<br />Business Interface是个普通的Java Class。依赖于使用本地接口与远E接口的不通,Business Interface的定义略有不同:应用与远E接口时Q在接口中的Ҏ(gu)需要抛出java.rmi.RemoteExceptionQ而应用与本地接口时候则不需要作M特别处理?br />应用Business Interface时候必L意一点:EJB规范不允许直接EJB的实例将对自q引用Qthis对象Q返回给客户端,否则~译时候即报错。但使用Business Interface后,~译时候无法检查出有无this对象q回l客L。这一炚w要程序员自己保证?/p><p><br />三. 内部数据转换{略</p><p><b>Data Transfer Object</b><br />ZEJB的J2EE多层架构应用中,l常涉及的一个问题就是如何在各层之间传递批量数据,比如客户端对服务器端数据的批量读写操作等。比如需要得到实体EJB的属性,直接的方法是多次调用不通的属性,如下图1Q:<br /></p><p><img height="324" src="http://dev2dev.bea.com.cn/images/article/other031028/image016.jpg" width="496" /><br />图1Q:低效的数据传递方?br />  但这U方法容易导致许多问题,比如性能以及代码的复杂度{,更有效的办法是在一个调用中得到所有需要的属性。所以可以引入Data Transfer Object来封装所需要的属性,q在客户与服务器端通过传递该对象一ơ实现对数据的操作。如下图Q1Q?br /><img height="310" src="http://dev2dev.bea.com.cn/images/article/other031028/image017.gif" width="501" /><br /> 图1Q:通过DTO传递数?br />  <br />DTO为普通的Java ClassQ通常是服务器端数据的快照。由于网l传输的需要,DTO应该实现java.io.Serializable接口?br />DTO的设计有两种模型QDomain DTO以及Custom DTO?br />Domain DTO仅仅实现Ҏ(gu)务器数据的拷贝,通常与实体EJBZ对一的关p?也存在ؓ多个相关联的实体EJB对应一个Domain DTO)。Domain DTO通常除用于读取更改实体EJB属性外也可用于创徏实体EJB时候。实体EJB与Domain DTO对应关系如下图1Q:<br /><img height="244" src="http://dev2dev.bea.com.cn/images/article/other031028/image018.gif" width="467" /><br /> 图1Q:Account EJB 与 Account DomainDTO<br />Domain DTO的应用除了DTO所h的一般优点外Q还有别的益处:<br />Q. 开发迅速。因Z旦实体EJB设计好后Q很Ҏ(gu)转换得到Domain DTO?br />Q. 可以利用Domain DTO的setXXX()Ҏ(gu)在客Lq行属性有效性效验?br />Domain DTO的缺Ҏ(gu)Q?br />Q. 客户端绑定了服务器端数据模型Q不利于l护?br />Q. 不够灉|Q无法处理客L的多样化数据要求。对一个数百个属性的实体EJBh一个属性时候却q回一个包含所有属性值的Domain DTO明显是笨重的实现?br />Q. D代码的重复?br />Q. Domain DTO中如果嵌套包含了别的Domain DTOӞ一旦需服务器端数据的更改而需要重定义Domain DTO模型时候异常困难?/p><p>Custom DTO则可以克服上q的一些缺炏VCustomer DTO仅仅装用户感兴的服务器数据集卛_以根据客L需求创建Customer DTO。这样作的优Ҏ(gu)灉|高效Q缺Ҏ(gu)大项目中可能D大量的Customer DTO存在?br />通常Domain DTO可以用于数据的更C创徏QCustomer DTO可以用于客户用于表现层的数据d。两者可以相辅相成。而且使用DTO一般与DTO Factory同时使用?/p><p><b>Domain Transfer Hash Map</b><br />  DTO的用往往~Z通用性。不通的用户案例需要创Z同的DTO。当目很复杂时Q从l护性考虑需要更好的数据传输的实现方式?<br />Domain Transfer Hash Map卛_用HashMap作ؓ客户所需数据集的装。好处是Q?br />Q. 良好的维护性?br />Q. 较大的通用性。不同的客户端可以用相同的数据传递方式?br />~点是:<br />Q. 需要维护客L与服务器端在属性及其对应关键字的映关pR?br />Q. 当需要用基本类型的数据时候,因ؓHash Map的限制必d基本cd先{换成对象?br />Q. 使用得到的数据时Q需要进行类型强制{换?/p><p>Data Transfer RowSet<br />当需要处理直接的JDBC调用得到的结果集Ӟ昄用DTO/Hash Map已经不合适,因ؓ需要对大量数据q行cd转换{额外操作是很费资源和不必要的,而且最l用户常需要以表格式样昄数据?<br />所以对二维表式数据Q更好的处理方式是利用Data Transfer RowSet。Data Transfer RowSet通过ResultSet直接转换为RowSet传递给客户端?br />在Session EJB中用RowSet的一D늤例代码如下图Q3Q?br /><img height="170" src="http://dev2dev.bea.com.cn/images/article/other031028/image019.gif" width="467" /><br />图1Q:使用RowSet<br />使用RowSet的好处很多:<br />Q. 接口通用于各L数据库查询操作?br />Q. 当需要表格式数据昄Ӟ因ؓ直接从ResultSet得到Q所以不需要额外的数据cd转换?br />~点是:<br />Q. 数据库结构暴露给客户端?br />Q. 不符合面向对象设计思想?br />Q. 依赖于SQL?br />Data Transfer RowSet通常用于只读式数据的昄操作Q经常和JDBC for Reading Patternq用?/p><p>四.事务和数据持久机?/p><p>  <b>JDBC for Reading Pattern</b><br /><br />ZEJB的J2EE应用中,通过EJBҎ(gu)据库的操作可以有两种方式Q实体EJB或者Session EJB中直接利用JDBC讉K?br />客户很多时候取出数据库中数据ƈ以表格方式显C。这U情形如果用实体EJB会导致如下问题:<br />Q. 引用服务器端频繁的数据库查询和加载操作。因为加载N个实体EJB总需要进行一ơfind()操作                                                           Nơ数据加载?br />Q. 如果使用Remote接口Q引起频J的额外|络操作?br />Q. 对关联关pL较复杂的数据库表l构Q很隄接通过Entity EJB表现?br />因此在只需Ҏ(gu)据库表数据进行只读访问时候,应该采用JDBC for Reading PatternQ即通过JDBC直接讉K数据库。除了避免上qC用实体EJB的缺点还带来一下好处:<br />Q. 充分利用数据库能力,比如数据库的~存机制?br />Q. 减少了对事务控制的资源?br />Q. 利用自定义SQL可以按需要比较灵zȝd数据?br />Q. 只需要一ơ数据查询,减少了数据库操作?br />~点是:<br />Q. 于J2EE应用的面向对象设计相q背?br />Q. 因ؓSession EJB代码中包含了自定义SQLQ维护性差?br />Q. Session EJB中不得不包含JDBC的APIQƈ且需要了解数据库l构?/p><!--文章其他信息--><img src ="http://www.aygfsteel.com/liaojiyong/aggbug/56241.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/liaojiyong/" target="_blank">liaojiyong</a> 2006-07-03 09:30 <a href="http://www.aygfsteel.com/liaojiyong/archive/2006/07/03/56241.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3.0之介lEntityQ{Q?/title><link>http://www.aygfsteel.com/liaojiyong/archive/2006/07/03/56222.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Sun, 02 Jul 2006 16:57:00 GMT</pubDate><guid>http://www.aygfsteel.com/liaojiyong/archive/2006/07/03/56222.html</guid><wfw:comment>http://www.aygfsteel.com/liaojiyong/comments/56222.html</wfw:comment><comments>http://www.aygfsteel.com/liaojiyong/archive/2006/07/03/56222.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/liaojiyong/comments/commentRss/56222.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/liaojiyong/services/trackbacks/56222.html</trackback:ping><description><![CDATA[ <div id="wmqeeuq" class="contentBox"> <div id="wmqeeuq" class="section"> <a name="EJB3介绍:Overview"> </a> <h2>EJB3介绍:Overview</h2> <p>EJB作ؓ企业U的数据讉K/持久化标准在1999q作为J2EE规范的核心规范出玎ͼ极大的{变了java企业U开发的模式Qؓjava软g开发提供了一个良好的架构?EJB?.0?.1在J2EE架构中,都是作ؓ一个服务器端的(Server side)的数据访问中间g。开发h员通过EJB标准的API接口来访问操作数据,避免直接用JDBC和Sql操作底层的数据库?</p> <p>采用EJB架构的目标在于: </p> <ul> <li>减轻直接操作底层数据库的工作? </li> <li>Z业开发引入了面向对象/面向服务的开发架? </li> <li>数据对象生命周期的自动管? </li> <li>分布式能? </li> <li>集成/声明式的安全/事务理 </li> </ul> <p> </p> <p>在旧的EJB模型中(2.1以前Q?EJB实现了大部分的目标,但一个巨大的~陷是原有的模型在试囑ևL据访问工作量的同时也引入了更多的复杂开发需求?例如EJB核心的的Entity Bean必须特定的Home,Remote,Business接口Q发布前需要预~译Q只能实现单表映操作,静态的EJB-QL(EJB查询语言Q都不能满化数据库操作的目标?EJB 2.1的复杂度Q开发成本和性能问题使得EJB在问?q后仍然{不到广泛的应用?</p> <p>C2004q_随着POJO( Plain Old Java Object )模型的出玎ͼ动态代码操作,IOC模式{先q,单实用技术的发展和它们在各种独立产品中的表现Q都证明POJO,IOC的技术比原有的EJB 2.1模型更适合作ؓ数据讉K中间Ӟ开发的隑ֺ和成本远q小于目前的EJB模型Q确有更灉|和可扩展?2004q?月J2EEq_规范集众家所长,推出了跨式的Java EE 5.0规范Q最核心的是全面引入新的ZPOJO和IOC技术的EJB3模型。到此,J2EE 5规范( Java EE 5 )成ؓ一个集大成者,U百家之长,成ؓjava企业开发统一的标准规范?</p> </div> <div id="wmqeeuq" class="section"> <a name="EJB_3和EJB_2_1的区?> </a> <h2>EJB 3和EJB 2.1的区?/h2> <p>从整个EJB规范的角度来_EJB 3和EJB 2.1最大变更在Entity Bean持久化API上。在EJB3中,Entity Bean持久化已l单独作Z个Persistence API规范和其他的EJB部分分离开来。下面我们主要讨论EJB 3和EJB 2.1在持久化API上的区别?</p> <p>EJB 2.1模型存在复杂度高的缺P </p> <ul> <li>EJB 2.0 模型要求创徏多个lg接口q实现多个不必要的回调方? </li> <li>lg接口要求实现 EJBObject ?EJBLocalObject 以及处理许多不必要的异常 </li> <li>ZXML的EJB 2.0 部v描述W比较复杂ƈҎ(gu)出错 </li> <li>Z EJB 模型的容器管理持久性在开发和理斚wq于复杂Qƈ且失M几个基本Ҏ(gu)?-如用数据库序列定义主键的标准方? </li> <li>EJBQL 语法非常有限Q而且是静态的Q无法做到运行期间的动态查? </li> <li>EJB 2.0 lgq是真正面向对象的Q因为它们在l承和多态性方面的有用限? </li> <li>开发h员无法在 EJB 容器外部试 EJB 模块Q而在容器内部调试 EJB非常复杂和耗时 </li> <li>查找和调?EJB 2.0 是一复杂的d。即使是在应用程序中使用最基本?EJB 也需要对 JNDI 有一个详l的了解 </li> <li>对容器的依赖使得EJB 2.0只能用于服务器组件的开发,无法实现一ơ编写,四处q行的面向构件的开?</li> </ul>所有这些复杂度和缺P都导致EJB 2.0的采用无法真正简化开发ƈ提高生力? <p></p><p>EJB 3.0 旨在解决以往EJB 2.0 模型的复杂性和提高灉|性,具体体现在: </p><ul><li>消除了不必要的接口Remote, Home, EJB以及回调Ҏ(gu)实现 </li><li>实体Bean采用了POJO模型Q一个简单的java bean可以是一个Entity Bean。无需依赖容器q行和测? </li><li>全面采用O/R Mapping技术来实现数据库操? </li><li>实体Bean可以q用在所有需要持久化的应用,不管是客Lq是服务器端。从而真正实现面向构件的开? </li><li>实体 bean 现在支持l承和多态? </li><li>灉|丰富的EJB3查询语言 </li><li>SQL支持 </li><li>使用元数据批注代曉K|描q符Q减复杂配|和提高可维护? </li><li>常?Java cȝ?EJB q将常规业务接口用于 EJB </li></ul><p></p></div> <div id="wmqeeuq" class="section"> <a name="EJB_3中的元数据批?Annotation"> </a> <h2>EJB 3中的元数据批?Annotation</h2> <p>EJB3 规范中引入了元数据批?Annotation)。Annotation是从J2SE 1.5开始称为java语言的一部分。Annotationq不是一个新的事物,在J2SE 1.5以前Qh们已l自行引入了象著名的XDoclet{外挂式的元数据Ҏ(gu)Ҏ(gu)。而在.NET中,元数据批注也早已l是C#语言的成分了?</p> <p>在以往Q我们都是采用xml作ؓ配置Ҏ(gu)Q但采用文本的xml配置存在一些缺P </p> <ul> <li>描述W多Q不Ҏ(gu)记忆和掌? </li> <li>无法做自动的校验Q需要h工排? </li> <li>当系l变大时Q大量的xml配置难以理 </li> <li>d和解析xml配置非常耗时Q导致应用启动缓慢,不利于测试和l护 </li> <li>做O/R Mapping的时候需要在java文g和xml配置文g之间交替Q增大了工作? </li> <li>q行中保存xml配置需要消耗额外的内存 </li> </ul> <p> </p> <p>采用元数据可以很好的解决q些问题: </p> <ul> <li>描述W大量减。以往在xml配置中往往需要描qjava属性的cdQ关pȝ{。而元数据本n是java语言Q从而省略了大量的描q符 </li> <li>~译期校验。错误的Ҏ(gu)在编译期间就会报错? </li> <li>元数据批注在java代码中,避免了额外的文gl护工作 </li> <li>元数据被~译成java bytecodeQ消耗小的多内存Q读取也非常q速,往往比xml配置解析快几个数据量U,利于试和维?</li> </ul> <h2>W一个Entity Bean:HelloWorld</h2> <p>EJB3中的Entity Bean是如此的单,是一个普通的java bean加上一些精炼的元数据批注?</p> <div id="wmqeeuq" class="source"> <pre> @Entity @Table( name="helloTable" ) public class HelloEntityBean { private int id; private String foo; /** * The entity class must have a no-arg constructor. */ public HelloEntityBean() { } public HelloEntityBean(int id, String foo) { this.id = id; this.foo = foo; } @Id(generate=GeneratorType.NONE) public int getId() { return id; } public void setId(int id) { this.id = id; } public String getFoo() { return foo; } public void setFoo(String foo) { this.foo = foo; } public String toString(){ return "HelloEntityBean: id=" + id + ", foo=" + foo; } } </pre> </div> <p>代码中元数据的说明:</p> <p>@Entity :EJB3 Entity Bean的批注,表明当前的java bean作ؓ一个Entity Bean来处理?/p> <p>@Table( name="helloTable" ) :֐思义Q定义当前Entity对应数据库中的表?/p> <p>@Id(generate=GeneratorType.NONE) :我们把HelloEntityBean的id属性定义ؓ主键。主键生策略ؓGeneratorType.NONE,意味q是一个业务主键?/p> <p>p么简单!<br /><br /></p> <div id="wmqeeuq" class="contentBox"> <div id="wmqeeuq" class="section"> <a name="解说Entity"> </a> <h2>解说Entity</h2> <p>从EJB3.0开始,Entity Bean持久化规范与EJB的其他规范如Session Bean, Message Driven Bean和EJB3容器规范开始分,单独作ؓ一个持久化API。而在来Q该持久化API很可能会从EJB3.0规范中脱d来成Z个独立的规范Java Persistence API。作为Javaq_上的通用数据讉K标准接口?Z跟规范一_我们在开发手册中Entity BeanUCؓEntity?/p> <p>虽然EJB3 Entity可以是很单的java beanQ只要批注了@Entity或者在xml配置中作了说明,p做一个可持久化的Entity处理?但还是需要遵行一定的规则Q?/p> <ul> <li>Entitycd要有一个无参数的public或者protected的Constructor? </li> <li>如果在应用中需要将该Entitycdd来在分布式环境中作ؓ参数传递,该Entity Class需要实现java.io.Serialzable接口? </li> <li>EntitycM可以是finalQ也不可有final的方法? </li> <li>abstractcdConcrete实体c都可以作ؓEntitycR? </li> <li>EntitycM的属性变量不可以是public。Entitycȝ属性必通过getter/setter或者其他的商业Ҏ(gu)获得?</li> </ul> </div> <div id="wmqeeuq" class="section"> <a name="定义对Entity中属性变量的讉K"> </a> <h2>定义对Entity中属性变量的讉K</h2> <p>在绝大部分的商业应用Q开发h员都可以忽略q部分无需兛_。但如果你需要编写复杂的Entitycȝ话,你需要了解这个部分。复杂的EntitycL指在Entitycȝgetter/setter和商业方法中包含比较复杂的业务逻辑而不是仅仅返?W值某个属性?/p> <p>在大部分的情况下Q我们都使EntitycMsetter/getter中的逻辑可能简单,除了必要的校验符值外Q不要包含复杂的业务逻辑Q例如对兌的其他Entityc进行操作。但有些情况下,我们q是需要在Entitycȝsetter/getterҎ(gu)中包含商业逻辑。这时候,采用何种属性访问方式就可能会媄响代码的性能甚至是逻辑正确产生影响?/p> <p>EJB3持久化规范中,在默认情况下所有的属性都会自动的被持久化Q除非属性变量用@Transient元数据进行了标注。针对可持久化属性定义了两种属性访问方?access): FIELD和PROPERTY?/p> <ul> <li>如果采用access=FIELD, EJB3 Persistenceq行环境QEJB3持久化品,如Liberator EJB3)直接讉K对象的属性变量,而不是通过getter。这U访问方式也不要求每个属性必Lgetter/setter。如果需要在getter中包含商业逻辑Q应该采用access=FIELD的方式? </li> <li>如果采用access=PROPERTY, EJB3 Persistenceq行环境?yu)通过EntitycM的getter来访问对象的属性变量,q就要求每个属性变量要有getter/setterҎ(gu)。在EJB3中,默认的属性访问方式是PROPERTY。access=PROPERTY时getter/setter的逻辑应该量单?</li> </ul> <p>规范中access方式q有多一层含义。就是采用access=FIELDӞ元数据应该批注在属性上?/p> <div id="wmqeeuq" class="source"> <pre> @Id(generate=GeneratorType.NONE) private int id; private String foo; /** * The entity class must have a no-arg constructor. */ public HelloEntityBean() { } public int getId() { return id; } </pre> </div> <p>采用access=PROPERTY(默认方式)Ӟ元数据应该批注在对应属性变量的getter上?/p> <div id="wmqeeuq" class="source"> <pre> private int id; private String foo; /** * The entity class must have a no-arg constructor. */ public HelloEntityBean() { } @Id(generate=GeneratorType.NONE) public int getId() { return id; } </pre> </div> <p>Z方便开发,Liberator EJB3实现对元数据Ҏ(gu)的位|比规范规定的宽松,针对属性变量或它的getterq行Ҏ(gu)都可以,不受accesscd的媄响?/p> <p>对EntitycMQgetter/setter的命名规则遵从java bean规范?/p> <p>EntitycM的属性变量可以是以下数据cdQ?/p> <ul> <li>原始数据cd和他们的对象cd </li> <li>java.lang.String </li> <li>java.math.BigInteger </li> <li>java.math.BigDecimal </li> <li>java.util.Date </li> <li>java.util.Calendar </li> <li>java.sql.Date </li> <li>java.sql.Time </li> <li>java.sql.Timestamp </li> <li>byte[] </li> <li>Byte[] </li> <li>char[] </li> <li>Character[] </li> <li>enums </li> <li>Entityc? </li> <li>嵌入实体c?embeddable classes) </li> </ul> <p>q可以是以下集合cd:</p> <ul> <li>java.util.Collection和它的实体类 </li> <li>java.util.Set和它的实体类 </li> <li>java.util.List和它的实体类 </li> <li>java.util.Map和它的实体类 </li> </ul> </div> <div id="wmqeeuq" class="section"> <a name="主键和实体标识(Primary_Key_and_Entity_Identity_"> </a> <h2>主键和实体标识(Primary Key and Entity Identity)</h2> <p>每个Entityc都必须有一个主键。在EJB3中定义了两种主键Q?/p> <ul> <li>键单主键 </li> <li>复合主键 </li> </ul> <p>单主键必d应Entity中的一个属性变量(Instance Variable)Q而该属性对应数据库表中的一列。用简单主键,我们只需要用@Id元数据对一个属性变量或者她的getterҎ(gu)q行Ҏ(gu)?/p> <p>当我们需要用一个或多个属性变量(表中的一列或多列Q联合v来作Z键,我们需要用复合主键。复合主键要求我们编写一个复合主键类( Composite Primary Key Class )。复合主键类需要符合以下一些要求:</p> <ul> <li>复合主键cdLpublic和具备一个没有参数的constructor </li> <li>复合主键cȝ每个属性变量必Lgetter/setterQ如果没有,每个属性变量则必须是public或者protected </li> <li>复合主键cdd现java.io.serializable </li> <li>复合主键cdd现equals()和hashcode()Ҏ(gu) </li> <li>复合主键cM的主键属性变量的名字必须和对应的Entity中主键属性变量的名字相同 </li> <li>一旦主键D定后Q不要修改主键属性变量的?</li> </ul>一L一个复合主键的例子。EntitycPersonQ它的主键属性变量是firstName和lastName? <div id="wmqeeuq" class="source"><pre> @Id private String firstName; @Id private String lastName; public Person() { } </pre></div>Person的复合主键类Q? <div id="wmqeeuq" class="source"><pre> public class PersonPK implements java.io.Serializable{ private String firstName; private String lastName; public PersonPK() { } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof PersonPK)) return false; final PersonPK personPK = (PersonPK) o; if (!firstName.equals(personPK.firstName)) return false; if (!lastName.equals(personPK.lastName)) return false; return true; } public int hashCode() { int result; result = firstName.hashCode(); result = 29 * result + lastName.hashCode(); return result; } } </pre></div></div> </div> </div> </div> <img src ="http://www.aygfsteel.com/liaojiyong/aggbug/56222.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/liaojiyong/" target="_blank">liaojiyong</a> 2006-07-03 00:57 <a href="http://www.aygfsteel.com/liaojiyong/archive/2006/07/03/56222.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3.0之操作Entity http://www.aygfsteel.com/liaojiyong/archive/2006/07/03/56223.htmlliaojiyongliaojiyongSun, 02 Jul 2006 16:57:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2006/07/03/56223.htmlhttp://www.aygfsteel.com/liaojiyong/comments/56223.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2006/07/03/56223.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/56223.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/56223.html

操作持久化Entity

对Entityq行操作的API都设计在javax.persistence.EntityManager接口上。EntityManagerQ顾名思义是管理所有EJB 3q行环境中的所有Entity?EntityManagerҎ(gu)q行的环境不同分为容器管理的EntityManager和应用管理的EntityManager。Liberator EJB3是一个可以运行在J2SE环境中的 嵌入式的EJB3 Persistence实现Q因此在Liberator EJB3中的 EntityManager都是指应用管理的EntityManager?/p>

配置和获得EntityManager

在J2SE环境中,EJB3定义了一个javax.persistence.Persistencecȝ于启动EJB3q行环境。要获得EntityManager,首先需要通过javax.persistence.Persistence获得EntityManagerFactoryQ然后调用EntityManagerFactory.createEntityManager()Ҏ(gu)获得?
                
    // 获得默认当前的EntityManagerFactory                
    final EntityManagerFactory emf = Persistence.createEntityManagerFactory();
    final EntityManager entityManager = emf.createEntityManager();    
                
            

当调用Persistence.createEntityManagerFactory()的时候,Persistence会做以下的步骤:

  • 搜烦当前jar包的META-INFO/persistence.xml配置文g
  • 如果没有在META-INFO下找到persistence.xmlQ搜索当前线E的ContextClassLoader中的persistence.xml
  • Ҏ(gu)获得的persistence.xml初始化EntityManagerFactory
每个EntityManagerFactory都必L一个persistence.xml配置文g。下面是一个例子:
                
<entity-manager>
    <name>myEntityManager</name>
    <provider>com.redsoft.ejb3.PersistenceProviderImpl</provider>
    <class>com.redsoft.samples.HelloEntityBean</class>
    <properties>
        <property name="ConnectionDriverName" value="com.mysql.jdbc.Driver"/>
        <property name="ConnectionURL" value="jdbc:mysql://localhost/EJB3Test"/>
        <property name="ConnectionUserName" value="ejb3"/>
        <property name="ConnectionPassword" value="ejb3"/>
        <property name="RetainValues" value="true"/>
        <property name="RestoreValues" value="false"/>
        <property name="IgnoreCache" value="false"/>
        <property name="NontransactionalRead" value="true"/>
        <property name="NontransactionalWrite" value="false"/>
        <property name="Multithreaded" value="false"/>
        <property name="Liberator.option.action" value="create"/>
        <property name="Liberator.option.cache" value="com.redsoft.jdo.enterprise.OscacheAdapter"/>
        <property name="Liberator.option.JMXEnabled" value="false"/>
        <property name="Liberator.option.NamingPort" value="3012"/>
        <property name="Liberator.option.JMXPort" value="3011"/>
        <property name="Liberator.option.JDBC.scrollable" value="false"/>
        <property name="Liberator.option.JDBC.fetchSize" value="500"/>
        <property name="cache.algorithm" value="LRUCache"/>
        <property name="cache.capacity" value="5000"/>
        <property name="log4j.logger.com.redsoft" value="FATAL"/>
    </properties>
</entity-manager>   
                
            

<name></name> 定义一个EntityManagerFactory的名字,q样当应用中需要多个EntityManagerFactory的时候可以区别。通常情况下,一个EntityManagerFactory对应一个数据源?/p>

<provider></provider> 定义采用的什么EJB3 Persistenceq行环境Q也是EJB3 Persistence产品)Q例子中采用的的是Liberator EJB3的运行环境。正如前面说的,在EJB3规范? EJB3 Persistenceq行环境( Runtime )是作Z个独立的嵌入式模块,你可以随意的更换不同的EJB3 Persistenceq行环境而不会媄响你的应用程序?strong>甚至在J2EE服务器内q行你也可以不用服务器本w提供的EJB3 Persistenceq行环境Q而采用第三方的EJB3 Persistenceq行环境?/p>

<class></class> 定义哪些cLEntity持久化类。如果是试环境或者你不采用ear/war的方式发布你的应用,而只是把~译后的cȝ接拷贝到web容器中,在添加一个新的EntitycLQ需要在q里d一行。要求这个步骤是因ؓ在J2EE 5架构中EJB3q行环境的嵌入式设计。采用这U松耦合设计使EJB3 Persistenceq行环境不能控制持久化类的加?由J2EE服务器负责加?, q样EJB3 Persistenceq行环境?yu)无法分辨jvm中哪个类是持久化Entityc,哪个不是。因此需要一个额外的信息来让EJB3 Persistence知道那些是持久化Entity?/p>

<property></property> 定义了了EJB3 Persistenceq行环境需要的其他参数Q这些参C是标准的Q而是由EJB3 Persistenceq行环境的厂商自行定义?/p>详细的配|方法参看persistence.xml的语法?

持久化Entity(Persist)

                
    final EntityManagerFactory emf = Persistence.createEntityManagerFactory();
    final EntityManager entityManager = emf.createEntityManager();

    final HelloEntityBean hello = new HelloEntityBean( 1, "foo" );
    EntityTransaction trans = entityManager.getTransaction();
    trans.begin();
    
    // 持久化hello,在此操作之前hello的状态ؓnew
    entityManager.persist( hello );
    
    // q时hello的状态变为managed
    
    trans.commit();

    entityManager.close();
    
    // q时hellow的状态变为detached.
    
                 
            
Liberator EJB3支持Persistence by reachability。当保存一个EntityӞ以该对象为根对象的整个对象图都会自动的被保存。但在EJB3中,我们仍然可以通过关系元数据(比如OneToOne,OneToMany)的cascade属性来_定义保存的联行为?下面我们来看看不同的cascade属性的区别?

不配|cascade的情况下QEJB3 Persistenceq行环境默认不会采用Persistence by reachability?/p>

                
    public class Father{
        @Id
        int id
        
        String name;
        
        // OneToOne没有配置cascade属性,因此默认不会使用Persistence by reachablity
        @OneToOne
        Son mySon
        
        public Father( int id, String name, Son mySon ){
            this.id = id;
            this.name = name;
            this.mySon = mySon;
        }
    }
                  
现在来保存一个Father和Son?
                
    final EntityManager manager = emf.createEntityManager();
    manager.getTransaction().begin;
    
    Son mySon = new Son();
    Father = new Father( 1, "father" mySon );
    
    // 保存Father
    manager.persist( father );
    
    // ׃OneToOne关系中没有配|casacade属性,father 兌的mySon不会被自动保存,需要分别保?
    manager.persist( mySon );
    manager.getTransaction().commit();
    manager.close();
                 
现在我们配置casacde=CascadeType.ALL
                
    public class Father{
        @Id
        int id
        
        String name;
        
        // OneToOne配置cascade=CascadeType.ALL,配置cascade=CascadeType.PERSIT也对persist操作也可以获得同L效果?
        // CascadeType.ALL包含CascadeType.PERSIST?
        @OneToOne(cascade=CascadeType.ALL)
        Son mySon
        
        public Father( int id, String name, Son mySon ){
            this.id = id;
            this.mySon = mySon;
            this.name = name;
        }
    }
                  
在代码中同样持久化Father和mySon?
                
    final EntityManager manager = emf.createEntityManager();
    manager.getTransaction().begin;
    
    Son mySon = new Son();
    Father = new Father( 1, mySon );
    
    // 保存Father。由于OneToOne关系中配|casacade=CascadeType.ALL属?兌的mySon会自动地被持久化
    manager.persist( father );
    manager.getTransaction().commit();
    manager.close();
                 
׃Liberator EJB3q行环境采用了弱引用POJO理技术,能很好的支持Persistence by reachablity而不会有其他产品有的潜在内存回收的问题, 因此在应用中可能用cascade=CascadeType.ALL来减持久化操作的复杂性和代码?/strong>Q特别是在有复杂对象关系囄时候?

获取Entity

如果知道Entity的唯一标示W,我们可以用find()Ҏ(gu)来获得Entity?
                        
    Father father = manager.find( Father.class, new Integer( 1 ) );
            
    // ׃JDK1.5支持自动转型Q也可以如下使用
            
    Father father = manager.find( Father.class, 1 );
    
    /* 
    * 或?可以用Entity名字作ؓ查找。但无法利用JDK 1.5的自动{型功能,
    *  需要用对象作为查找主键,q要对获得Entityq行转型
    */
    
    Father father = (Father)manager.find( "com.redsoft.samples.Father", new Integer( 1 ) );
            
          

更新Entity

对Entity的更新必d事物内完成。和persist中一P关系元数据的cascade属性对是否集联删除有媄响?
                
    transaction.begin();                
    Father father = manager.find( Father.class, 1 );
    
    // 更新原始数据cd
    father.setName( "newName" );
    
    // 更新对象引用
    Son newSon = new Son();
    father.setSon( newSon );
    
    
    // 提交事务Q刚才的更新同步到数据库
    transaction.commit();
                 

删除Entity

对Entity的删除必d事物内完成?
                
    transaction.begin();                
    
    Father father = manager.find( Father.class, 1 );
        
    // 如果father/son的@OneToOne的cascade=CascadeType.ALLQ在删除father时候,也会把son删除?
    // 把cascade属性设为cascade=CascadeType.REMOVE有同L效果?
    manager.remove( father );
        
    // 提交事务Q刚才的更新同步到数据库
    transaction.commit();
                 

q/附合(Detach/Merge)

在三层或者分布式应用中,我们很多时候需要Entity能脱EntityManagerQ避免长旉保持EntityManager打开占用资源和可以在不同的JVM之间传递Entity?/p>

在脱EJB3 Persistence Runtime(EntityManager)的管理后,我们仍然可以d或者修改Entity中的内容。而在E后的时_我们又可以将Entity重新和原有或者新的EntityManager附合Q如果附合前Entity被改动过Q更改的数据可以自动的被发现q和数据库同步?/p>

                
    EntityManager entityManager = emf.createEntityManager();
    
    // q时Fatherq是被EntityManager理?
    Father father = manager.find( Father.class, 1 );
    
    // 当entityManger关闭的时候,当前被entityManager理的Entity都会自动的脱EntityManagerQ状态{变ؓdetached
    entityManager.close();
    
    // qEntityManager后,我们仍然可以修改Father的属?
    father.setName( "newName" );
    
    // 在稍后的Q我们可以将father重新附和C个新的或者原来的EntityManager?
    EntityManager newEntityManager = emf.createEntityManager();
    
    // 附合( merge )需要在事务中进?
    newEntityManager.getTransaction().begin();
    newEntityManager.merge( father );
    
    // commit后father中的被修改的内容会同步到数据库?
    newEntityManager.getTransaction().commit();
    

                 

Liberator EJB3 Persistneceq行环境׃支持Persistence-by-reachablity。我们徏议采用cascade=CascadeType.ALLQ这样当需要附合的是一个对象图的时候,我们只需要merge根对象即可,整个对象图,对象图中被修改过的对象都会被自动识别和同步?/p>

需要注意的是在qEJB3 Persistence Runtime的管理后Q如果对象中有定义ؓlazy-load的属性将无法讉K?/p>



liaojiyong 2006-07-03 00:57 发表评论
]]>
EJB3.0之关pd象映元数据Q{Q?/title><link>http://www.aygfsteel.com/liaojiyong/archive/2006/07/03/56221.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Sun, 02 Jul 2006 16:53:00 GMT</pubDate><guid>http://www.aygfsteel.com/liaojiyong/archive/2006/07/03/56221.html</guid><wfw:comment>http://www.aygfsteel.com/liaojiyong/comments/56221.html</wfw:comment><comments>http://www.aygfsteel.com/liaojiyong/archive/2006/07/03/56221.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/liaojiyong/comments/commentRss/56221.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/liaojiyong/services/trackbacks/56221.html</trackback:ping><description><![CDATA[ <div id="wmqeeuq" class="contentBox"> <div id="wmqeeuq" class="section"> <a name="Table"> </a> <h2>Table</h2> <p>Table用来定义entity主表的nameQcatalogQschema{属性?/p> <p>元数据属性说明:</p> <ul> <li>name: 表名 </li> <li>catalog: 对应关系数据库中的catalog </li> <li>schemaQ对应关pL据库中的schema </li> <li>UniqueConstraints:定义一个UniqueConstraint数组Q指定需要徏唯一U束的列Q具体参?a ><font color="#002c99">UniqueConstraint</font></a>Q?</li> </ul> <div id="wmqeeuq" class="source"> <pre> @Entity @Table(name="CUST") public class Customer { ... } </pre> </div>  </div> <div id="wmqeeuq" class="section"> <a name="SecondaryTable"> </a> <h2>SecondaryTable</h2> <p>一个entity class可以映射到多表,SecondaryTable用来定义单个从表的名字,主键名字{属性?/p> <p>元数据属性说明:</p> <ul> <li>name: 表名 </li> <li>catalog: 对应关系数据库中的catalog </li> <li>schemaQ对应关pL据库中的schema </li> <li>pkJoin: 定义一个PrimaryKeyJoinColumn数组Q指定从表的主键列(具体参看<a ><font color="#002c99">PrimaryKeyJoinColumn</font></a>Q? </li> <li>UniqueConstraints:定义一个UniqueConstraint数组Q指定需要徏唯一U束的列Q具体参?a ><font color="#002c99">UniqueConstraint</font></a>Q?</li> </ul> <p>下面的代码说明CustomercL到两个表,主表名是CUSTOMERQ从表名是CUST_DETAILQ从表的主键列和主表的主键列cd相同Q列名ؓCUST_ID?/p> <div id="wmqeeuq" class="source"> <pre> @Entity @Table(name="CUSTOMER") @SecondaryTable(name="CUST_DETAIL",pkJoin=@PrimaryKeyJoinColumn(name="CUST_ID")) public class Customer { ... } </pre> </div> </div> <div id="wmqeeuq" class="section"> <a name="SecondaryTables"> </a> <h2>SecondaryTables</h2> <p>当一个entity class映射C个主表和多个从表Ӟ用SecondaryTables来定义各个从表的属性?/p> <p>元数据属性说明:</p> <ul> <li>valueQ?定义一个SecondaryTable数组Q指定每个从表的属性?</li> </ul> <div id="wmqeeuq" class="source"> <pre> @Table(name = "CUSTOMER") @SecondaryTables( value = { @SecondaryTable(name = "CUST_NAME", pkJoin = { @PrimaryKeyJoinColumn(name = "STMO_ID", referencedColumnName = "id") }), @SecondaryTable(name = "CUST_ADDRESS", pkJoin = { @PrimaryKeyJoinColumn(name = "STMO_ID", referencedColumnName = "id") }) }) public class Customer {} </pre> </div> </div> <div id="wmqeeuq" class="section"> <a name="UniqueConstraint"> </a> <h2>UniqueConstraint</h2> <p>UniqueConstraint定义在Table或SecondaryTable元数据里Q用来指定徏表时需要徏唯一U束的列?/p> <p>元数据属性说明:</p> <ul> <li>columnNames:定义一个字W串数组Q指定要建唯一U束的列名?</li> </ul> <div id="wmqeeuq" class="source"> <pre> @Entity @Table(name="EMPLOYEE", uniqueConstraints={@UniqueConstraint(columnNames={"EMP_ID", "EMP_NAME"})} ) public class Employee { ... } </pre> </div> </div> <div id="wmqeeuq" class="section"> <a name="Column"> </a> <h2>Column</h2> <p>Column元数据定义了映射到数据库的列的所有属性:列名Q是否唯一Q是否允ؓI,是否允许更新{?/p> <p>元数据属性说明:</p> <ul> <li>name:列名? </li> <li>unique: 是否唯一 </li> <li>nullable: 是否允许为空 </li> <li>insertable: 是否允许插入 </li> <li>updatable: 是否允许更新 </li> <li>columnDefinition: 定义时创建此列的DDL </li> <li>secondaryTable: 从表名。如果此列不建在主表上(默认建在主表Q,该属性定义该列所在从表的名字?</li> </ul> <div id="wmqeeuq" class="source"> <pre> public class Person { @Column(name = "PERSONNAME", unique = true, nullable = false, updatable = true) private String name; @Column(name = "PHOTO", columnDefinition = "BLOB NOT NULL", secondaryTable="PER_PHOTO") private byte[] picture; </pre> </div> </div> <div id="wmqeeuq" class="section"> <a name="JoinColumn"> </a> <h2>JoinColumn</h2> <p>如果在entity class的field上定义了关系Qone2one或one2many{)Q我们通过JoinColumn来定义关pȝ属性。JoinColumn的大部分属性和ColumncM?/p> <p>元数据属性说明:</p> <ul> <li>name:列名? </li> <li>referencedColumnName:该列指向列的列名Q徏表时该列作ؓ外键列指向关pd一端的指定列) </li> <li>unique: 是否唯一 </li> <li>nullable: 是否允许为空 </li> <li>insertable: 是否允许插入 </li> <li>updatable: 是否允许更新 </li> <li>columnDefinition: 定义时创建此列的DDL </li> <li>secondaryTable: 从表名。如果此列不建在主表上(默认建在主表Q,该属性定义该列所在从表的名字?</li> </ul> <p>下面的代码说明Custom和Order是一对一关系。在Order对应的映表Z个名为CUST_ID的列Q该列作为外键指向Custom对应表中名ؓID的列?/p> <div id="wmqeeuq" class="source"> <pre> public class Custom { @OneToOne @JoinColumn( name="CUST_ID", referencedColumnName="ID", unique=true, nullable=true, updatable=true) public Order getOrder() { return order; } </pre> </div> </div> <div id="wmqeeuq" class="section"> <a name="JoinColumns"> </a> <h2>JoinColumns</h2> <p>如果在entity class的field上定义了关系Qone2one或one2many{)Qƈ且关pd在多个JoinColumnQ用JoinColumns定义多个JoinColumn的属性?/p> <p>元数据属性说明:</p> <ul> <li>value: 定义JoinColumn数组Q指定每个JoinColumn的属性?</li> </ul> <p>下面的代码说明Custom和Order是一对一关系。在Order对应的映表Z列,一列名为CUST_IDQ该列作为外键指向Custom对应表中名ؓID的列,另一列名为CUST_NAMEQ该列作为外键指向Custom对应表中名ؓNAME的列?/p> <div id="wmqeeuq" class="source"> <pre> public class Custom { @OneToOne @JoinColumns({ @JoinColumn(name="CUST_ID", referencedColumnName="ID"), @JoinColumn(name="CUST_NAME", referencedColumnName="NAME") }) public Order getOrder() { return order; } </pre> </div> </div> <div id="wmqeeuq" class="section"> <a name="Id"> </a> <h2>Id</h2> <p>声明当前field为映表中的主键列。id值的获取方式有五U:TABLE, SEQUENCE, IDENTITY, AUTO, NONE。Oracle和DB2支持SEQUENCEQSQL Server和Sybase支持IDENTITY,mysql支持AUTO。所有的数据库都可以指定为AUTOQ我们会Ҏ(gu)不同数据库做转换。NONE(默认)需要用戯己指定Id的倹{Tablecd详见<a ><font color="#002c99">TableGenerator</font></a>的介l?/p> <p>元数据属性说明:</p> <ul> <li>generate():主键值的获取cd </li> <li>generator():<a ><font color="#002c99">TableGenerator</font></a>的名字(当generate=GeneratorType.TABLE才需要指定该属性) </li> </ul> <p>下面的代码声明Task的主键列id是自动增长的?Oracle和DB2从默认的SEQUENCE取|SQL Server和Sybase该列建成IDENTITYQmysql该列建成auto increment?</p> <div id="wmqeeuq" class="source"> <pre> @Entity @Table(name = "OTASK") public class Task { @Id(generate = GeneratorType.AUTO) public Integer getId() { return id; } } </pre> </div> </div> <div id="wmqeeuq" class="section"> <a name="IdClass"> </a> <h2>IdClass</h2> <p>当entity class使用复合主键Ӟ需要定义一个类作ؓid class。id class必须W合以下要求:cdd明ؓpublicQƈ提供一个声明ؓpublic的空构造函数。必d现Serializable接,覆写equals()和hashCodeQ)Ҏ(gu)。entity class的所有id field在id class都要定义Q且cd一栗?/p> <p>元数据属性说明:</p> <ul> <li>value: id class的类?</li> </ul> <p> </p> <div id="wmqeeuq" class="source"> <pre> public class EmployeePK implements java.io.Serializable{ String empName; Integer empAge; public EmployeePK(){} public boolean equals(Object obj){ ......} public int hashCode(){......} } @IdClass(value=com.acme.EmployeePK.class) @Entity(access=FIELD) public class Employee { @Id String empName; @Id Integer empAge; } </pre> </div> </div> <div id="wmqeeuq" class="section"> <a name="MapKey"> </a> <h2>MapKey</h2> <p>在一对多Q多对多关系中,我们可以用Map来保存集合对象。默认用主键值做keyQ如果用复合主键,则用id class的实例做keyQ如果指定了name属性,q指定的field的值做key?/p> <p>元数据属性说明:</p> <ul> <li>name: 用来做key的field名字 </li> </ul> <p>下面的代码说明Person和Book之间是一对多关系。Person的books字段是MapcdQ用Book的isbn字段的g为Map的key?/p> <div id="wmqeeuq" class="source"> <pre> @Table(name = "PERSON") public class Person { @OneToMany(targetEntity = Book.class, cascade = CascadeType.ALL, mappedBy = "person") @MapKey(name = "isbn") private Map<String, Book> books = new HashMap<String, Book>(); } </pre> </div> </div> <div id="wmqeeuq" class="section"> <a name="OrderBy"> </a> <h2>OrderBy</h2> <p>在一对多Q多对多关系中,有时我们希望从数据库加蝲出来的集合对象是按一定方式排序的Q这可以通过OrderBy来实玎ͼ默认是按对象的主键升序排列?/p> <p>元数据属性说明:</p> <ul> <li>value: 字符串类型,指定排序方式。格式ؓ"fieldName1 [ASC|DESC],fieldName2 [ASC|DESC],......",排序cd可以不指定,默认是ASC?</li> </ul> <p>下面的代码说明Person和Book之间是一对多关系。集合books按照Book的isbn升序Qname降序排列?/p> <div id="wmqeeuq" class="source"> <pre> @Table(name = "MAPKEY_PERSON") public class Person { @OneToMany(targetEntity = Book.class, cascade = CascadeType.ALL, mappedBy = "person") @OrderBy(name = "isbn ASC, name DESC") private List<Book> books = new ArrayList<Book>(); } </pre> </div> </div> <div id="wmqeeuq" class="section"> <a name="PrimaryKeyJoinColumn"> </a> <h2>PrimaryKeyJoinColumn</h2> <p>在三U情况下会用到PrimaryKeyJoinColumn? </p> <ul> <li>l承(详见<a ><font color="#002c99">Inheritance</font></a>)? </li> <li>entity class映射C个或多个从表。从表根据主表的主键列(列名为referencedColumnName值的列)Q徏立一个类型一L主键列,列名由name属性定义? </li> <li>one2one关系Q关pȝ护端的主键作为外键指向关p被l护端的主键Q不再新Z个外键列(?a ><font color="#002c99">JoinColumn</font></a>不同)?</li> </ul> <p> </p> <p>元数据属性说明:</p> <ul> <li>name:列名? </li> <li>referencedColumnName:该列引用列的列名 </li> <li>columnDefinition: 定义时创建此列的DDL </li> </ul> <p>下面的代码说明Customer映射C个表Q主表CUSTOMER,从表CUST_DETAILQ从表需要徏立主键列CUST_IDQ该列和主表的主键列id除了列名不同Q其他定义一栗?</p> <div id="wmqeeuq" class="source"> <pre> @Entity @Table(name="CUSTOMER") @SecondaryTable(name="CUST_DETAIL",pkJoin=@PrimaryKeyJoinColumn(name="CUST_ID"QreferencedColumnName="id")) public class Customer { @Id(generate = GeneratorType.AUTO) public Integer getId() { return id; } } </pre> </div> <p>下面的代码说明Employee和EmployeeInfo是一对一关系QEmployee的主键列id作ؓ外键指向EmployeeInfo的主键列INFO_ID?</p> <div id="wmqeeuq" class="source"> <pre> @Table(name = "Employee") public class Employee { @OneToOne @PrimaryKeyJoinColumn(name = "id", referencedColumnName="INFO_ID") EmployeeInfo info; } </pre> </div> </div> <div id="wmqeeuq" class="section"> <a name="PrimaryKeyJoinColumns"> </a> <h2>PrimaryKeyJoinColumns</h2> <p>如果entity class使用了复合主键,指定单个PrimaryKeyJoinColumn不能满要求Ӟ可以用PrimaryKeyJoinColumns来定义多个PrimaryKeyJoinColumn?</p> <p>元数据属性说明:</p> <ul> <li>value: 一个PrimaryKeyJoinColumn数组Q包含所有PrimaryKeyJoinColumn?</li> </ul> <p>下面的代码说明了Employee和EmployeeInfo是一对一关系。他们都使用复合主键Q徏表时需要在Employee表徏立一个外键,从Employee的主键列id,name指向EmployeeInfo的主键列INFO_ID和INFO_NAME. </p> <div id="wmqeeuq" class="source"> <pre> @Entity @IdClass(EmpPK.class) @Table(name = "EMPLOYEE") public class Employee { private int id; private String name; private String address; @OneToOne(cascade = CascadeType.ALL) @PrimaryKeyJoinColumns({ @PrimaryKeyJoinColumn(name="id", referencedColumnName="INFO_ID"), @PrimaryKeyJoinColumn(name="name" , referencedColumnName="INFO_NAME")}) EmployeeInfo info; } @Entity @IdClass(EmpPK.class) @Table(name = "EMPLOYEE_INFO") public class EmployeeInfo { @Id @Column(name = "INFO_ID") private int id; @Id @Column(name = "INFO_NAME") private String name; } </pre> </div> </div> <div id="wmqeeuq" class="section"> <a name="Transient"> </a> <h2>Transient</h2> <p>Transient用来注释entity的属性,指定的这些属性不会被持久化,也不会ؓq些属性徏表?/p> <div id="wmqeeuq" class="source"> <pre> @Transient private String name; </pre> </div>  </div> <div id="wmqeeuq" class="section"> <a name="Version"> </a> <h2>Version</h2> <p>Version指定实体cd乐观事务中的version属性。在实体c重新由EntityManager理q且加入C观事务中Ӟ保证完整性。每一个类只能有一个属性被指定为versionQversion属性应该映到实体cȝ主表上?/p> <p>下面的代码说明versionNum属性作个类的versionQ映到数据库中主表的列名是OPTLOCK?/p> <div id="wmqeeuq" class="source"> <pre> @Version @Column("OPTLOCK") protected int getVersionNum() { return versionNum; } </pre> </div> </div> <div id="wmqeeuq" class="section"> <a name="Lob"> </a> <h2>Lob</h2> <p>Lob指定一个属性作为数据库支持的大对象cd在数据库中存储。用LobTypeq个枚D来定义Lob是二q制cdq是字符cd?/p> <p>LobType枚Dcd说明Q?/p> <ul> <li>BLOB 二进制大对象QByte[]或者Serializable的类型可以指定ؓBLOB? </li> <li>CLOB 字符型大对象Qchar[]、Character[]或Stringcd可以指定为CLOB?</li> </ul> <p>元数据属性说明:</p> <ul> <li>fetchQ?定义q个字段是lazy loadedq是eagerly fetched。数据类型是FetchType枚DQ默认ؓLAZY,即lazy loaded. </li> <li>typeQ?定义q个字段在数据库中的JDBC数据cd。数据类型是LobType枚DQ默认ؓBLOB?</li> </ul> <p>下面的代码定义了一个BLOBcd的属性和一个CLOBcd的属性?/p> <div id="wmqeeuq" class="source"> <pre> @Lob @Column(name="PHOTO" columnDefinition="BLOB NOT NULL") protected JPEGImage picture; @Lob(fetch=EAGER, type=CLOB) @Column(name="REPORT") protected String report; </pre> </div> </div> <div id="wmqeeuq" class="section"> <a name="JoinTable"> </a> <h2>JoinTable</h2> <p>JoinTable在many-to-many关系的所有者一边定义。如果没有定义JoinTableQ用JoinTable的默认倹{?/p> <p>元数据属性说明:</p> <ul> <li>table:q个join table?a ><font color="#002c99">Table</font></a>定义? </li> <li>joinColumns:定义指向所有者主表的外键列,数据cd?a ><font color="#002c99">JoinColumn</font></a>数组? </li> <li>inverseJoinColumns:定义指向非所有者主表的外键列,数据cd?a ><font color="#002c99">JoinColumn</font></a>数组?</li> </ul> <p>下面的代码定义了一个连接表CUST和PHONE的join table。join table的表名是CUST_PHONEQ包含两个外键,一个外键是CUST_IDQ指向表CUST的主键IDQ另一个外键是PHONE_IDQ指向表PHONE的主键ID?/p> <div id="wmqeeuq" class="source"> <pre> @JoinTable( table=@Table(name=CUST_PHONE), joinColumns=@JoinColumn(name="CUST_ID", referencedColumnName="ID"), inverseJoinColumns=@JoinColumn(name="PHONE_ID", referencedColumnName="ID") ) </pre> </div> </div> <div id="wmqeeuq" class="section"> <a name="TableGenerator"> </a> <h2>TableGenerator</h2> <p>TableGenerator定义一个主键值生成器Q在<a ><font color="#002c99">Id</font></a>q个元数据的generateQTABLEӞgenerator属性中可以使用生成器的名字。生成器可以在类、方法或者属性上定义?/p> <p>生成器是为多个实体类提供q箋的ID值的表,每一行ؓ一个类提供ID|ID值通常是整数?/p> <p>元数据属性说明:</p> <ul> <li>name:生成器的唯一名字Q可以被Id元数据用? </li> <li>table:生成器用来存储id值的<a ><font color="#002c99">Table</font></a>定义? </li> <li>pkColumnName:生成器表的主键名U? </li> <li>valueColumnName:生成器表的ID值的列名U? </li> <li>pkColumnValue:生成器表中的一行数据的主键倹{? </li> <li>initialValue:id值的初始倹{? </li> <li>allocationSize:id值的增量?</li> </ul> <p>下面的代码定义了两个生成器empGen和addressGenQ生成器的表是ID_GEN?/p> <div id="wmqeeuq" class="source"> <pre> @Entity public class Employee { ... @TableGenerator(name="empGen", table=@Table(name="ID_GEN"), pkColumnName="GEN_KEY", valueColumnName="GEN_VALUE", pkColumnValue="EMP_ID", allocationSize=1) @Id(generate=TABLE, generator="empGen") public int id; ... } @Entity public class Address { ... @TableGenerator(name="addressGen", table=@Table(name="ID_GEN"), pkColumnValue="ADDR_ID") @Id(generate=TABLE, generator="addressGen") public int id; ... } </pre> </div> </div> <div id="wmqeeuq" class="section"> <a name="SequenceGenerator"> </a> <h2>SequenceGenerator</h2> <p>SequenceGenerator定义一个主键值生成器Q在<a ><font color="#002c99">Id</font></a>q个元数据的generator属性中可以使用生成器的名字。生成器可以在类、方法或者属性上定义。生成器是数据库支持的sequence对象?/p> <p>元数据属性说明:</p> <ul> <li>name:生成器的唯一名字Q可以被Id元数据用? </li> <li>sequenceName:数据库中Qsequence对象的名U。如果不指定Q会使用提供商指定的默认名称? </li> <li>initialValue:id值的初始倹{? </li> <li>allocationSize:id值的增量?</li> </ul> <p>下面的代码定义了一个用提供商默认名称的sequence生成器?/p> <div id="wmqeeuq" class="source"> <pre> @SequenceGenerator(name="EMP_SEQ", allocationSize=25) </pre> </div> </div> <div id="wmqeeuq" class="section"> <a name="DiscriminatorColumn"> </a> <h2>DiscriminatorColumn</h2> <p>DiscriminatorColumn定义在用SINGLE_TABLE或JOINEDl承{略的表中区别不l承层次的列?/p> <p>元数据属性说明:</p> <ul> <li>name:column的名字。默认gؓTYPE? </li> <li>columnDefinition:生成DDL的sql片断? </li> <li>length:Stringcd的column的长度,其他cd使用默认?0?</li> </ul> <p>下面的代码定义了一个列名ؓDISCQ长度ؓ20的Stringcd的区别列?/p> <div id="wmqeeuq" class="source"> <pre> @Entity @Table(name="CUST") @Inheritance(strategy=SINGLE_TABLE, discriminatorType=STRING, discriminatorValue="CUSTOMER") @DiscriminatorColumn(name="DISC", length=20) public class Customer { ... } </pre> </div> </div> </div> <img src ="http://www.aygfsteel.com/liaojiyong/aggbug/56221.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/liaojiyong/" target="_blank">liaojiyong</a> 2006-07-03 00:53 <a href="http://www.aygfsteel.com/liaojiyong/archive/2006/07/03/56221.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3.0之映(转)http://www.aygfsteel.com/liaojiyong/archive/2006/07/03/56220.htmlliaojiyongliaojiyongSun, 02 Jul 2006 16:52:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2006/07/03/56220.htmlhttp://www.aygfsteel.com/liaojiyong/comments/56220.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2006/07/03/56220.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/56220.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/56220.html一对一映射

双向一对一关系需要在关系l护端(owner sideQ的one2one Annotition定义mappedBy属性。徏表时在关p被l护端(inverse sideQ徏立外键列指向关系l护端的主键列?/p>

假设Country ?Capital 是双向一对一的关p,具体元数据声明如?

				
public class Country {
	@OneToOne(optional = true,cascade = CascadeType.ALL, mappedBy = "country")
	private Capital capital;
}

public class Capital {
	@OneToOne(optional = false, cascade = CascadeType.ALL)
	@JoinColumn(name = "COUNTRY_ID", referencedColumnName = "id")
	private Country country;
                
			

代码中元数据的说明:

元数据描q?

@OneToOne(optional = true,cascade = CascadeType.ALL, mappedBy = "country")

optional声明关系是否是必d在的Q即是否允许其中一端ؓnull?/p>

cascade声明U联操作?/p>

@JoinColumn(name = "COUNTRY_ID", referencedColumnName = "id")

name声明外键列的名字QreferencedColumnName声明外键指向列的列名?br />

一对多映射

双向一对多关系Q一是关pȝ护端Qowner sideQ,多是关系被维护端Qinverse sideQ?时在关系被维护端建立外键列指向关pȝ护端的主键列?/p>

假设Father ?Child 是双向一对多的关p,具体元数据声明如?

				
public class Father {
	@OneToMany(targetEntity = Child.class, cascade = CascadeType.ALL, mappedBy = "father")
	public List<Child> getChildren() {
		return children;
	}
}

public class Child {
	@ManyToOne
	@JoinColumn(name = "FATHER_ID", referencedColumnName = "id")
	public Father getFather() {
		return father;
	}
}

                
			

代码中元数据的说明:

元数据描q?

@OneToMany(targetEntity = Child.class, cascade = CascadeType.ALL, mappedBy = "father")

targetEntity = Child.class表明关系另一端的实体cd

cascade声明U联操作?/p>

mappedBy声明关系l护端的字段QfieldQ名?/p>

@ManyToOne

@JoinColumn(name = "FATHER_ID", referencedColumnName = "id")

name声明外键列的名字QreferencedColumnName声明外键指向列的列名?br />

多对多映?/h2>

多对多映采取中间表q接的映策略,建立的中间表分别引入两边的主键作ؓ外键?/p>

EJB3对于中间表的元数据提供了可配|的方式Q用户可以自定义中间表的表名Q列名?/p>

假设Teacher ?Student是多对多的关p,具体元数据声明如?

				
pubic class Teacher{
	@ManyToMany(targetEntity = Student.class, cascade = CascadeType.PERSIST)
	@JoinTable(table = @Table(name = "M2M_TEACHER_STUDENT"),
        joinColumns = @JoinColumn(name = "TEACHER_ID", referencedColumnName = "ID"),
        inverseJoinColumns = @JoinColumn(name = "STUDENT_ID", referencedColumnName = "ID"))
	public List<Student> getStudents() {return students;}
					
}
public class Student{
	@ManyToMany(targetEntity = Teacher.class, mappedBy = "students")
	public List<Teacher> getTeachers() {
		return teachers;
	}
}
			
			

代码中元数据的说明:

元数据描q?

@ManyToMany(targetEntity = Student.class, cascade = CascadeType.PERSIST)

targetEntity = Student.class表明关系另一端的实体cd。cascade声明U联操作?/p>

@JoinTable(table = @Table(name = "M2M_TEACHER_STUDENT"),

joinColumns = @JoinColumn(name = "TEACHER_ID", referencedColumnName = "ID"),

inverseJoinColumns = @JoinColumn(name = "STUDENT_ID", referencedColumnName = "ID"))

JoinTable配置中间表信息,它由3个部分组?

1) table = @Table(name = "M2M_TEACHER_STUDENT") ,声明中间表的名字

2Q?joinColumns Q定义中间表与关pȝ护端的外键关pR?/p>

3Q?inverseJoinColumnsQ定义中间表与inverse端的外键关系.

Inheritance strategy

EJB3规定了三U基本的l承映射{略Q?/p>

.每个cd层结构一张表(table per class hierarchy)

.每个子类一张表(table per subclass)

.每个具体cM张表(table per concrete class)

在我们提供的Alpha版本中仅支持W一U映策略,x个类层次一个表。我们将在下一个版本中提供每个具体cM张表的支持, 考虑到性能Q这两个映射{略也是推荐的映策?

每个cd层结构一张表(Table per class hierarchy)

假设有这么一个承类层次:Employee,两个子类FullTimeEmployee,PartTimeEmployee 源代码如下所C?
				
@Entity
@Table( name="inheritance_Employee" )
@Inheritance(strategy=InheritanceType.SINGLE_TABLE,
		discriminatorType=DiscriminatorType.STRING,
		discriminatorValue="employee")
public class Employee {...}
					
@Entity
@Inheritance(discriminatorValue="fullTimeEmp")
public class FullTimeEmployee extends Employee {...}

@Entity
@Inheritance(discriminatorValue="partTimeEmp")
public class PartTimeEmployee extends Employee {...}
                
			

代码中元数据的说明:

基类中元数据描述:

@Inheritance(strategy=InheritanceType.SINGLE_TABLE,

discriminatorType=DiscriminatorType.STRING,discriminatorValue="employee")

strategy=InheritanceType.SINGLE_TABLE表示l承映射采用W一U映策略?/p>

discriminatorType=DiscriminatorType.STRING表示l承层次中类型识别列cd为String.

discriminatorValue="employee" 表示此类对应的类型识别码为employee.



liaojiyong 2006-07-03 00:52 发表评论
]]>EJB3 QL查询(?http://www.aygfsteel.com/liaojiyong/archive/2006/07/02/56216.htmlliaojiyongliaojiyongSun, 02 Jul 2006 15:35:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2006/07/02/56216.htmlhttp://www.aygfsteel.com/liaojiyong/comments/56216.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2006/07/02/56216.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/56216.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/56216.html

EJB3 QL查询

EJB3的查询语a是一U和SQL非常cM的中间性和对象化查询语a。它可以被编译成不同的底层数据库能接受的SQLQ从而屏蔽不同数据库的差异,保用EJB3 QL查询语言~写的代码可在不同的数据库上q行。比起EJB 2.1的查询语aQEJB3可以q行期构造,支持多态,q远比EJB 2.1的查询更灉|和功能强大。在E序中用EJB3 QL可以使用大写(SELECT)或者小?select)Q但不要大小?比如:Select)混合使用?/p>   

Query接口

javax.persistence.Query是EJB3查询操作的接口。进行查询,首先要通过EntityManager 获得Query对象?/p>

                
    public Query createQuery(String ejbqlString);                 
                
            

下面我们做一个最单的查询Q查询所有的com.redsoft.samples.OrdercR?/p>

                
    final Query query = entityManager.createQuery( "select o from Order o"); 
    final List result = query.getResultList();
    final Iterator iterator = result.iterator();
    while( iterator.hasNext() ){
        // 处理Order
    }
                
            

注意"from Order"?Order"在EJB3查询中称为com.redsoft.samples.Ordercȝabstract schema Type。查询Entity在EJB3 QL中都是针对Entity的Abstract Schema Typeq行查询?在同一个EntityManagerFactory中,不允许同时有两个Abstract Schema Type相同的EntitycR比如不允许同时有com.redsoft.samples.Order和com.redsoft.foo.Order。  

Queryq回一个List的集合结果,我们可以用Iterator或者List.get( int )的方法来获得每个W合条g的Entity。Liberator EJB3 Persistenceq行环境的Query查询 在构造Query的时候的只是把EJB3 QL~译成相应的SQLQ但q不执行。只有当应用代码W一ơ调用Iterator.next(),Iterator.hasNext()或者List.get( int )Ҏ(gu)的时?~译后的SQL才会被真正的执行?

在Liberator EJB3 Persistenceq行环境q回的结果集合中Qƈ不保存所有的l果Q而只是保持一个指向JDBC ResultSet或者缓存ResultSet的一个行(row)指针。只有当用户实需要获得Entity实例的时候,才会从ResultSet中获取数据ƈ填充到Entity实例中返回给应用?

如果查询l果l合中包含所有符合条件的Entity, Liberator EJB3 Persistenceq行环境默认会自动缓存每ơ查询的l果。这样下ơ同L查询操作无需讉K数据库,而直接从~存中返回结果集合。但如果在下ơ查询操作之前,有针对被~存的Entityc进行update/insert/delete操作Q则~存的结果集合会自动被清I,q样下次查询׃从数据库获得数据Q?保查询L获得正确的结果,避免~存脏数据?/p>

有时候查询会q回量的数据。Liberator EJB3q行环境采用了自适应的弱引用POJO理机制Q可以处理v量的数据。在我们的测试中和客L环境可以处千万别的数据量。但在处理大数据量的时候,注意关闭寚w合结果的~存?/p>

                
    
    // 假设q回的结果数量巨?
    final Query query = entityManager.createQuery( "select o from Order o");
    
    // 关闭Ҏ(gu)询结果的~存
    query.setHint( Constants.QUERY_RESULT_CACHE, "false");
    final List result = query.getResultList();
    final Iterator iterator = result.iterator();
    
    // q里我们可以处理量的数?
    while( iterator.hasNext() ){
        // 处理Order
    }
                
            
  
注意条g语句中查询的是Entity的属性,属性的名字需要和Entity中的属性变量名字一致?

使用参数查询

参数查询也和SQL中的参数查询cM。EJB3 QL支持两种方式的参数定义方? 命名参数和位|参数。在同一个查询中只允怋用一U参数定义方式?/p>命名参数:

                
    final Query query = entityManager.createQuery( "select o from Order o where o.id = :myId");
    
    // 讄查询中的参数
    query.setParameter( "myId", 2 );
    
    
    // 可以使用多个参数
    final Query query = entityManager.createQuery( "select o from Order o where o.id = :myId and o.customer = :customerName" );
        
    // 讄查询中的参数
    query.setParameter( "myId", 2 );
    query.setParameter( "customerName", "foo" );
              
    
注意不允许在同一个查询中使用两个相同名字的命名参数?

位置参数Q?

                
    final Query query = entityManager.createQuery( "select o from Order o where o.id = ?1");
    
    // 讄查询中的参数
    query.setParameter( 1, 2 );// 1表示W一个参敎ͼ2是参数的?
    
    //或?
    final Query query = entityManager.createQuery( "select o from Order o where o.id = ?1").setParameter( 1, 2 );
        
    
    // 可以使用多个参数
    final Query query = entityManager.createQuery( "select o from Order o where o.id = ?1 and o.customer = ?2" );
        
    // 讄查询中的参数
    query.setParameter( 1, 2 );
    query.setParameter( 2, "foo" );
              
    
如果在未来需要在不同的EJB3 q行环境中运行,请用位|参敎ͼ保证应用是可UL的?

排序(order by)

下面是一个简单查询的例子Q可以看到和SQL的用方法很cM?ASC"?DESC"分别为升序和降序Q如果不昑ּ注明QEJB3 QL中默认ؓasc升序?
                
    // 不注明的话,默认为asc为升?               
    final Query query = entityManager.createQuery( "select o from Order o order by o.id");
    
    final Query query = entityManager.createQuery( "select o from Order o order by o.address.streetNumber desc");// desc为降?
    
    final Query query = entityManager.createQuery( "select o from Order o order by o.id, o.address.streetNumber");
            
    

查询中用构造器(Constructor)

EJB3 QL支持查询的属性结果直接作Z个java class的构造器参数Qƈ产生实体作ؓl果q回?
                
    // 我们把需要的三个属性作Z个class( OrderHolder )的构造器参数Qƈ使用new函数?               
    Query query = entityManager.createQuery("select new com.redsoft.ejb3.dummy.OrderHolder (   o.id, o.vender, o.partNumber  )  FROM Order AS o");
    
    // 集合中的l果是OrderHolder
    List result = query.getResultList();
            
         
    
该java class不需要是Entity Class?strong>NEW
要求java class使用全名?

聚合查询(Aggregation)

象大部分的SQL一?EJB3 QL也支持查询中的聚合函数。目前EJB QL支持的聚合函数包括:

  • AVG
  • SUM
  • COUNT
  • MAX
  • MIN
                    
                    
    final Query query = entityManager.createQuery( "select MAX( o.id ) from Order where o.customerName='foo'");
        
    // 如果我们知道l果是单个,我们可以用getSingleResult()获得l果
    final Object result = query.getSingleResult();
        
    // ׃Order中id的类型ؓlong,
    final Long max = (Long)result;
        
        
    // 在一些数据库中max函数q回的结果的cd不一定于id对应的列的类型相W,更安全的方式可以采用string来{?
    fina long max = Long.parseLong( result.toString() );
                
        
聚合函数也可以作查询的一个属性返回?
                    
    
    // q回所有的订单的生产厂商和他们的订单h(hun)值总额
    final Query query 
        = entityManager.createQuery( "select o.vender, sum(o.amount) FROM Order o group by o.vender");");
                
        

和SQL一P如果聚合函数不是select...from的唯一一个返回列Q需要?GROUP BY"语句?GROUP BY"应该包含select语句中除了聚合函数外的所有属性?/p>

                    
    
    // q回所有的订单的生产厂商的的名字,货物L和每U货物的订单价值总额
    // 注意group by后面必须包含o.vender和o.partNumber
    final Query query 
        = entityManager.createQuery( "select o.vender, o.partNumber, sum(o.amount) FROM Order o group by o.venderQo.partNumber");
                
        

如果q需要加上查询条Ӟ需要?HAVING"条g语句而不?WHERE"语句?/p>

                    
    
    // q回所有的订单的生产厂商是"foo"的货物号码和每种货物的订单h(hun)值总额
    // q里"having o.vender = 'foo'为条?
    final Query query 
        = entityManager.createQuery( "select o.vender, o.partNumber, sum(o.amount) FROM Order o 
            group by o.venderQo.partNumber having o.vender='foo'");
        
        

?HAVING"语句里可以跟"WHERE"语句一样用参数?/p>

                    
    
    // q回所有的订单的生产厂商是"foo"的货物号码和每种货物的订单h(hun)值总额
    // q里"having o.vender = 'foo'为条?
    final Query query 
        = entityManager.createQuery( "select o.vender, o.partNumber, sum(o.amount) FROM Order o 
            group by o.venderQo.partNumber having o.vender=?1");
    query.setParameter( 1, "foo" );
    final List result = query.getResultList();
        
        

兌(join)

在EJB3 QL中,大部分的情况下,使用对象属性都隐含了关?join)。例如在以下查询中:

                
    final Query query = entityManager.createQuery( "select o from Order o
         where o.address.streetNumber=2000 order by o.id");
   
            
    
当这个句EJB3 QL~译成以下的SQL时就会自动包含了兌,EJB3 QL~译成SQL时关联默认取左关?left join)?
    
    select o.id, o.vender, o.partNumber, o.amount, addressTable.id, addressTable.streetNumber 
        from orderTable as o left join addressTable where addressTable.streetNumber = 2000
      
    

但在一些情况下Q我们仍焉要对兌做精的控制。因此EJB3 QL仍然支持和SQL中类似的兌语法Q?/p>

  • left out join/left join
  • inner join
  • left join/inner join fetch

left join, left out join{义Q都是允许符合条件的双表达式中的Entiies为空?/p>

                
    // q回所有地址?000的OrderU录Q不Order中是否有OrderItem                
    final Query query = entityManager.createQuery( "select o from Order o
         left join o.orderItems where o.address.streetNumber=2000 order by o.id");
   
                
    

׃EJB3 QL默认采用left join。这L查询和以下的EJB3 QL其实是等L?/p>

                
    // q回所有地址?000的OrderU录Q不Order中是否有OrderItem                
    final Query query = entityManager.createQuery( "select o from Order o
          where o.address.streetNumber=2000 order by o.id");
   
                
    

需要显式用left join/left outer join的情况会比较?yu)?/p>

inner join要求双的表辑ּ必须q回Entities?/p>

                
    // q回所有地址?000的OrderU录QOrder中必LOrderItem                
    final Query query = entityManager.createQuery( "select o from Order o
         inner join o.orderItems where o.address.streetNumber=2000 order by o.id");
   
                
    

left/left out/inner join fetch提供了一U灵zȝ查询加蝲方式来提高查询的性能。在默认的查询中QEntity中的集合属性默认不会被兌Q集合属性默认是~加? lazy-load )?/p>

                
                
``` // 默认EJB3 QL~译后不兌集合属性变?orderItems)对应的表                
    final Query query = entityManager.createQuery( "select o from Order o
         inner join o.orderItems where o.address.streetNumber=2000 order by o.id");
    final List result = query.getResultList();
    
    // q时获得Order实体中orderItems( 集合属性变?)为空
    final Order order = (Order)result.get( 0 )
    
    // 当应用需要时QEJB3 Runtime才会执行一条SQL语句来加载属于当前Order的OrderItems
    Collection orderItems = order.getOrderItems();
   
                
    

q样的查询性能上有不的地斏Vؓ了查询N个OrderQ我们需要一条SQL语句获得所有的Order的原?对象属性, 但需要另外N条语句获得每个Order的orderItems集合属性。ؓ了避免N+1的性能问题Q我们可以利用join fetch一ơ过用一条SQL语句把Order的所有信息查询出来?/p>

                
    // q回所有地址?000的OrderU录QOrder中必LOrderItem                
    final Query query = entityManager.createQuery( "select o from Order o
         inner join fetch o.orderItems where o.address.streetNumber=2000 order by o.id");
   
             
    

׃使用了fetch,q个查询只会产生一条SQL语句Q比原来需要N+1条SQL语句在性能上有了极大的提升?/p>

比较Entity

在查询中使用参数查询Ӟ参数cd除了String, 原始数据cd( int, double{?和它们的对象cd( Integer, Double{?,也可以是Entity的实例?/p>

                
    final Query query = entityManager.createQuery( "select o from Order o where o.address = ?1 order by o.id");
    
    final Address address = new Address( 2001, "foo street", "foo city", "foo province" );
    
    // 直接把address对象作ؓ参数?
    query.setParameter( 1, address );
  
             
    

扚w更新(Batch Update)

EJB3 QL支持扚w更新?/p>

                
   Query query = managerNew.createQuery("update Order as o set o.vender=:newvender,  o.partNumber='fooPart' where o.vender = 'foo'");
   query.setParameter("newvender", "barVender");
   
   // update的记录数
   int result = query.executeUpdate();
            
    

扚w删除(Batch Remove)

EJB3 QL支持扚w删除?/p>

                
    Query query = managerNew.createQuery("DELETE FROM Order");
    int result = query.executeUpdate();
                
    Query query = managerNew.createQuery("DELETE FROM Order AS o WHERE o.vender='redsoft'");
    int result = query.executeUpdate();            
    
    
    
    

使用操作WNOT

                
                
    // 查询所有vender不等?foo"的Order                
    Query query = managerNew.createQuery("SELECT FROM Order AS o WHERE not(o.vender='foo')");
    List result = query.getResultList();
                
    // 删除所有vender不等?foo"的Order
    Query query = managerNew.createQuery("DELETE FROM Order AS o WHERE not(o.vender='foo')");
    int result = query.executeUpdate();            
    

使用操作WBETWEEN

                
                
    // 查询所有h(hun)值amount在5?0之间?包含5,10)的Order               
    Query query = managerNew.createQuery("select o FROM Order AS o left join o.orderItems ot where o.amount BETWEEN 5 AND 10 order by o.vender desc");
    List result = query.getResultList();
         
    

使用操作WIN

                
    // 查询所有vender?foo1", "foo2"或?foo3"的Order                
    Query query = managerNew.createQuery("select o FROM Order AS o left join o.orderItems ot where o.vender in ( 'foo1', 'foo2', 'foo3' ) order by o.vender desc");
    List result = query.getResultList();
                        
         
    

使用操作WLIKE

                
    // 查询所有vender以字W串"foo"开头的Order                
    Query query = managerNew.createQuery("select o FROM Order as o where o.vender like 'foo%' order by o.vender desc");
    List result = query.getResultList();
    
    
    // 查询所有vender以字W串"foo"l尾的Order                
    Query query = managerNew.createQuery("select o FROM Order as o where o.vender like '%foo' order by o.vender desc");
    List result = query.getResultList();
    
    
    // 可以l合NOT一起用,比如查询所有vender不以以字W串"foo"l尾的Order                
    Query query = managerNew.createQuery("select o FROM Order as o where o.vender not like '%foo' order by o.vender desc");
    List result = query.getResultList();
    
    // 可以l合escape使用Q比如查询所有vender?foo"开始的Orderq忽?3'字符?
    // 如果vender?foo1", "foo2", "foo3"W合q个条g, 另外"3foo1", "f3oo4"也符合条件?
    Query query = managerNew.createQuery("select o FROM Order as o where o.vender like '%foo' escape '3' order by o.vender desc");
    List result = query.getResultList();
    
    
                        
         
    

使用操作WIS NULL

                
    // 查询所有没有地址的Order                
    Query query = managerNew.createQuery("select o FROM Order as o where o.address is null");
    List result = query.getResultList();
    
    // 查询所有地址非空的Order 
    Query query = managerNew.createQuery("select o FROM Order as o where o.address is not null");
    List result = query.getResultList();
    
                        
         
    

使用操作WIS EMPTY

IS EMPTY是针寚w合属?Collection)的操作符。可以和NOT一起用?/p>

                
    // 查询orderItems集合为空的Order                
    Query query = managerNew.createQuery("select o FROM Order o where o.orderItems is empty by o.vender desc");
    List result = query.getResultList();
    
   // 查询orderItems集合非空的Order                
    Query query = managerNew.createQuery("select o FROM Order o where o.orderItems is not empty by o.vender desc");
    List result = query.getResultList();                     
         
    

使用操作WEXISTS

[NOT]EXISTS需要和子查询配合用?/p>

                
    Query query = manager.createQuery("select o FROM Order o where exists (select o from Order o where o.partNumber=?1) order by o.vender desc");
    query.setParameter(1, "partNumber");
    
    
    Query query = manager.createQuery("select o FROM Order o where o.vender='partNumber' and not exists (select o from Order o where o.partNumber=?1) order by o.vender desc");
    query.setParameter(1, "partNumber");
         
    

使用操作WALL/SOME/ANY

                
    Query query = managerNew.createQuery("select emp from EmployeeA emp where emp.salary > all ( select m.salary from Manager m where m.department = emp.department)");
    List result = query.getResultList();
    
    Query query = managerNew.createQuery("select emp from EmployeeA emp where emp.salary > any ( select m.salary from Manager m where m.department = emp.department)");
    List result = query.getResultList();
    
    Query query = managerNew.createQuery("select emp from EmployeeA emp where emp.salary > some ( select m.salary from Manager m where m.department = emp.department)");
    List result = query.getResultList();
         
    

计算函数

EJB3 QL中定义的计算函数包括Q?/p>

  • ABS l对?
  • SQRT qx?
  • MOD 取余?
  • SIZE 取集合的数量
       
    Query query = entityManager.createQuery("select o.vender, size( o.orderItems ) FROM Order o  where o.owner.firstName = 'charles' group by o.vender order by o.vender desc");
    List result = query.getResultList();
    
    // 函数也可以用在条件中
    Query query = managerNew.createQuery("select o.vender, sum(o.amount) FROM Order AS o left join o.orderItems ot group by o.vender having size(o.orderItems) = 0 or lower( o.vender ) = 'foo' order by o.vender desc");
    List result = query.getResultList();

    
    // 取余?
    Query query = managerNew.createQuery("select mod( o.owner.info.age, 10 ) FROM Order o where exists ( select o from Order o where o.partNumber= :name ) and o.vender='order1' and exists ( select o from Order o where o.amount= :name1 ) order by o.vender desc");
        
         
    


liaojiyong 2006-07-02 23:35 发表评论
]]>使用EJB3.O化EJB开发(全中文)Q{Q?/title><link>http://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55919.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Fri, 30 Jun 2006 03:49:00 GMT</pubDate><guid>http://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55919.html</guid><wfw:comment>http://www.aygfsteel.com/liaojiyong/comments/55919.html</wfw:comment><comments>http://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55919.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/liaojiyong/comments/commentRss/55919.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/liaojiyong/services/trackbacks/55919.html</trackback:ping><description><![CDATA[     摘要: 使用EJB3.O化EJB开发  ?原著QDebu Panda 我们引入EJB来构造分布式的组件。它诞生之时是ؓ了解x有CORBA的问题和复杂性。经历过几次重要的版本更新和增加许多Ҏ(gu)之后,EJB已经成ؓ了J2EE的核心。在早期Q很多开发h员沉q于EJB甚至在没有Q何意义的情况下在他们的工E中使用EJB。而当他们发现所使用的工Eƈ没有质的变化后,谴责EJB成了一U趋?..  <a href='http://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55919.html'>阅读全文</a><img src ="http://www.aygfsteel.com/liaojiyong/aggbug/55919.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/liaojiyong/" target="_blank">liaojiyong</a> 2006-06-30 11:49 <a href="http://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55919.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用EJB3.O化EJB开发(转)http://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55914.htmlliaojiyongliaojiyongFri, 30 Jun 2006 03:46:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55914.htmlhttp://www.aygfsteel.com/liaojiyong/comments/55914.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55914.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/55914.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/55914.html阅读全文

liaojiyong 2006-06-30 11:46 发表评论
]]>
W一个EJB3.0范例Q{Q?/title><link>http://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55909.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Fri, 30 Jun 2006 03:38:00 GMT</pubDate><guid>http://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55909.html</guid><wfw:comment>http://www.aygfsteel.com/liaojiyong/comments/55909.html</wfw:comment><comments>http://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55909.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/liaojiyong/comments/commentRss/55909.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/liaojiyong/services/trackbacks/55909.html</trackback:ping><description><![CDATA[     摘要: 2004 q? 7 月, EJB 专家委员会公布了新的 EJB3.0 规范草本? 2004 q? 10 ? 7 P JBoss 发布了支? EJB3.0 的第一个预览版? jboss-EJB-3.0_Preview_1 ...  <a href='http://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55909.html'>阅读全文</a><img src ="http://www.aygfsteel.com/liaojiyong/aggbug/55909.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/liaojiyong/" target="_blank">liaojiyong</a> 2006-06-30 11:38 <a href="http://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55909.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JBoss4中对EJB3.0支持的Hibernate3和数据源的配|(转)http://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55906.htmlliaojiyongliaojiyongFri, 30 Jun 2006 03:35:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55906.htmlhttp://www.aygfsteel.com/liaojiyong/comments/55906.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55906.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/55906.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/55906.html

JBoss4中对EJB3.0支持的Hibernate3和数据源的配|?/strong>

    JBoss EJB3.0 建立?span lang="EN-US">Hibernate 3.0之上。配|数据源你的实体bean需要创?span lang="EN-US">hibernate. Properties配置文g。在EJB 3.0部v包下有一个默认的hibernate配置文gejb3.deployer/META-INF/hibernate.properties?br />

    请参考我们附带的Hibernate 3.0的文档来了解如何配置hibernate.properties文g中的各个倹{这里只做一些说明?br />

hibernate.transaction.manager_lookup_class=org.hibernate.transaction.JBossTransactionManagerLookup

hibernate.hbm2ddl.auto=create-drop

hibernate.cache.provider_class=org.hibernate.cache.HashtableCacheProvider

hibernate.connection.datasource=java:/DefaultDS

hibernate.dialect=org.hibernate.dialect.HSQLDialect

    上面?span lang="EN-US">EJB3.0应用E序?span lang="EN-US">ejb3.deployer/META-INF/hibernate.properties默认的配|文?br />

hibernate.connection.datasource 指向JBoss数据源的JNDI?span lang="EN-US">

hibernate.dialect 默认?span lang="EN-US">Hypersonic SQLQ但是你可以改变为其他数据库方言?span lang="EN-US">Oracle。可以参?span lang="EN-US">Hibernate 3.0的文档?span lang="EN-US">

hibernate.hbm2ddl.auto=create-drop 建立部v中的数据库图表,q在取消部v的时候删除他们?span lang="EN-US">

hibernate.transaction.manager_lookup_class 定义?span lang="EN-US">Hibernates的事务管理。它一般不能改变?span lang="EN-US">

hibernate.cache.provider_class 定义?span lang="EN-US">Hibernate要使用的缓存结构。如果你在集中使用你也许要考虑JBoss的缓存?br />

每个部v?span lang="EN-US">Hibernate.properties文g

    你或讔R要替换默认的hibernate.properties文g。那么用上面提到的变量定义一个最配|来建立一个你自己?span lang="EN-US">hibernate.properties文g。然后将文g攑֜你得.ejb3 jar 目录下的META-INF/下或打入JAR包?/span>



liaojiyong 2006-06-30 11:35 发表评论
]]>
EJB3.0中JNDI的绑定和多通\传输Q{Q?/title><link>http://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55903.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Fri, 30 Jun 2006 03:30:00 GMT</pubDate><guid>http://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55903.html</guid><wfw:comment>http://www.aygfsteel.com/liaojiyong/comments/55903.html</wfw:comment><comments>http://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55903.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/liaojiyong/comments/commentRss/55903.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/liaojiyong/services/trackbacks/55903.html</trackback:ping><description><![CDATA[ <div id="wmqeeuq" class="postTitle"> <a > </a> </div> <div id="wmqeeuq" class="postText"> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align="left"> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">默认的会?span lang="EN-US">bean</span>会以路径或远E接口的全名l定?span lang="EN-US">JNDI</span>。你可以通过定义你自q<span lang="EN-US">@org.jboss.ejb3.LocalBinding</span>?span lang="EN-US">@org.jboss.ejb3.remoting.RemoteBinding</span>来修?span lang="EN-US"><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?><o:p></o:p></span></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan; mso-outline-level: 4" align="left"> <b> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">本地接口?span lang="EN-US">JNDI</span>l定<span lang="EN-US"><o:p></o:p></span></span> </b> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">使用<span lang="EN-US">org.jboss.ejb3.LocalBinding annotation</span>来改变你本地接口?span lang="EN-US">JNDI</span>名字?span lang="EN-US"><o:p></o:p></span></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">@Stateless<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">@LocalBinding(jndiBinding="custom/MySession")<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">public class MySessionBean implements MySession<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">{<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">}<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan; mso-outline-level: 4" align="left"> <b> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">q程接口?span lang="EN-US">JNDI</span>l定<span lang="EN-US"><o:p></o:p></span></span> </b> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">使用<span lang="EN-US">org.jboss.ejb3.RemoteBindings annotation</span>来改变你q程接口?span lang="EN-US">JNDI</span>名字?span lang="EN-US"><o:p></o:p></span></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">@Stateless<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">@RemoteBindings({@RemoteBinding(jndiName="custom/remote/MySession")})<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">public class MySessionBean implements MySession<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">{<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">}<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan; mso-outline-level: 4" align="left"> <b> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">多通\传输和客L拦截Q?span lang="EN-US">Multiple transports and Client Interceptors<o:p></o:p></span></span> </b> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan; mso-outline-level: 4" align="left"> <b> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">Q?span lang="EN-US"><o:p></o:p></span></span> </b> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align="left"> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">你可以通过<span lang="EN-US">JBoss Remoting</span>架构来展C个会?span lang="EN-US">bean</span>通过多通\传输的远E调用。现在仅仅一些插件支持。可以查?span lang="EN-US">JBoss</span>文档中怎样定义传?span lang="EN-US">MBean</span>。要展现一个会?span lang="EN-US">bean</span>通过多通\传输你需要用远E绑定注解?span lang="EN-US"><o:p></o:p></span></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> <o:p> </o:p> </span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">public @interface RemoteBinding<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">{<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> <span style="mso-spacerun: yes">   </span>String jndiBinding() default "";<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> <span style="mso-spacerun: yes">   </span>String interceptorStack() default "SessionBeanClientInterceptors";<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> <span style="mso-spacerun: yes">   </span>String clientBindUrl();<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> <span style="mso-spacerun: yes">   </span>Class factory() default org.jboss.ejb3.remoting.RemoteProxyFactory.class;<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">}<o:p></o:p></span> </p> <ul type="disc"> <li id="wmqeeuq" class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan; tab-stops: list 36.0pt; mso-list: l0 level1 lfo1"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">JNDI</span> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">l定指定了代理将捆绑?span lang="EN-US">JNDI</span>名字?span lang="EN-US"><o:p></o:p></span></span> </li> <li id="wmqeeuq" class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan; tab-stops: list 36.0pt; mso-list: l0 level1 lfo1"> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">拦截堆栈Q?span lang="EN-US">interceptorStack</span>Q允怽插入数据C?span lang="EN-US">JBoss AOP</span>Q栈l构Q。会?span lang="EN-US">bean</span>客户端拦截器Q?span lang="EN-US">SessionBeanClientInterceptors</span>Q栈可以在你部v得文件夹下的<span lang="EN-US">ejb3-interceptors-aop.xml</span>配置文g中找到?span lang="EN-US"><o:p></o:p></span></span> </li> <li id="wmqeeuq" class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan; tab-stops: list 36.0pt; mso-list: l0 level1 lfo1"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">clientBindUrl</span> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">定义了客L用来l定服务器的<span lang="EN-US">JBoss</span>q程<span lang="EN-US">URL</span>?span lang="EN-US"><o:p></o:p></span></span> </li> <li id="wmqeeuq" class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan; tab-stops: list 36.0pt; mso-list: l0 level1 lfo1"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">Factory</span> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">允许你ؓ你自׃理的<span lang="EN-US">bean</span>插入拦截。你通常不需要接触这些设|?span lang="EN-US"><o:p></o:p></span></span> </li> </ul> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan" align="left"> <span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">q里是一个例子:<span lang="EN-US"><o:p></o:p></span></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">@Stateless<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">@RemoteBindings({<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> <span style="mso-spacerun: yes">                 </span>@RemoteBinding(jndiName="custom/remote/MySession", <o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> <span style="mso-spacerun: yes">                                </span>interceptorStack="MyInterceptorStack", <o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> <span style="mso-spacerun: yes">                                </span>clientBindUrl="socket://foo.jboss.org:2222")<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"> <span style="mso-spacerun: yes">                </span>})<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">public class MySessionBean implements MySession<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">{<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"> <span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">}<o:p></o:p></span> </p> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> <span lang="EN-US" style="FONT-SIZE: 9pt"> <o:p> </o:p> </span> </p> </div> <img src ="http://www.aygfsteel.com/liaojiyong/aggbug/55903.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/liaojiyong/" target="_blank">liaojiyong</a> 2006-06-30 11:30 <a href="http://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55903.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>什么时候用EJB Q什么时候不用EJBQ?/title><link>http://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55899.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Fri, 30 Jun 2006 03:21:00 GMT</pubDate><guid>http://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55899.html</guid><wfw:comment>http://www.aygfsteel.com/liaojiyong/comments/55899.html</wfw:comment><comments>http://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55899.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/liaojiyong/comments/commentRss/55899.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/liaojiyong/services/trackbacks/55899.html</trackback:ping><description><![CDATA[ <h3> </h3> <p> </p> <p>参?Enterprise JavaBeans 4</p> <p>q篇文章 讲述了何时用EJBQ何时不用EJBQ以及用哪些可以替代EJBQ?/p> <p> <br /> <strong>1 When to Use EJBs<br /></strong>Here's a list of situations where EJBs are strong; we haven't distinguished between </p> <p>different types of EJBs.</p> <p> </p> <p> <br /> <strong>Single and multisystem business transactions</strong> </p> <p>The ability to maintain transactional integrity for complex business entities is one of </p> <p>an EJB's key strengths. EJBs aren't alone in providing straightforward transactional </p> <p>control over a single data repository. However, EJBs shine where multiple resources </p> <p>(relational databases, messaging systems, etc.) are involved because they allow </p> <p>transactions to spread across as many different resources as you like, so long as the </p> <p>resources support distributed transactions.</p> <p> </p> <p> <br /> <strong>Distributed functionality</strong> </p> <p>Business services often live on a remote server. For example, a business enterprise will </p> <p>have many different systems, ranging in degrees of inflexibility and entrenchment. One of </p> <p>these systems may need to access another; EJBs, which are inherently distributed, are </p> <p>often the simplest way to distribute remote services. EJB also allows you to provide </p> <p>business services to remote clients more easily than some alternatives. Remote access </p> <p>through components is easier to maintain than direct database access, because the </p> <p>component code can shield the client from database schema changes.</p> <p> </p> <p> <br /> <strong>Portable components (not classes)</strong> </p> <p>Until recently, if you wanted to share your business services with another application </p> <p>developer, you were forced to share classes or at least packages. Java did not allow for </p> <p>the easy creation of enterprise components, reusable software building blocks that can be </p> <p>assembled with other components to form an application. EJBs allow you to package your </p> <p>business logic into a tidy, distributable unit that can be shared in a loosely coupled </p> <p>fashion. The user of your component need only tweak a descriptor file for her </p> <p>environment.</p> <p> </p> <p> <br /> <strong>Applications relying on asynchronous messaging</strong> </p> <p>EJBs (specifically MDBs) provide a strong technology for handling asynchronous </p> <p>communication such as JMS-based messaging or web services.</p> <p> </p> <p> <br /> <strong>Security roles</strong> </p> <p>If your application's business operations can be mapped to specific business roles in </p> <p>your enterprise, then EJBs may be a good choice. So much is made of the transaction </p> <p>management capability of EJBs that their deployment-descriptor-based security management </p> <p>features are overlooked. This capability is very powerful; if your application's users </p> <p>fit into distinct roles and the rules for those roles dictate which users can write what </p> <p>data, EJBs are a good choice.</p> <p> <br /> <strong>2 When Not to Use EJBs</strong> <br />There are several situations in building a software application—even an "enterprise" </p> <p>software application—in which using EJBs may actually be a barrier to meeting your </p> <p>business goals. The following list represents places where you might not want to use </p> <p>EJBs:</p> <p> </p> <p> <br /> <strong>Read-mostly applications</strong> </p> <p>If your application requires only (or even mostly) database reads (as opposed to writes), </p> <p>then the added complexity and performance overhead of EJBs may be unwarranted. If your </p> <p>application is only reading and presenting data, you should go with straight JDBC (see </p> <p>below) or another persistence mechanism. That said, if your application's writes </p> <p>(database update and inserts) require transactional support (especially if those </p> <p>transactions go over multiple systems), then EJBs may be the way to go—at least for the </p> <p>write portion of the application.</p> <p> </p> <p> <br /> <strong>Applications requiring thread control</strong> </p> <p>If your application design requires extensive use of threads, then the EJB spec actually </p> <p>prevents you from using EJBs (although some EJB container vendors may provide nonportable </p> <p>ways around this restriction). Container systems manage resources, transactions, </p> <p>security, and other qualities of service using threads; threads you create are outside of </p> <p>the container's control and can potentially cause system failures. Also, EJB containers </p> <p>may distribute EJBs across multiple JVMs, preventing the synchronization of threads.</p> <p> </p> <p> <br /> <strong>Performance</strong> </p> <p>Because EJBs do so much more than plain Java classes, they are slower than plain Java </p> <p>classes. The EJB container has to do a lot: maintain transactional integrity, manage bean </p> <p>instances and the bean pools, enforce security roles, manage resources and resource </p> <p>pools, coordinate distributed operations, synchronize shared services (if the vendor </p> <p>offers clustering capabilities), and so on. The security and transactional management </p> <p>operations can have a significant impact on the performance of method calls (on both </p> <p>local and remote interfaces). If you require real-time or near-real-time performance </p> <p>characteristics, EJB may not be your best choice.</p> <p> <br /> <strong>3 Alternatives to EJB</strong> <br />There are several alternatives to EJB; some of them are growing in popularity and </p> <p>maturity. EJBs still rank as the de facto standard for enterprise transactional needs, </p> <p>but some of the alternatives, like JDO, are also available.</p> <p>3.1 JDBC</p> <p>3.2 Java Data Objects</p> <p>3.3 Others</p> <p>Castor JDO (<a rel="nofollow">http://www.exolab.org</a>)</p> <p>Hibernate (<a rel="nofollow">http://www.hibernate.org</a>)</p> <p>Prevayler (<a rel="nofollow">http://www.prevayler.org</a>)</p> <p> <br />As you can see, there are several alternatives to EJB. If your application doesn't need </p> <p>the complexity or some of the features of EJB, take a look around. Data persistence with </p> <p>Java has been around for some time and there is a wide assortment of approaches.</p> <img src ="http://www.aygfsteel.com/liaojiyong/aggbug/55899.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/liaojiyong/" target="_blank">liaojiyong</a> 2006-06-30 11:21 <a href="http://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55899.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3.0开发指南之无状态会话Beanhttp://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55845.htmlliaojiyongliaojiyongFri, 30 Jun 2006 00:31:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55845.htmlhttp://www.aygfsteel.com/liaojiyong/comments/55845.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2006/06/30/55845.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/55845.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/55845.html阅读全文

liaojiyong 2006-06-30 08:31 发表评论
]]>
EJB3 Persistence开发手?/title><link>http://www.aygfsteel.com/liaojiyong/archive/2006/06/28/55514.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Wed, 28 Jun 2006 04:23:00 GMT</pubDate><guid>http://www.aygfsteel.com/liaojiyong/archive/2006/06/28/55514.html</guid><wfw:comment>http://www.aygfsteel.com/liaojiyong/comments/55514.html</wfw:comment><comments>http://www.aygfsteel.com/liaojiyong/archive/2006/06/28/55514.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/liaojiyong/comments/commentRss/55514.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/liaojiyong/services/trackbacks/55514.html</trackback:ping><description><![CDATA[ <ol> <li> <a >EJB3 Persistence API介绍</a> <ol> <li> <a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/overview.html#Why EJB3(Z么要引入EJB3)">Z么要引入EJB3</a> </li> <li> <a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/overview.html#EJB_3和EJB_2_1的区?>EJB 3和EJB 2.1的区?/a> </li> <li> <a >EJB 3中的元数据批?Annotation</a> </li> </ol> </li> <li> <a >W一个Entity Bean:HelloWorld</a> </li> <li> <a >解说Entity</a> <ol> <li> <a >定义对Entity中属性的讉K</a> </li> <li> <a >主键和实体标识(Primary Key and Entity Identity)</a> </li> </ol> </li> <li> <a >操作Entity</a> <ol> <li> <a >配置和获得EntityManager</a> </li> <li> <a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/EntityManager.html#Entity的生命周期和状?>Entity的生命周期和状?/a> </li> <li> <a >持久化Entity</a> </li> <li> <a >获取Entity</a> </li> <li> <a >更新Entity</a> </li> <li> <a >删除Entity</a> </li> <li> <a >分离/附合(Detach/Merge)</a> </li> </ol> </li> <li> <a >EJB3 QL查询</a> <ol> <li> <a >Query接口</a> </li> <li> <a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#单查?>单查?/a> </li> <li> <a >使用参数查询</a> </li> <li> <a >排序(order by)</a> </li> <li> <a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#查询部分属?>查询部分属?/a> </li> <li> <a >查询中用构造器(Constructor)</a> </li> <li> <a >聚合查询(Aggregation)</a> </li> <li> <a >兌(join)</a> <ul> <li> <a >left join/left out join</a> </li> <li> <a >inner join</a> </li> <li> <a >left/inner join fetch</a> </li> </ul> </li> <li> <a >比较Entity</a> </li> <li> <a >扚w更新(Batch Update)</a> </li> <li> <a >扚w删除(Batch Remove)</a> </li> <li> <a >使用操作WNOT</a> </li> <li> <a >使用操作WBETWEEN</a> </li> <li> <a >使用操作WIN</a> </li> <li> <a >使用操作WLIKE</a> </li> <li> <a >使用操作WIS NULL</a> </li> <li> <a >使用操作WIS EMPTY</a> </li> <li> <a >使用操作WEXISTS</a> </li> <li> <a >使用操作WALL/SOME/ANY</a> </li> <li> <a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#字符串函?>字符串函?/a> </li> <li> <a >计算函数</a> </li> <li> <a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#子查?>子查?/a> </li> </ol> </li> <li> <a >原生SQL查询(Native SQL)</a> </li> <li>关系Q对象映? <ol><li><a >一对一映射</a></li><li><a >一对多映射</a></li><li><a >多对多映?/a></li><li><a >l承</a></li></ol></li> <li> <a >关系对象映射元数?/a> <ol> <li> <a >Table</a> </li> <li> <a >SecondaryTable</a> </li> <li> <a >SecondaryTables</a> </li> <li> <a >UniqueConstraint</a> </li> <li> <a >Column</a> </li> <li> <a >JoinColumn</a> </li> <li> <a >JoinColumns</a> </li> <li> <a >Id</a> </li> <li> <a >IdClass</a> </li> <li> <a >MapKey</a> </li> <li> <a >OrderBy</a> </li> <li> <a >PrimaryKeyJoinColumn</a> </li> <li> <a >PrimaryKeyJoinColumns</a> </li> <li> <a >Transient</a> </li> <li> <a >Version</a> </li> <li> <a >Lob</a> </li> <li> <a >JoinTable</a> </li> <li> <a >TableGenerator</a> </li> <li> <a >SequenceGenerator</a> </li> <li> <a >DiscriminatorColumn</a> </li> <li> <a >DiscriminatorColumn</a> </li> </ol> </li> </ol> <img src ="http://www.aygfsteel.com/liaojiyong/aggbug/55514.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/liaojiyong/" target="_blank">liaojiyong</a> 2006-06-28 12:23 <a href="http://www.aygfsteel.com/liaojiyong/archive/2006/06/28/55514.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3 Demo(?http://www.aygfsteel.com/liaojiyong/archive/2006/06/27/55367.htmlliaojiyongliaojiyongTue, 27 Jun 2006 09:14:00 GMThttp://www.aygfsteel.com/liaojiyong/archive/2006/06/27/55367.htmlhttp://www.aygfsteel.com/liaojiyong/comments/55367.htmlhttp://www.aygfsteel.com/liaojiyong/archive/2006/06/27/55367.html#Feedback0http://www.aygfsteel.com/liaojiyong/comments/commentRss/55367.htmlhttp://www.aygfsteel.com/liaojiyong/services/trackbacks/55367.html

描述

EJB3 Demo

The goal of this project is to try out various features of Java EE 5.0, such as EJB 3.0, JAX-WS, JAXB, etc., and identify design/code patterns that result in:

  1. Improved portability and re-usability of code, in particular, allow Business Logic and Data Access logic to be deployed inside and outside J2EE containers. The two main features of EJB 3.0 that should enable this are a) the new Persistence framework, and b) the promise of building Business Logic components as POJOs.
  2. Establish design and coding patterns that result in simplicity, and promote a rapid development approach, without sacrificing good design principles.

Current status

A few experimental projects are available from the download area. These are:

  1. tpcc-persist - contains EJB 3.0 Entity classes for Apache Derby. The entity model is a mapping of the tables defined by the well known TPC-C Benchmark, however, due to limitations in Glassfish, the schema has been modified to use surrogate primary keys instead of composite primary keys.
  2. tpcc-persist-oracle - this packages the same entity classes for Oracle.
  3. tpcc-session - contains EJB 3.0 Session beans that implement the Data Access layer. An important objective of this component is to preserve the Interface/Implementation separation so that it is possible to replace the EJB 3.0 persistence logic with pure JDBC logic at the implementation level without impacting clients.
  4. tpcc-client - contains sample J2EE application client programs that show how to access EJBs from a client. Makes use of JNDI lookups and dependency injection.
  5. tpcc-j2se - Contains sample programs that run under J2SE. These program also access the Session beans, but treat them as plain old Java objects (POJOs) and use a factory class to instantiate the beans. An EntityManager instance is injected manually into the Beans by the factory.
  6. tpcc-web - Contains very simple web interfaces that allow experimentation with EJBs.
  7. tpcc-ea - Builds and deploys EAR file to the J2EE server. The objective here is to explore packaging options.

How you can help

I require help to create the user interface programs that will exercise the EJBs. I would like to have a complete Web application implemented in tpcc-web project, and also an alternative J2SE GUI application implemented in tpcc-client and tpcc-j2se projects. The aim is to share the same Business Logic/Data Access Layer and Entities across these projects, thus demonstrating the benefits of the new EJB 3.0 technolgies.

I would also welcome essays and articles that describe design patterns that will lead to portability, simplicity, and reusability of code.

It would be nice if someone could take these projects and make them work under JBOSS.

A test of the EJB 3.0 technology will be to deploy the Business Logic and DAO layer as Beans using the Spring Framework.

If you would like to participate in this project, please request an appropriate role and email me describing what you would like to work on.

News

  • 09-Mar-06 - Ported the entities to Oracle.
  • 23-Feb-06 - Refreshed the project code.
  • 14-Feb-06 - Uploaded an initial set of projects.

Downloads

The latest code can be obtained here. Note that this is work in progress, and therefore changing frequently.

Articles

Todo.

Links

  • Blog about EJB 3.0 and Java programming in general.
  • Glassfish - Sun's OpenSource Java EE 5.0 Application Server.


liaojiyong 2006-06-27 17:14 发表评论
]]>
վ֩ģ壺 Դ| Ǩ| Ǧɽ| | | | | | ɽ| | | | | ƽ| ʯ| | | | ǿ| | | | ֶ| | | ־| | | ȫ| | | | | | | | Ӧ| | ԭ| ԭ| |