﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-&lt;font color="red"&gt;中國男人&lt;/font&gt;&lt;font color="lightgreen"&gt;大鹏一曰同风起，扶摇直上九万里&lt;/font&gt;-随笔分类-EJB</title><link>http://www.blogjava.net/liaojiyong/category/12588.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 19:04:41 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 19:04:41 GMT</pubDate><ttl>60</ttl><item><title>为什么要使用EJB？(转)</title><link>http://www.blogjava.net/liaojiyong/archive/2006/08/02/61344.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Wed, 02 Aug 2006 07:56:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/08/02/61344.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/61344.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/08/02/61344.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/61344.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/61344.html</trackback:ping><description><![CDATA[
		<h2 align="center">　</h2>
		<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">板桥里人</a> http://www.jdon.com 2004/03/08</p>
		<p align="left">　　首先，我们必须明确，为什么要使用J2EE？J2EE优点是什么？使用J2EE的主要原因是多层结构，传统的两层C/S结构难于维护，稳定性极差，界面代码和数据库代码混淆在一起，牵一动百，多层结构使得界面和数据库完全分离，并且诞生了中间件这样的技术，如下图：</p>
		<p align="center">
				<img height="186" alt="" src="http://www.jdon.com/artichect/images/middle.png" width="400" />
		</p>
		<h3>Web+EJB能组成真正的多层结构</h3>
		<p>　　为什么使用EJB我原先认为这不是一个讨论的话题，因为EJB是J2EE重要的组成部分，可以说没有EJB的J2EE只是一种Web系统，这样的系统非常容易丧失了多层结构的大部分优点（仔细想想那些混合多种层次功能JavaBeans和传统两层结构有什么区别？）。</p>
		<p>　 　当然，可以人为地在Javabeans之间进行层次划分，例如Hibernate算数据持久层，某些JavaBeans是业务核心层，但是因为都是普通 JavaBeans，这种划分没有一种强制性和明显标志性，这样的系统更换了主创人员或设计师，可能就会被新的程序员修改得非常混乱。</p>
		<p>　　我们先看看一个包含EJB的J2EE系统是如何清晰地表达层次。如下图：</p>
		<p align="center">
				<img height="300" alt="" src="http://www.jdon.com/artichect/images/j2ee.png" width="482" />
		</p>
		<p>　　Web完全只是一个MVC模式的实现，关键业务核心是在EJB的服务层实现，这样做的优点是，Web只负责界面相关部分，因为，如果是一个智能客户端，如Swing或J2ME，在不需要修改任何业务核心的情况下能够方便地更换。同样，提供Web Services功能，也只是在 Web层修改，不会涉及EJB方面的修改，同样保证了系统的稳定性，保证了系统升级和未来的扩展性。</p>
		<p>　　如果不使用EJB，在EJB服务层实现的业务核心将由普通JavaBeans实现，使用何种架构或设计能够保证负责MVC的JavaBeans和负责业务核心的JavaBeans清晰地分开，又如何保证在新的程序员不会破坏和打乱你精心布局的JavaBeans架构？</p>
		<h3>EJB提供性能优化支持</h3>
		<p>　　最主要的是性能问题，由于以前国内中文Java网站有些人弯曲EJB，认为EJB性能低，其实这是一种非常肤浅错误的认识，我们首先看看在一般Java环境中是如何提高性能。</p>
		<p>　　假定一个JavaBeans为A，那么一般使用这个JavaBeans命令如下：</p>
		<p>　　A a = new A();</p>
		<p>　 　但是，在高访问量的环境中，new A()其实是很费时消耗系统性能的，因此，能不能在软件系统启动时候就预先建立一些对象，这样，系统运行时，从这些已经生成的对象池中借用一个，这样，就 无需在使用时进行New，节约了开销，提高了性能，因此，真正成熟性能解决方案都是需要对象池等支持。</p>
		<p>　 　在一个纯Web结构的系统（也就是只能运行在Tomat环境中），例如Struts + Hibernate等这样的系统，除非自己动手做，一般是没有对象池技术支持的，因此他们的性能只能算是Demo演示版本的性能，根本无法承受大容量并发 访问，也无法称为一个成熟的系统，所以，我们研究成熟的开源Web系统，如Jive、OFBize，LifeRay等，他们都在Web层拥有自己的对象池 和缓存池。</p>
		<p>　　对象池和缓存机制是J2EE必须的吗？当然，是所有成熟系统必须的，Windows系统如果去掉缓存将会变得怎样？</p>
		<p>　　自己动手开发对象池和缓存机制并不是一件简单的事情，需要对多线程以及同步锁等底层原理有深层次的把握，这其实也是一门非常深入的Java研究分支，所以，你可以抛开你的客户焦急的催促，精心研究开发自己的对象池和缓存池。</p>
		<p>　 　但是，EJB容器（如JBoss）已经提供了对象池和缓存机制，所以，没有事务机制的无状态Session Bean的性能肯定要强于普通JavaBeans。EJB容器不但在单机中提供了对象池和缓存，而且可以跨服务器实现动态负载平衡，这些都无需开发者自己 开发任何软件代码，结构如下：</p>
		<p align="center">
				<img height="227" alt="" src="http://www.jdon.com/artichect/images/ejb.png" width="304" />
		</p>
		<h3 align="left">EJB组件能提供真正的可重用框架</h3>
		<p align="left">　　每一个jar包代表一个EJB组件，一个系统可以由多个可重用的EJB组件构成，例如：树形结构EJB组件；自增序号EJB组件；用户资料EJB组件等，这样的EJB组件可以象积木一样搭配在大部分应用系统中，提高了系统的开发效率，保证了开发质量。</p>
		<p align="left">　　下图是某个新的具体系统时应用到的EJB组件图，在这个新的应用中，由于使用了以前大量可重用的EJB组件，新的开发工作基本集中在界面设计和流程安排上：</p>
		<p align="center">
				<img height="421" alt="" src="http://www.jdon.com/artichect/images/ejbcomps.png" width="297" />
		</p>
		<h3>EJB提供了事务机制</h3>
		<p>　　事务机制对于一些关键事务是很重要的，例如ATM机提款，提款有多个动作：修改数据库以及数钱等，如果这其中有任何一个环节出错，那么其它已经实现的操作必须还原，否则，就会出现，提款人没有拿到钱，但是卡上已经扣款等不可思议的事情发生。</p>
		<p>　 　EJB提供的事务机制非常周全，但事务机制带来的缺点是性能的降低，因此，有些人认为EJB很重，因为在实际应用中，有的用户系统可能不需要事务机制， 只是需要EJB提供的性能优化机制，这样，如果使用EJB，就象叫一个人来背东西，他除了背着我要的东西外，还背着我不要的东西。</p>
		<p>　　除非你是一个完美主义，在一般企业应用或数据库系统应用中，EJB不会对你构成很重的包袱。</p>
		<h3>CMP独特的优点</h3>
		<p>　　开源以及一些数据库持久层技术崇拜者，一直抨击CMP，认为CMP慢无用，实际最大的问题是他们的设计和使用问题。</p>
		<p>　 　由于EJB容器（如JBoss）对CMP实现有事务机制的缓存优化，因此，CMP特别适合多个用户同时更新同一个数据源的情况，CMP这种严格的事务完 整性保证多个用户同时操作一个数据记录时，能够保证性能优化和数据的完整性，如果这个数据记录是是软件系统的状态标志，它的状态会影响系统中很多的环节， 那么状态更改的重要性不言而喻。</p>
		<p>　　如果没有事务完整性支持，你的软件系统在用户访问量变大，就会变得发生各种不可能发生的逻辑错误，查看程序逻辑是正确的，那么问题出在哪里？出在数据完整性上。</p>
		<p>　 　由于每个CMP在内存中都有一个缓存，在实际应用中，如果使用CMP批量读数据库数据，几万条查询完毕，内存中充满了几万条CMP缓存，如果这时你的 EJB容器设置不当（如使用JBoss缺省配置），那么JVM的垃圾回收机制就会频繁启动，导致你的系统变慢甚至死机，这也是一些人抨击CMP慢的原因所 在，其实他们使用方法不当，或者没有正确配置EJB容器CMP缓存。</p>
		<p>　　对于这种情况，根据J2EE核心模式，推荐使用DAO+JDBC方式。</p>
		<h3>小结</h3>
		<p>　 　除非你对设计模式非常精深，能够将自己系统中的JavaBeans使用模式或某种框架进行固定分层，同时，你孜孜不倦研发出对象池，又熟练于JTA等事 务机制，你可以选择没有EJB的纯Web结构，就象Jive、OFBiz那样。当然还有一个前提，老板不懂或者非常有挑战性（做与IBM SUN 微软齐名的公司和技术）。</p>
		<p>　　不要再被TSS那些狂热的开源先生误导，他们有时间有保障可以做他们喜欢的事情，作为专业的J2EE程序员，按照J2EE标准去学习去行动，也不要认为，只要使用了J2EE其中某个技术如Jsp或JavaBeans就心安理得认为自己的系统是J2EE了。</p>
		<p>　　当然，我并不是说纯Web系统不能实现多层结构，但是至少在很多方面没有Web+EJB结构完善和清晰，所以，EJB不是J2EE可以忽视的部分，而是主要的重要的部分，重要业务功能核心都封装在EJB中，相反Web层是一种次要的、和界面相关的层次。</p>
		<p>　　补充：什么情况下不需要EJB，在SUN的SECA架构师试卷中回答：小型系统和不需要事务。另外过去那种认为“EJB有性能问题”根本是一种缪误，具体可参考下面有关问题。</p> <img src ="http://www.blogjava.net/liaojiyong/aggbug/61344.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-08-02 15:56 <a href="http://www.blogjava.net/liaojiyong/archive/2006/08/02/61344.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB 3.0 学习笔记——Entity Bean（转）</title><link>http://www.blogjava.net/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.blogjava.net/liaojiyong/archive/2006/07/21/59317.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/59317.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/07/21/59317.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/59317.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/59317.html</trackback:ping><description><![CDATA[
		<p>在EJB 3.0 学习笔记——准备工作中只是简单的搭好了EJB3.0开发的基本环境，之</p>
		<p>后就可以开发最简单的Session Bean了，我感兴趣的还是Entity Bean，所以接下来</p>
		<p>我想先试验一下Entity Bean。<br /> <br />一、在JBoss中配置好Data Source<br />我使用的是MySQL数据库，所以首先将MySQL的JDBC驱动复制到<br />jboss-4.0.3SP1\server\all\lib目录，然后将jboss-4.0.3SP1\docs\examples\jca</p>
		<p>下的mysql-ds.xml作出适当修改后复制到jboss-4.0.3SP1\server\all\deploy目录</p>
		<p>下，这是我修改后的mysql-ds.xml文件：</p>
		<p>&lt;?xml version="1.0" encoding="UTF-8"?&gt;</p>
		<p>&lt;!-- $Id: mysql-ds.xml,v 1.3.2.1 2004/12/01 11:46:00 schrouf Exp $ --&gt;<br />&lt;!--  Datasource config for MySQL using 3.0.9 available from:<br /><a href="http://www.mysql.com/downloads/api-jdbc-stable.html"><font color="#000080">http://www.mysql.com/downloads/api-jdbc-stable.html</font></a><br />--&gt;</p>
		<p>&lt;datasources&gt;<br />  &lt;local-tx-datasource&gt;<br />    &lt;jndi-name&gt;MySqlDS&lt;/jndi-name&gt;<br />    &lt;connection-url&gt;jdbc:mysql://localhost:3306/test&lt;/connection-url&gt;<br />    &lt;driver-class&gt;com.mysql.jdbc.Driver&lt;/driver-class&gt;<br />    &lt;user-name&gt;test&lt;/user-name&gt;<br />    &lt;password&gt;&lt;/password&gt;<br />    &lt;exception-sorter-class-</p>
		<p>name&gt;org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter&lt;/excepti</p>
		<p>on-sorter-class-name&gt;<br />    &lt;!-- sql to call when connection is created<br />    &lt;new-connection-sql&gt;some arbitrary sql&lt;/new-connection-sql&gt;<br />      --&gt;<br />    &lt;!-- sql to call on an existing pooled connection when it is obtained </p>
		<p>from pool <br />    &lt;check-valid-connection-sql&gt;some arbitrary sql&lt;/check-valid-</p>
		<p>connection-sql&gt;<br />      --&gt;</p>
		<p>    &lt;!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml </p>
		<p>(optional) --&gt;<br />    &lt;metadata&gt;<br />       &lt;type-mapping&gt;mySQL&lt;/type-mapping&gt;<br />    &lt;/metadata&gt;<br />  &lt;/local-tx-datasource&gt;<br />&lt;/datasources&gt;<br />这样之后，JBoss下的MySQL Data Source配置完成。</p>
		<p>二、创建数据库并编写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 Project，导入User Library：EJB3_JBoss，以下是类代码。</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 并进行测试</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 &lt;a href="<a href="mailto:bill@jboss.org&quot;&gt;Bill"><font color="#000080">mailto:bill@jboss.org"&gt;Bill</font></a> Burke&lt;/a&gt;<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需要修改。<br />//builder.xml<br />&lt;?xml version="1.0"?&gt;</p>
		<p>&lt;!-- </p>
		<p>======================================================================= </p>
		<p>--&gt;<br />&lt;!-- JBoss build file                                                     </p>
		<p>  --&gt;<br />&lt;!-- </p>
		<p>======================================================================= </p>
		<p>--&gt;</p>
		<p>&lt;project name="JBoss" default="ejbjar" basedir="."&gt;</p>
		<p>   &lt;property file="../local.properties" /&gt;<br />   &lt;property environment="env"/&gt;<br />   &lt;property name="src.dir" value="${basedir}/src"/&gt;<br />   &lt;property name="jboss.home" value="E:/Programming/Servers/jboss-</p>
		<p>4.0.3SP1/"/&gt;<br />   &lt;property name="jboss.server.config" value="all"/&gt;<br />   &lt;property name="build.dir" value="${basedir}/build"/&gt;<br />   &lt;property name="build.classes.dir" value="${build.dir}/classes"/&gt;</p>
		<p>   &lt;!-- Build classpath --&gt;<br />   &lt;path id="classpath"&gt;<br />      &lt;!-- So that we can get jndi.properties for InitialContext --&gt;<br />      &lt;pathelement location="${basedir}"/&gt;<br />      &lt;fileset dir="${jboss.home}/lib"&gt;<br />         &lt;include name="**/*.jar"/&gt;<br />      &lt;/fileset&gt;<br />      &lt;fileset dir="${jboss.home}/server/${jboss.server.config}/lib"&gt;<br />         &lt;include name="**/*.jar"/&gt;<br />      &lt;/fileset&gt;<br />      &lt;fileset dir="${jboss.home}/server/</p>
		<p>${jboss.server.config}/deploy/ejb3.deployer"&gt;<br />         &lt;include name="*.jar"/&gt;<br />      &lt;/fileset&gt;<br />      &lt;fileset dir="${jboss.home}/server/</p>
		<p>${jboss.server.config}/deploy/jboss-aop-jdk50.deployer"&gt;<br />         &lt;include name="*.jar"/&gt;<br />      &lt;/fileset&gt;<br />      &lt;pathelement location="${build.classes.dir}"/&gt;<br />   &lt;/path&gt;</p>
		<p>   &lt;property name="build.classpath" refid="classpath"/&gt;</p>
		<p>   &lt;!-- </p>
		<p>=================================================================== --&gt;<br />   &lt;!-- Prepares the build directory                                      </p>
		<p>  --&gt;<br />   &lt;!-- </p>
		<p>=================================================================== --&gt;<br />   &lt;target name="prepare"&gt;<br />      &lt;mkdir dir="${build.dir}"/&gt;<br />      &lt;mkdir dir="${build.classes.dir}"/&gt;<br />   &lt;/target&gt;</p>
		<p>   &lt;!-- </p>
		<p>=================================================================== --&gt;<br />   &lt;!-- Compiles the source code                                          </p>
		<p>  --&gt;<br />   &lt;!-- </p>
		<p>=================================================================== --&gt;<br />   &lt;target name="compile" depends="prepare"&gt;<br />      &lt;javac srcdir="${src.dir}"<br />         destdir="${build.classes.dir}"<br />         debug="on"<br />         deprecation="on"<br />         optimize="off"<br />         includes="**"&gt;<br />         &lt;classpath refid="classpath"/&gt;<br />      &lt;/javac&gt;<br />   &lt;/target&gt;</p>
		<p>   &lt;target name="ejbjar" depends="compile"&gt;<br />      &lt;jar jarfile="build/tutorial.jar"&gt;<br />         &lt;fileset dir="${build.classes.dir}"&gt;<br />            &lt;include name="**/*.class"/&gt;<br />         &lt;/fileset&gt;<br />        &lt;fileset dir="."&gt;<br />           &lt;include name="META-INF/persistence.xml"/&gt;<br />        &lt;/fileset&gt;<br />      &lt;/jar&gt;<br />      &lt;copy file="build/tutorial.jar" todir="${jboss.home}/server/</p>
		<p>${jboss.server.config}/deploy"/&gt;<br />   &lt;/target&gt;</p>
		<p>   &lt;target name="run.stateless" depends="ejbjar"&gt;<br />      &lt;java classname="ejb.client.stateless.Client" fork="yes" dir="."&gt;<br />         &lt;classpath refid="classpath"/&gt;<br />      &lt;/java&gt;<br />   &lt;/target&gt;<br /> <br /> &lt;target name="run.stateful" depends="ejbjar"&gt;<br />       &lt;java classname="ejb.client.stateful.Client" fork="yes" </p>
		<p>dir="."&gt;<br />          &lt;classpath refid="classpath"/&gt;<br />       &lt;/java&gt;<br /> &lt;/target&gt;<br /> <br /> &lt;target name="run.timer" depends="ejbjar"&gt;<br />       &lt;java classname="ejb.client.timer.Client" fork="yes" </p>
		<p>dir="."&gt;<br />          &lt;classpath refid="classpath"/&gt;<br />       &lt;/java&gt;<br /> &lt;/target&gt;<br /> <br /> &lt;target name="run.entity" depends="ejbjar"&gt;<br />        &lt;java classname="ejb.client.entity.Client" </p>
		<p>fork="yes" dir="."&gt;<br />           &lt;classpath refid="classpath"/&gt;<br />        &lt;/java&gt;<br />  &lt;/target&gt;<br /> </p>
		<p>   &lt;!-- </p>
		<p>=================================================================== --&gt;<br />   &lt;!-- Cleans up generated stuff                                         </p>
		<p>  --&gt;<br />   &lt;!-- </p>
		<p>=================================================================== --&gt;<br />   &lt;target name="clean.db"&gt;<br />      &lt;delete dir="${jboss.home}/server/</p>
		<p>${jboss.server.config}/data/hypersonic"/&gt;<br />   &lt;/target&gt;</p>
		<p>   &lt;target name="clean"&gt;<br />      &lt;delete dir="${build.dir}"/&gt;<br />      &lt;delete file="${jboss.home}/server/</p>
		<p>${jboss.server.config}/deploy/tutorial.jar"/&gt;<br />   &lt;/target&gt;</p>
		<p>
				<br />&lt;/project&gt;</p>
		<p>最后，在工程目录下新建目录META-INF，在目录META-INF新建persistence.xml文件</p>
		<p>，以下是文件内容：<br />&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;persistence&gt;<br />   &lt;persistence-unit name="test"&gt;<br />      &lt;jta-data-source&gt;java:/MySqlDS&lt;/jta-data-source&gt;<br />      &lt;properties&gt;<br />       &lt;property name="hibernate.dialect" </p>
		<p>value="org.hibernate.dialect.MySQLDialect"/&gt;       <br />        &lt;property name="hibernate.hbm2ddl.auto" value="update"/&gt;<br />      &lt;/properties&gt;<br />   &lt;/persistence-unit&gt;<br />&lt;/persistence&gt;</p>
		<p>四、运行测试<br />run as-&gt;ant build后，选择运行目标为run.entity-&gt;run。<br />运行结果：<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.blogjava.net/liaojiyong/aggbug/59317.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-07-21 01:39 <a href="http://www.blogjava.net/liaojiyong/archive/2006/07/21/59317.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB 3.0开发指南之组合主键</title><link>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56460.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Tue, 04 Jul 2006 01:28:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56460.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/56460.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56460.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/56460.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/56460.html</trackback:ping><description><![CDATA[在前面的所有的实体Bean的例子中，我们所用的主键都是Id,而且都是由容器自动生成的。 <br /><br />　　如:<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>@Id(generate = GeneratorType.AUTO)<br />public int getId()<br />{<br />　return id;<br />}</td></tr></tbody></table><br />　　事实上,主键可以是任意的java基本类型、或者是基本类型的包装类，如Integer、String类型、或者是带字段或属性的主键类。注意，如果这样使用主键,你需要将主键的注释中的生成规则改为NONE。就是由程序生成主键值。<br /><br />　　主键类必须实现hashCode和equals方法。<br /><br />　　这个例子前面举例过，就是一个存储学生信息的实体bean，在那个例子中，使用Name类作为属性，并且以Id作为主键，在这个例子中，我们将使用name作为主键，注意name的类型一个java类。和前面的例子一样，我们还是使用Client测试。<br /><br />　　Name.java：主键。<br /><br />　　Student.java：实体Bean类。<br /><br />　　StudentDAO.java：会话Bean的业务接口<br /><br />　　StudentDAOBean.java：会话Bean的实现类<br /><br />　　Client.java：测试EJB的客户端类。<br /><br />　　jndi.properties：jndi属性文件，提供访问jdni的基本配置属性。<br /><br />　　Build.xml：ant 配置文件，用以编译、发布、测试、清除EJB。<br /><br />　　下面针对每个文件的内容做一个介绍。<br /><br />　　Name.java<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>package com.kuaff.ejb3.composite;<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 /><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 /><br />　public int hashCode()<br />　{<br />　　return (first+last).hashCode();<br />　}<br /><br />　public boolean equals(Object object)<br />　{<br />　　if (this == object) return true;<br />　　if (object == null) return false;<br />　　if (! (object instanceof Name)) return false;<br />　　Name name = (Name)object;<br />　　if ((name.first.equals(first)) &amp;&amp; (name.last.equals(last)))<br />　　　return true;<br />　　else<br />　　　return false;<br />　}<br /><br />}</td></tr></tbody></table><br />　　Student.java<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>package com.kuaff.ejb3.composite;<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 Name name;<br />　private String grade;<br />　private String email;<br /><br />　public void setName(Name name)<br />　{<br />　　this.name = name;<br />　}<br /><br />　@Id(generate = GeneratorType.NONE)<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 />　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;</td></tr></tbody></table><br />　　StudentDAO.java<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>package com.kuaff.ejb3.composite;<br /><br />import javax.ejb.Remote;<br />import java.util.List;<br /><br />@Remote<br /><br />public interface StudentDAO<br /><br />{<br /><br />void create(String first, String last, String grade, String email);<br /><br /><br /><br />Student find(Name name);<br /><br />List findByFirstName(String name);<br /><br />List findByLastName(String name);<br /><br />List findByEmail(String email);<br /><br /><br /><br />void merge(Student s);<br /><br />}</td></tr></tbody></table><br />　　StudentDAOBean.java<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>package com.kuaff.ejb3.composite;<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 void 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 />　}<br /><br />　public Student find(Name name)<br />　{<br />　　return manager.find(Student.class, name);<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 />　}<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 />　　Client.java<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>package com.kuaff.ejb3.composite;<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 />　　dao.create("晁","岳攀","8","smallnest@kuaff.com");<br />　　dao.create("朱","立焕","6","zhuzhu@kuaff.com");<br />　　Name name = new Name("朱","立焕");<br /><br />　　//List list = dao.findByEmail("zhuzhu@kuaff.com");<br /><br />　　Student s = dao.find(name);<br />　　System.out.printf("%s %s的email:%s%n",s.getName().getFirst(),s.getName().getLast(),s.getEmail());<br />　　/*<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 />　　这个客户端用来测试。<br /><br />　　请运行{$JBOSS_HOME}/bin目录下的run.bat: run –c all,启动JBOSS。<br /><br />http://localhost:8080/jmx-console/HtmlAdaptor?action=inspectMBean&amp;name=jboss%3Aservice%3DHypersonic%2Cdatabase%3DlocalDB，然后调用startDatabaseManager()方法，打开HSQL管理工具管理数据库。<br /><br />　　在Eclipse的Ant视图中执行ejbjar target。或者在命令行下，进入到此工程目录下，执行ant ejbjar,将编译打包发布此EJB。<br /><br />　　在Eclipse的Ant视图中执行run target。或者在命令行下，进入到此工程目录下，执行ant run,测试这个EJB。<br /><img src ="http://www.blogjava.net/liaojiyong/aggbug/56460.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-07-04 09:28 <a href="http://www.blogjava.net/liaojiyong/archive/2006/07/04/56460.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3.0开发指南之多对多和一对一</title><link>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56459.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Tue, 04 Jul 2006 01:27:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56459.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/56459.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56459.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/56459.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/56459.html</trackback:ping><description><![CDATA[在前面的例子中，我们演示了一对多和多对一的例子，在本章将演示多对多和一对一的关系。 <br /><br />　　学生和老师就是多对多的关系。一个学生有多个老师，一个老师教多个学生。<br /><br />　　学生和档案就是一对一的关系（不知道国外的学生有没有档案？）。<br /><br />　　为了实现多对多的关系，数据库中需要关联表，用以在两个实体间建立关联。JBoss可以自动生成关联表，你也可以@AssociationTable来指定关联表的信息。<br /><br />　　如:<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>@ManyToMany(cascade = {CascadeType.CREATE, CascadeType.MERGE}, fetch = FetchType.EAGER, isInverse = true)<br />@AssociationTable(table = @Table(name = "STUDENT_TEACHER"),<br /><br />joinColumns = {@JoinColumn(name = "TEACHER_ID")},inverseJoinColumns = {@JoinColumn(name = "STUDENT_ID")})<br /><br />@ AssociationTable的注释声明如下：<br />@Target({METHOD, FIELD})<br /><br />public @interface AssociationTable {<br />　Table table() default @Table(specified=false);<br />　JoinColumn[] joinColumns() default {};<br />　JoinColumn[] inverseJoinColumns() default {};<br />}</td></tr></tbody></table><br />　　关联表注释指定了关联表的名称、主表的列和从表的列。<br /><br />　　为了实现一对一的关系，需要用@OneToOne来注释。 <br /><br />　　如:<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>@OneToOne(cascade = {CascadeType.ALL})<br />@JoinColumn(name = "DOSSIER_ID")<br /><br />public Dossier getDossier()<br />{<br />　return dossier;<br />}</td></tr></tbody></table><br />　　这定义了一个单向的一对一的关系。如果在Dossier也定义了相关的关联，那么它就是双向的。双向的意思就是通过一个Student实体就可以查找到一个Dossier，通过一个Dossier就可以查找到一个Student。<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>@ OneToOne的注释声明如下：<br />@Target({METHOD, FIELD}) @Retention(RUNTIME)<br /><br />public @interface OneToOne {<br />　String targetEntity() default "";<br />　CascadeType[] cascade() default {};<br />　FetchType fetch() default EAGER;<br />　boolean optional() default true;<br />}</td></tr></tbody></table><br />　　这个例子主要有以下几个文件，这个例子主要实现了学生和老师、学生和档案之间的关系。Student、Teacher、Dossier都是实体Bean。Student和Dossier是一个双向的OneToOne之间的关系，Student和Teacher是ManyToMany的关系，也是双向的。和前面的例子一样，我们还是使用Client测试。<br /><br />　　Student.java：实体Bean。<br /><br />　　Dossier.java：实体Bean所依赖的类。<br /><br />　　Teacher.java：实体Bean所依赖的类。<br /><br />　　EntityTest.java：会话Bean的业务接口<br /><br />　　EntityTest Bean.java：会话Bean的实现类<br /><br />　　Client.java：测试EJB的客户端类。<br /><br />　　jndi.properties：jndi属性文件，提供访问jdni的基本配置属性。<br /><br />　　Build.xml：ant 配置文件，用以编译、发布、测试、清除EJB。<br /><br />　　下面针对每个文件的内容做一个介绍。<br /><br />　　Student.java<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>package com.kuaff.ejb3.relationships;<br />import javax.ejb.CascadeType;<br />import javax.ejb.Entity;<br />import javax.ejb.FetchType;<br />import javax.ejb.GeneratorType;<br />import javax.ejb.Id;<br />import javax.ejb.JoinColumn;<br />import javax.ejb.OneToOne;<br />import javax.ejb.ManyToMany;<br />import javax.ejb.Table;<br />import javax.ejb.AssociationTable;<br />import java.util.ArrayList;<br />import java.util.Set;<br />import java.util.Collection;<br />import java.io.Serializable;<br /><br />@Entity<br /><br />@Table(name = "STUDENT")<br /><br />public class Student implements Serializable<br /><br />{<br />　private int id;<br />　private String first;<br />　private String last;<br />　private Dossier dossier;<br />　private Set&lt;Teacher&gt; teachers;<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 setFirst(String first)<br />　{<br />　　this.first = first;<br />　}<br /><br />　public String getFirst()<br />　{<br />　　return first;<br />　}<br /><br />　public void setLast(String last)<br />　{<br />　　this.last = last;<br />　}<br /><br />　public String getLast()<br />　{<br />　　return last;<br />　}<br /><br />　public void setDossier(Dossier dossier)<br />　{<br />　　this.dossier = dossier;<br />　}<br /><br />@OneToOne(cascade = {CascadeType.ALL})<br />@JoinColumn(name = "DOSSIER_ID")<br /><br />public Dossier getDossier()<br />{<br />　return dossier;<br />}<br /><br />public void setTeacher(Set&lt;Teacher&gt; teachers)<br />{<br />　this.teachers = teachers;<br />}<br /><br />@ManyToMany(cascade = {CascadeType.CREATE, CascadeType.MERGE}, fetch = FetchType.EAGER, isInverse = true)<br />@AssociationTable(table = @Table(name = "STUDENT_TEACHER"),<br /><br />joinColumns = {@JoinColumn(name = "TEACHER_ID")},inverseJoinColumns = {@JoinColumn(name = "STUDENT_ID")})<br /><br />public Set&lt;Teacher&gt; getTeacher()<br />{<br />　return teachers;<br />}<br />}<br /><br /><br />　　Dossier.java<br /><br />package com.kuaff.ejb3.relationships;<br /><br />import javax.ejb.Entity;<br />import javax.ejb.GeneratorType;<br />import javax.ejb.Id;<br /><br />@Entity<br /><br />public class Dossier implements java.io.Serializable<br />{<br />　private Long id;<br />　private String resume;<br /><br />　@Id(generate = GeneratorType.AUTO)<br />　public Long getId()<br />　{<br />　　return id;<br />　}<br /><br />　public void setId(Long id)<br />　{<br />　　this.id = id;<br />　}<br /><br />　public void setResume(String resume)<br />　{<br />　　this.resume = resume;<br />　}<br /><br />　public String getResume()<br />　{<br />　　return resume;<br />　}<br />}<br /><br /></td></tr></tbody></table><br /><table cellspacing="0" cellpadding="0" width="776" border="0"><tbody><tr><td valign="top" bgcolor="#f0f2fb" height="10"></td></tr><tr><td valign="top" bgcolor="#f0f2fb"><table cellspacing="0" cellpadding="0" width="590" align="center" border="0"><tbody><tr><td><span class="f14">　　Teacher.java<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>package com.kuaff.ejb3.relationships;<br /><br />import javax.ejb.AssociationTable;<br />import javax.ejb.Basic;<br />import javax.ejb.CascadeType;<br />import javax.ejb.Column;<br />import javax.ejb.Entity;<br />import javax.ejb.FetchType;<br />import javax.ejb.Id;<br />import javax.ejb.JoinColumn;<br />import javax.ejb.ManyToMany;<br />import javax.ejb.Table;<br />import javax.ejb.Transient;<br />import javax.ejb.Version;<br />import java.util.Set;<br />import javax.ejb.GeneratorType;<br /><br />@Entity<br /><br />public class Teacher implements java.io.Serializable<br />{<br />　private Long id;<br />　private String resume;<br />　private String name;<br />　private String info;<br />　private Set&lt;Student&gt; students;<br /><br />　@Id(generate = GeneratorType.IDENTITY) <br /><br />　public Long getId()<br />　{<br />　　return id;<br />　}<br /><br />　public void setId(Long id)<br />　{<br />　　this.id = id;<br />　}<br /><br />　public void setName(String name)<br />　{<br />　　this.name = name;<br />　}<br /><br />　public String getName()<br />　{<br />　　return name;<br />　}<br /><br />　public void setInfo(String info)<br />　{<br />　　this.info = info;<br />　}<br /><br />　public String getInfo()<br />　{<br />　　return info;<br />　}<br /><br />　public void setStudents(Set&lt;Student&gt; students)<br />　{<br />　　this.students = students;<br />　}<br /><br />　@ManyToMany(cascade = {CascadeType.CREATE, CascadeType.MERGE}, fetch = FetchType.EAGER)<br />　@AssociationTable(table = @Table(name = "STUDENT_TEACHER"),<br /><br />　joinColumns = {@JoinColumn(name = "TEACHER_ID",referencedColumnName="ID")},<br />　inverseJoinColumns = {@JoinColumn(name = "STUDENT_ID",referencedColumnName="ID")})<br /><br />　public Set&lt;Student&gt; getStudents()<br />　{<br />　　return students;<br />　}<br />}<br /></td></tr></tbody></table><br />　　EntityTest.java<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>package com.kuaff.ejb3.relationships;<br /><br />import javax.ejb.Remote;<br />import java.util.List;<br /><br />@Remote<br /><br />public interface EntityTest<br />{<br />　public void createData();<br />　public List findByName(String name);<br />}</td></tr></tbody></table><br />　　EntityTestBean.java<br />　<br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>package com.kuaff.ejb3.relationships;<br /><br />import javax.ejb.EntityManager;<br />import javax.ejb.Inject;<br />import javax.ejb.Stateless;<br />import java.util.HashSet;<br />import java.util.Set;<br />import java.util.List;<br /><br />@Stateless<br /><br />public class EntityTestBean implements EntityTest<br />{<br />　private @Inject EntityManager manager;<br />　public void createData()<br />　{<br />　　Teacher teacher1 = new Teacher();<br />　　Teacher teacher2 = new Teacher();<br /><br />　　Set&lt;Student&gt; students1 = new HashSet&lt;Student&gt;();<br />　　Set&lt;Student&gt; students2 = new HashSet&lt;Student&gt;();<br />　　Student student1 = new Student();<br />　　Student student2 = new Student();<br />　　Student student3 = new Student();<br /><br />　　Dossier dossier1 = new Dossier();<br />　　Dossier dossier2 = new Dossier();<br />　　Dossier dossier3 = new Dossier();<br />　　teacher1.setId(new Long(1));<br />　　teacher1.setName("hushisheng");<br />　　teacher1.setInfo("胡时胜教授，博士生导师");<br />　　manager.create(teacher1);<br />　　teacher2.setId(new Long(2));<br />　　teacher2.setName("liyongchi");<br />　　teacher2.setInfo("李永池教授，博士生导师");<br />　　manager.create(teacher2);<br /><br />　　student1.setFirst("晁");<br />　　student1.setLast("岳攀");<br />　　dossier1.setResume("这是晁岳攀的档案");<br />　　student1.setDossier(dossier1);<br />　　students1.add(student1);<br /><br />　　student2.setFirst("赵");<br />　　student2.setLast("志伟");<br />　　dossier2.setResume("这是赵志伟的档案");<br />　　student2.setDossier(dossier2);<br />　　students1.add(student2);<br /><br />　　student3.setFirst("田");<br />　　student3.setLast("明");<br /><br />　　dossier3.setResume("这是田明的档案");<br />　　student3.setDossier(dossier3);<br />　　students2.add(student3);<br /><br />　　teacher1.setStudents(students1);<br />　　teacher2.setStudents(students2);<br /><br />　}<br /><br />　public List findByName(String name)<br />　{<br />　　return manager.createQuery("from Teacher t where t.name = :name").setParameter("name", name).listResults();<br />　}<br /><br />}</td></tr></tbody></table><br />　　在这个会话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.secondary;<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("晁","岳攀","8","smallnest@kuaff.com","男");<br />　　dao.create("朱","立焕","6","zhuzhu@kuaff.com","女");<br />　　List list = dao.findAll();<br />　　for(Object o:list)<br />　　{<br />　　　Student s = (Student)o;<br />　　　System.out.printf("%s%s的性别:%s%n",s.getName().getFirst(),s.getName().getLast(),s.getGender());<br />　　　dao.evict(s);<br />　　}<br />　}<br />} </td></tr></tbody></table><br />　　这个客户端用来测试。<br /><br />　　请运行{$JBOSS_HOME}/bin目录下的run.bat: run –c all,启动JBOSS。<br /><br />　　http://localhost:8080/jmx-console/HtmlAdaptor?action=inspectMBean&amp;name=jboss%3Aservice%3DHypersonic%2Cdatabase%3DlocalDB，然后调用startDatabaseManager()方法，打开HSQL管理工具管理数据库。<br /><br />　　在Eclipse的Ant视图中执行ejbjar target。或者在命令行下，进入到此工程目录下，执行ant ejbjar,将编译打包发布此EJB。<br /><br />　　在Eclipse的Ant视图中执行run target。或者在命令行下，进入到此工程目录下，执行ant run,测试这个EJB。</span><br /></td></tr></tbody></table></td></tr></tbody></table><img src ="http://www.blogjava.net/liaojiyong/aggbug/56459.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-07-04 09:27 <a href="http://www.blogjava.net/liaojiyong/archive/2006/07/04/56459.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB 3.0开发指南之多表映射</title><link>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56458.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Tue, 04 Jul 2006 01:26:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56458.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/56458.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56458.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/56458.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/56458.html</trackback:ping><description><![CDATA[在前面的例子中，我们每一个实体Bean只映射到数据库中的一张表上。事实上，一个实体Bean可以映射到多张表上。在一些需要字典表的项目上会经常用到，象以前我做过的项目，使用到很多国标规定的数据表。在我们下面这个例子中，性别作为一个字典表存在，学生这个实体将映射到学生信息表、性别表这两个表。 <br /><br />　　从表可以使用@SecondaryTable来注释：<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>@Target({TYPE}) @Retention(RUNTIME)<br /><br />public @interface SecondaryTable {<br />　String name();<br />　String catalog() default "";<br />　String schema() default "";<br />　JoinColumn[] join() default {};<br />　UniqueConstraint[] uniqueConstraints() default {};<br />}</td></tr></tbody></table><br />　　这个注释可以指定表名、分类、schema、联合列、约束等。假如你使用多张表，你可以使用下面的注释来声明多张表:<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>@SecondaryTable<br />@Target({TYPE}) @Retention(RUNTIME)<br /><br />public @interface SecondaryTables {<br />　SecondaryTable[] value() default {};<br />}</td></tr></tbody></table><br />　　这个例子主要有以下几个文件，这个例子主要实现了管理学生的功能。Student是一个实体Bean，这个Bean的name属性是一个类，也就是Name类，这个Name类就是一个依赖值对象。学生的性别映射到第二张表中。StudentDAOBean是一个无状态的会话Bean，用来调用实体Bean。和前面的例子一样，我们还是使用Client测试。<br /><br />　　这个例子和上一个例子基本相同，只是Student.java和Client有所不同。<br /><br />　　　Student.java：实体Bean。<br /><br />　　　Name.java：实体Bean所依赖的类。<br /><br />　　　StudentDAO.java：会话Bean的业务接口<br /><br />　　　StudentDAOBean.java：会话Bean的实现类<br /><br />　　　Client.java：测试EJB的客户端类。<br /><br />　　　jndi.properties：jndi属性文件，提供访问jdni的基本配置属性。<br /><br />　　　Build.xml：ant 配置文件，用以编译、发布、测试、清除EJB。<br /><br />　　下面针对每个文件的内容做一个介绍。<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>Student.java<br /><br />package com.kuaff.ejb3.secondary;<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 />import javax.ejb.SecondaryTables;<br />import javax.ejb.SecondaryTable;<br />import javax.ejb.JoinColumn;<br /><br />@Entity <br />@Table(name = "STUDENT")<br />@SecondaryTables({<br />@SecondaryTable(name = "GENDER", join = {@JoinColumn(name = "GENDER_ID")})<br />})<br /><br />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 />　private String gender;<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({ @DependentAttribute(name = "first", column ={ @Column(name = "FIRST") }), <br /><br />@DependentAttribute(name = "last", column ={ @Column(name = "LAST") }) }) <br /><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 />public void setGender(String gender)<br />{<br />　this.gender = gender;<br />}<br /><br />@Column(name = "gender", secondaryTable = "GENDER")<br /><br />public String getGender()<br />{<br />　return gender;<br />}<br /><br />}<br /></td></tr></tbody></table><br />　　Student.java实现了Student实体Bean，它提供学生的基本情况。在类上声明上加上了第二张表的注释：<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>@SecondaryTables({<br />@SecondaryTable(name = "GENDER", join = {@JoinColumn(name = "GENDER_ID")})<br />})</td></tr></tbody></table><br />　　在gender属性上加上了映射第二张的注释：<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>@Column(name = "gender", secondaryTable = "GENDER")<br /><br />Client.java<br /><br />package com.kuaff.ejb3.secondary;<br /><br />import javax.naming.InitialContext;<br /><br />import javax.naming.NamingException;<br /><br />import java.util.List;<br /><br /><br />public class Client<br />{<br />public static void main(String[] args) throws NamingException<br /><br />{<br /><br />InitialContext ctx = new InitialContext();<br /><br />StudentDAO dao = (StudentDAO) ctx.lookup(StudentDAO.class.getName());<br /><br />int id = dao.create("晁","岳攀","8","smallnest@kuaff.com","男");<br /><br />dao.create("朱","立焕","6","zhuzhu@kuaff.com","女");<br /><br /><br /><br />List list = dao.findAll();<br /><br />for(Object o:list)<br /><br />{<br /><br />Student s = (Student)o;<br /><br />System.out.printf("%s%s的性别:%s%n",s.getName().getFirst(),s.getName().getLast(),s.getGender());<br /><br />dao.evict(s);<br /><br />}</td></tr></tbody></table><br />　　这个客户端增加学生的分数，并且测试显示这个学生的email。<br /><br />　　请运行{$JBOSS_HOME}/bin目录下的run.bat: run –c all,启动JBOSS。<br /><br />http://localhost:8080/jmx-console/HtmlAdaptor?action=inspectMBean&amp;name=jboss%3Aservice%3DHypersonic%2Cdatabase%3DlocalDB，<br /><br />　　然后调用startDatabaseManager()方法，打开HSQL管理工具管理数据库。<br /><br />　　在Eclipse的Ant视图中执行ejbjar target。或者在命令行下，进入到此工程目录下，执行ant ejbjar,将编译打包发布此EJB。<br /><br />　　在Eclipse的Ant视图中执行run target。或者在命令行下，进入到此工程目录下，执行ant run,测试这个EJB。<br /><img src ="http://www.blogjava.net/liaojiyong/aggbug/56458.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-07-04 09:26 <a href="http://www.blogjava.net/liaojiyong/archive/2006/07/04/56458.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB 3.0开发指南之使用实体Bean</title><link>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56456.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Tue, 04 Jul 2006 01:25:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56456.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/56456.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56456.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/56456.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/56456.html</trackback:ping><description><![CDATA[　在上面一个例子中，实体Bean的属性对应到数据表中的列，都是采用默认的设置。通过Column，你可以为属性指定数据表中的列名。 <br />Column的声明如下：<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>@Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)<br />public @interface Column {<br />　String name() default "";<br />　boolean primaryKey() default false;<br />　boolean unique() default false;<br />　boolean nullable() default true;<br />　boolean insertable() default true;<br />　boolean updatable() default true;<br />　String columnDefinition() default "";<br />　String secondaryTable() default "";<br />　int length() default 255;<br />　int precision() default 0;<br />　int scale() default 0;<br />　boolean specified() default true; // For internal use only<br />}</td></tr></tbody></table><br />　　EntityManager 是用来处理实体Bean的辅助类。它可以用来产生/删除持久化的实体Bean，通过主键查找实体bean，通过查询语言来查询实体Bean。<br /><br />　　下面是EntityManager接口的声明：<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>package javax.ejb;<br /><br />import java.sql.Connection;<br />/**<br />* 用来和持久化上下文交互的接口<br />*/<br /><br />public interface EntityManager {<br /><br />　/**<br />　* 使实体bean受持久化管理<br />　* @param entity<br />　*/<br /><br />　public void create(Object entity);<br />　<br />　/**<br />　* 将给定的实体Bean的状态和持久化上下文结合。类似数据库的更新操作。<br />　* @param entity<br />　* @return 被结合的实体实例<br />　*/<br /><br />　public &lt;T&gt; T merge(T entity);<br /><br />　/**<br />　* 删除实例<br />　* @param entity<br />　*/<br /><br />　public void remove(Object entity);<br />　/**<br />　* 根据主键查找.<br />　* @param entityName<br />　* @param primaryKey<br />　* @return 查询实例<br />　*/<br /><br />　public Object find(String entityName, Object primaryKey);<br />　/**<br />　* 根据主键查找<br />　* @param primaryKey<br />　* @return 查询实例<br />　*/<br /><br />　public &lt;T&gt; T find(Class&lt;T&gt; entityClass, Object primaryKey);<br />　/**<br />　* 持久化上下文与底层数据库的同步<br />　*/<br /><br />　public void flush();<br />　/**<br />　* 执行一个EJBQL查询<br />　* @param ejbqlString EJBQL查询语句<br />　* @return the new query instance<br />　*/<br /><br />　public Query createQuery(String ejbqlString);<br />　/**<br />　* 执行命名的查询<br />　* @param name 预定义的查询名称<br />　* @return 查询实例<br />　*/<br /><br />　public Query createNamedQuery(String name);<br />　/**<br />　* 执行一个本地SQL查询语句<br />　* @param sqlString 本地查询语句<br />　* @return 返回查询实例<br />　*/<br /><br />　public Query createNativeQuery(String sqlString);<br />　/**<br />　* 更新到数据库中<br />　* @param entity<br />　*/<br /><br />　public void refresh(Object entity);<br />　/**<br />　* 持久化上下文中删除实体<br />　* @param entity<br />　*/<br /><br />　public void evict(Object entity);<br />　/**<br />　* 检查当前上下文中是否包含此实体<br />　* context.<br />　* @param entity<br />　* @return<br />　*/<br /><br />　public boolean contains(Object entity);<br />}<br /></td></tr></tbody></table><br />　　@JoinColumns<br /><br />　　用来指示符合主键，在后面的章节中介绍。<br /><br />　　 这个例子主要有以下几个文件，这个例子主要实现了管理学生分数的功能。Student是一个实体Bean，管理学生的基本信息（姓名和各课分数），其中学生的分数又是一个实体Bean。TacherBean是一个无状态的会话Bean，用来调用实体Bean。和前面的例子一样，我们还是使用Client测试。<br /><br />　　·Student.java：实体Bean。<br /><br />　　·Score.java：实体Bean。<br /><br />　　·Teacher.java：会话Bean的业务接口<br /><br />　　·TeacherBean.java：会话Bean的实现类<br /><br />　　·Client.java：测试EJB的客户端类。<br /><br />　　·jndi.properties：jndi属性文件，提供访问jdni的基本配置属性。<br /><br />　　·Build.xml：ant 配置文件，用以编译、发布、测试、清除EJB。<br /><br />　　下面针对每个文件的内容做一个介绍。<br /><br />　　Student.java<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>package com.kuaff.ejb3.entity;<br /><br />import javax.ejb.CascadeType;<br />import javax.ejb.Entity;<br />import javax.ejb.FetchType;<br />import javax.ejb.GeneratorType;<br />import javax.ejb.Id;<br />import javax.ejb.JoinColumn;<br />import javax.ejb.OneToMany;<br />import javax.ejb.Table;<br />import java.util.ArrayList;<br />import java.util.Collection;<br />import java.io.Serializable;<br /><br />@Entity<br />@Table(name = "STUDENT")<br /><br />public class Student implements Serializable<br />{<br />　//主键<br />　private int id;<br />　//学生名<br />　private String name;<br />　//学生的分数<br />　private Collection&lt;Score&gt; scores;<br />　//主键自动产生<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 String getName()<br />　{<br />　　return name;<br />　}<br /><br />　public void setName(String name)<br />　{<br />　　this.name = name;<br />　}<br /><br />　public void addScores(String name,int number)<br />　{<br />　　if (scores == null)<br />　　{<br />　　　scores = new ArrayList&lt;Score&gt;();<br />　　}<br />　　Score score = new Score();<br />　　score.setName(name);<br />　　score.setNumber(number);<br />　　score.setStudent(this);<br />　　scores.add(score);<br />　}<br /><br />　@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)<br />　@JoinColumn(name = "student_id")<br /><br />　public Collection&lt;Score&gt; getScores()<br />　{<br />　　return scores;<br />　}<br /><br />　public void setScores(Collection&lt;Score&gt; scores)<br />　{<br />　　this.scores = scores;<br />　}<br />}</td></tr></tbody></table><br />　　Student.java实现了Student实体Bean，它提供学生的基本情况以及学生的得分情况，得分是另外一个实体Bean。Student实体Bean和Score实体Bean是一对多的关系，站在Score的角度看是多对一的关系。<br /><br />　　实体Bean需要使用@Entity做注释，另外它指定这个实体Bean与表STUDENT对应（通过注释@Table(name = "STUDENT")），你可以在JBOSS的数据库中看到这个表。<br /><br />　　Score.java<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>package com.kuaff.ejb3.entity;<br /><br />import java.io.Serializable;<br />import javax.ejb.Entity;<br />import javax.ejb.GeneratorType;<br />import javax.ejb.Id;<br />import javax.ejb.JoinColumn;<br />import javax.ejb.ManyToOne;<br />import javax.ejb.Table;<br /><br />@Entity<br />@Table(name = "Score")<br /><br />public class Score implements Serializable<br />{<br />　private int id;<br />　private String name;<br />　private int number;<br />　private Student student;<br /><br />　//主键自动产生<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 String getName()<br />　{<br />　　return name;<br />　}<br /><br />　public void setName(String name)<br />　{<br />　　this.name = name;<br />　}<br /><br />　public int getNumber()<br />　{<br />　　return number;<br />　}<br /><br />　public void setNumber(int number)<br />　{<br />　　this.number = number;<br />　}<br /><br />　@ManyToOne<br />　@JoinColumn(name = "student_id")<br /><br />　public Student getStudent()<br />　{<br />　　return student;<br />　}<br /><br />　public void setStudent(Student student)<br />　{<br />　　this.student = student;<br />　}<br /><br />} </td></tr></tbody></table><br />　　这个实体Bean存放学生的分数。<br /><br />　　Teacher.java<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>package com.kuaff.ejb3.entity;<br /><br /><br /><br />import javax.ejb.Remote;<br /><br />import javax.ejb.Remove;<br /><br />import java.util.Map;<br /><br /><br /><br />@Remote<br /><br />public interface Teacher<br /><br />{<br /><br />public void addScore(String studentName,Map&lt;String,Integer&gt; map);<br /><br /><br /><br />public Student getStudent();<br /><br /><br /><br />@Remove<br /><br />public void leave();<br /><br />}</td></tr></tbody></table><br />　　这个会话Bean接口提供增加分数和得到用户的方法。<br /><br />　　TeacherBean.java<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>package com.kuaff.ejb3.entity;<br /><br />import javax.ejb.EntityManager;<br />import javax.ejb.Inject;<br />import javax.ejb.Remove;<br />import javax.ejb.Stateful;<br />import java.util.Map;<br />import java.util.Set;<br /><br />@Stateful<br /><br />public class TeacherBean implements Teacher<br />{<br />　@Inject<br />　private EntityManager manager;<br />　private Student student;<br /><br />　public Student getStudent()<br />　{<br />　　return student;<br />　}<br /><br />　public void addScore(String studentName, Map&lt;String,Integer&gt; map)<br />　{<br />　　if (student == null)<br />　　{<br />　　　student = new Student();<br />　　}<br />　　student.setName(studentName);<br />　　Set&lt;String&gt; set = map.keySet();<br />　　for (String sname:set)<br />　　{<br />　　　student.addScores(sname,map.get(sname).intValue());<br />　　}<br />　}<br /><br />　@Remove<br /><br />　public void leave()<br />　{<br />　　manager.create(student);<br />　}<br /><br /><br /><br />}<br /></td></tr></tbody></table><br />　　这个是会话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.entity;<br /><br />import java.util.Map;<br />import java.util.HashMap;<br />import java.util.Collection;<br />import javax.naming.InitialContext;<br />import javax.naming.NamingException;<br /><br />public class Client<br />{<br />　public static void main(String[] args) throws NamingException<br />　{<br />　　InitialContext ctx = new InitialContext();<br />　　Teacher teacher = (Teacher) ctx.lookup(Teacher.class.getName());<br />　　Map&lt;String,Integer&gt; map = new HashMap&lt;String,Integer&gt;();<br />　　map.put("语文",new Integer(98));<br />　　map.put("化学",new Integer(149));<br />　　map.put("物理",new Integer(143));<br />　　teacher.addScore("smallnest",map);<br />　　Student student = teacher.getStudent();<br />　　String name = student.getName();<br />　　System.out.printf("显示%s的分数:%n",name);<br />　　Collection&lt;Score&gt; c = student.getScores();<br /><br />　　for (Score score:c)<br />　　{<br />　　　System.out.printf("%s:%s%n",score.getName(),score.getNumber()+"");<br />　　}<br />　}<br />}<br /></td></tr></tbody></table><br />　　这个客户端增加学生的分数，并且测试显示这个学生的相关信息。<br /><br />　　请运行{$JBOSS_HOME}/bin目录下的run.bat: run –c all,启动JBOSS。<br /><br />http://localhost:8080/jmx-console/HtmlAdaptor?action=inspectMBean&amp;name=jboss%3Aservice%3DHypersonic%2Cdatabase%3DlocalDB，然后调用startDatabaseManager()方法，打开HSQL管理工具管理数据库。<br /><br />　　在Eclipse的Ant视图中执行ejbjar target。或者在命令行下，进入到此工程目录下，执行ant ejbjar,将编译打包发布此EJB。<br /><br />　　在Eclipse的Ant视图中执行run target。或者在命令行下，进入到此工程目录下，执行ant run,测试这个EJB。<br /><img src ="http://www.blogjava.net/liaojiyong/aggbug/56456.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-07-04 09:25 <a href="http://www.blogjava.net/liaojiyong/archive/2006/07/04/56456.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB 3.0 开发指南之依赖值对象</title><link>http://www.blogjava.net/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.blogjava.net/liaojiyong/archive/2006/07/04/56457.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/56457.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56457.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/56457.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/56457.html</trackback:ping><description><![CDATA[在上面的章节我们提到，实体bean的属性可以是java基本对象、Date等，事实上，实体Bean的属性也可以是其他的java对象。这些Java对象不能直接从持久化上下文中读取，它依赖于主实体bean。不象关联实体Bean，在EJB3.0中不支持依赖值对象的集合。 <br /><br />　　依赖值对象不支持继承，这将在EJB3.1中在讨论。<br /><br />　　依赖类需要使用◎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 />　　这个注释可以指定容器访问这个类的方法，是通过属性还是直接通过字段来访问。<br /><br />　　在实体Bean的一个属性需要使用依赖值对象，那么这个属性的get方法需要使用@Dependent注释：<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 />　　这个注释可以指定依赖的属性DependentAttribute：<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 />　　可以指定属性名称和映射的列名。这里，一个主实体Bean的属性可以映射到数据表中的多列。<br /><br />　　如果你还不太明白，看下面的例子。<br /><br />　　这个例子主要有以下几个文件，这个例子主要实现了管理学生的功能。Student是一个实体Bean，这个Bean的name属性是一个类，也就是Name类，这个Name类就是一个依赖值对象。StudentDAOBean是一个无状态的会话Bean，用来调用实体Bean。和前面的例子一样，我们还是使用Client测试。<br /><br />　　·Student.java：实体Bean。<br /><br />　　·Name.java：实体Bean所依赖的类。<br /><br />　　·StudentDAO.java：会话Bean的业务接口<br /><br />　　·StudentDAOBean.java：会话Bean的实现类<br /><br />　　·Client.java：测试EJB的客户端类。<br /><br />　　·jndi.properties：jndi属性文件，提供访问jdni的基本配置属性。<br /><br />　　·Build.xml：ant 配置文件，用以编译、发布、测试、清除EJB。<br /><br />　　下面针对每个文件的内容做一个介绍。<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实体Bean，它提供学生的基本情况。学生的姓名是Name类，通过@Dependent(<br /><br />{ @DependentAttribute(name = "first", column ={ @Column(name = "FIRST") }), <br /><br />@DependentAttribute(name = "last", column ={ @Column(name = "LAST") }) }) <br /><br />来声明，并指定这个依赖类的两个属性first和last，并映射到数据表的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 />　　这个值对象也很简单，和一般的javaBean差不多，但有两个地方需要注意：<br /><br />　　1． 这个类实现了java.io.Serializable接口<br /><br />　　2． 这个类使用@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 />　　这个会话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 />　　这个是会话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("晁","岳攀","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 />　　这个客户端增加学生的分数，并且测试显示这个学生的email。<br /><br />　　请运行{$JBOSS_HOME}/bin目录下的run.bat: run –c all,启动JBOSS。<br /><br />http://localhost:8080/jmx-console/HtmlAdaptor?action=inspectMBean&amp;name=jboss%3Aservice%3DHypersonic%2Cdatabase%3DlocalDB，然后调用startDatabaseManager()方法，打开HSQL管理工具管理数据库。<br /><br />　　在Eclipse的Ant视图中执行ejbjar target。或者在命令行下，进入到此工程目录下，执行ant ejbjar,将编译打包发布此EJB。<br /><br />　　在Eclipse的Ant视图中执行run target。或者在命令行下，进入到此工程目录下，执行ant run,测试这个EJB。<br /><img src ="http://www.blogjava.net/liaojiyong/aggbug/56457.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-07-04 09:25 <a href="http://www.blogjava.net/liaojiyong/archive/2006/07/04/56457.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB 3.0 开发指南之定时服务</title><link>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56455.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Tue, 04 Jul 2006 01:24:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56455.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/56455.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56455.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/56455.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/56455.html</trackback:ping><description><![CDATA[在EJB2.1的规范中需要实现ejbTimeout方法，当然还有ejbPassivate、ejbRemove等方法。在EJB3.0中，只有你想用它们的时候，你才必须创建它们，否则不必实现。 <br /><br />　　这个例子主要有5个文件，这个例子的Bean是一个无状态会话Bean：<br /><br />　　NewsTimer.java：业务接口。<br /><br />　　NewsTimer.java：业务实现类。将来我们开发的EJB也都是这样命名（在接口名上加上Bean）。<br /><br />　　Client.java：测试EJB的客户端类。<br /><br />　　jndi.properties：jndi属性文件，提供访问jdni的基本配置属性。<br /><br />　　Build.xml：ant 配置文件，用以编译、发布、测试、清除EJB。<br /><br />　　下面针对每个文件的内容做一个介绍。<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>NewsTimer.java<br /><br />package com.kuaff.ejb3.schedule;<br />import javax.ejb.Remote;<br />@Remote<br /><br />public interface NewsTimer<br />{<br />　public void fiveNews();<br />}<br /></td></tr></tbody></table><br />　　这个接口定义了fiveNews方法，如果这个方法被调用，5分钟后将往控制台上输出一条新闻。<br /><br />　　你不必配置它的JNDI名称，也不必写它的配置文件。在JBOSS实现的EJB3.0中，你不必写任何的EJB部署文件和jboss部署文件。JBOSS默认使用接口的全称作为它的JNDI名。在上面的例子中，它的全称可以通过NewsTimerclass.forName()得到。<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>NewsTimerBean.java<br /><br />package com.kuaff.ejb3.schedule;<br />import java.util.Date;<br />import javax.ejb.Inject;<br />import javax.ejb.SessionContext;<br />import javax.ejb.Stateless;<br />import javax.ejb.Timer;<br /><br />@Stateless<br /><br />public class NewsTimerBean implements NewsTimer<br />{<br />　private @Inject SessionContext ctx;<br />　public void fiveNews()<br />　{<br />　　ctx.getTimerService().createTimer(new Date(new Date().getTime() + 300000), "子虚乌有电视台5分钟新闻栏目:现在过5分钟，又到即时新闻节目的时间了。");<br />　}<br /><br />　public void ejbTimeout(Timer timer)<br />　{<br />　　System.out.printf("时间到:%n%s%n" , timer.getInfo());<br />　　timer.cancel();<br />　}<br />}<br /><br />Client.java<br /><br />package com.kuaff.ejb3.schedule;<br /><br />import javax.naming.InitialContext;<br />import javax.naming.NamingException;<br /><br />public class Client<br />{<br />　public static void main(String[] args) throws NamingException<br />　{<br />　　InitialContext ctx = new InitialContext();<br />　　NewsTimer timer = (NewsTimer) ctx.lookup(NewsTimer.class.getName());<br />　　timer.fiveNews();<br />　}<br />}<br /><br /></td></tr></tbody></table><br />　　这个类用来测试我们发布的计数器EJB。首先通过<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>ctx = new InitialContext();</td></tr></tbody></table><br />　　得到上下文，然后通过lookup查找NewsTimer，然后启动计时。。<br /><br />　　请运行{$JBOSS_HOME}/bin目录下的run.bat: run –c all,启动JBOSS。<br /><br />　　在Eclipse的Ant视图中执行ejbjar target。或者在命令行下，进入到此工程目录下，执行ant ejbjar,将编译打包发布此EJB。<br /><br />　　在Eclipse的Ant视图中执行run target。或者在命令行下，进入到此工程目录下，执行ant run,测试这个EJB。<br /><img src ="http://www.blogjava.net/liaojiyong/aggbug/56455.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-07-04 09:24 <a href="http://www.blogjava.net/liaojiyong/archive/2006/07/04/56455.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB 3.0开发指南之依赖注入</title><link>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56453.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Tue, 04 Jul 2006 01:23:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56453.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/56453.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56453.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/56453.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/56453.html</trackback:ping><description><![CDATA[依赖注入（Dependency Injection），又称作控制反转(IOC)，本来是一种设计模式，现在被吵得热火朝天，有点过了。比较有名项目如String,picoContainer等。 <br /><br />　　在EJB3.0中，可以通过在字段和设置方法上加上注释注入依赖，我想在很快会有新的项目，或者在原来的项目的基础上，一些IOC容器会采用注释的方式注入依赖，JDK5.0加入的注释的确是一个很强大的功能，相对而言，在.net中的属性却没有发挥那么大的价值。这就是开源的威力，成千上万的在开源java程序员不断涌现出新的想法新的功能。<br /><br />　　看下面的例子：我们知道,JBOSS中已经默认配置了一个数据源，它的JNDI名称是"java:/DefaultDS"。下面这个例子声明了一个数据源，通过注释，就可以将JBOSS的这个默认的数据源赋值给它。<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#d8d8d1" border="1"><tbody><tr><td>@Resource(jndiName="java:/DefaultDS") <br />public DataSource customerDB;<br />Resource注释的声明<br />@Target({TYPE, METHOD, FIELD, PARAMETER}) @Retention(RUNTIME)<br /><br />public @interface Resource {<br /><br />String name() default "";<br /><br />String resourceType() default "";<br /><br />AuthenticationType authenticationType() default CONTAINER;<br /><br />boolean shareable() default true;<br /><br />String jndiName() default "";<br /><br />}<br /><br /><br />public enum Authentication Type {<br /><br />CONTAINER,<br /><br />APPLICATION<br /><br />}<br /><br />@Target(TYPE) @Retention(RUNTIME)<br /><br />public @interface Resources {<br /><br />Resource[] value();<br /><br />}</td></tr></tbody></table><br />　　Resource的name指向一个在环境属性中命名的资源，AuthenticationType用来指定是容器还是EJB组件来进行身份验证，sharebale指定是否共享,jndiName用来指定JDNI中的名称。resourceType()用来指定资源的类型。<br /><br />　　如果name和resourceType都指向被注释的程序成员，AuthenticationType和resourceType都是缺省的，则可以使用Inject注释：<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#d8d8d1" border="1"><tbody><tr><td>@Inject(jndiName="java:/DefaultDS") <br /><br />public DataSource customerDB;</td></tr></tbody></table><br />　　对于单例的成员，你可以更简化：<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#d8d8d1" border="1"><tbody><tr><td>@Inject javax.ejb.SessionContext ctx;<br /><br />@Inject javax.ejb.TimerService timer;<br /><br />@Inject javax.ejb.UserTransaction ut;<br /><br />@Inject javax.ejb.EntityManager manager;</td></tr></tbody></table><br />　　Resources注释可以注入多个资源。<br /><br />　　在Eclipse中导入本文提供的例子DI。<br /><br />　　这个例子从数据库中读取JMS_USER表，并显示表中的内容。这个例子使用依赖注入的方式得到JBOSS默认的数据源。<br /><br />　　这个例子主要有5个文件：<br /><br />　　　JmsUsers.java：业务接口。<br /><br />　　　JmsUsersBean.java：业务实现类。将来我们开发的EJB也都是这样命名（在接口名上加上Bean）。<br /><br />　　　Client.java：测试EJB的客户端类。<br /><br />　　　jndi.properties：jndi属性文件，提供访问jdni的基本配置属性。<br /><br />　　　Build.xml：ant 配置文件，用以编译、发布、测试、清除EJB。<br /><br />　　下面针对每个文件的内容做一个介绍。<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#d8d8d1" border="1"><tbody><tr><td>JmsUsers.java<br /><br />package com.kuaff.ejb3.di;<br />import java.util.List;<br />import javax.ejb.Remote;<br />import javax.sql.*;<br /><br />@Remote<br />public interface JmsUsers<br />{<br />　public List&lt;String&gt; getUsers();<br />}</td></tr></tbody></table><br />　　这个接口很简单，定义了一个得到全部用户的方法，JBOSS默认使用接口的全称作为它的JNDI名。在上面的例子中，它的全称可以通过JmsUsers.class。getName（）得到。<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#d8d8d1" border="1"><tbody><tr><td>CounterBean.java<br /><br />package com.kuaff.ejb3.di;<br />import java.util.List;<br />import java.util.ArrayList;<br />import javax.ejb.Stateless;<br />import javax.ejb.Resource;<br />import javax.sql.*;<br />import java.sql.*;<br /><br /><br />@Stateless<br />public class JmsUsersBean implements JmsUsers<br />{<br />　@Resource(jndiName="java:/DefaultDS",resourceType="javax.sql.DataSource") <br />　public DataSource customerDB;<br />　public List&lt;String&gt; getUsers() <br />　{<br />　　List&lt;String&gt; list = new ArrayList&lt;String&gt;();<br />　　try<br />　　{<br />　　　Connection conn = customerDB.getConnection();<br />　　　Statement st = conn.createStatement();<br />　　　ResultSet rs = st.executeQuery("select * from jms_users");<br />　　　while(rs.next())<br />　　　{<br />　　　　list.add(rs.getString("userid"));<br />　　　}<br />　　}<br />　　catch(SQLException e)<br />　　{}<br />　　return list;<br />　}<br />}</td></tr></tbody></table><br />　　这个是业务逻辑的具体实现。一旦这个EJB被容器产生，则容器将JBOSS的数据源注入到customerDB变量上，所以不要以为customerDB没有被初始化，这些工作是容器做的。<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#d8d8d1" border="1"><tbody><tr><td>Client.java<br /><br />package com.kuaff.ejb3.di;<br />import java.util.List;<br />import javax.naming.InitialContext;<br />import javax.naming.NamingException;<br /><br />public class Client<br />{<br />　public static void main(String[] args)<br />　{<br />　　InitialContext ctx;<br />　　try<br />　　{<br />　　　ctx = new InitialContext();<br />　　　JmsUsers users = (JmsUsers) ctx.lookup(JmsUsers.class.getName());<br />　　　List&lt;String&gt; jmsUsers = users.getUsers();<br />　　　for(String user:jmsUsers)<br />　　　{<br />　　　　System.out.printf("用户名:%s%n",user);<br />　　　}<br />　　}<br />　　catch (NamingException e)<br />　　{<br />　　　e.printStackTrace();<br />　　}<br />　}<br />}</td></tr></tbody></table><br />　　这个类用来测试我们发布的EJB组件。显示从JMS_USERS表中读取的数据。<br /><br />　　请运行{$JBOSS_HOME}/bin目录下的run.bat: run ?call,启动JBOSS。<br /><br />　　在Eclipse的Ant视图中执行ejbjar target。或者在命令行下，进入到此工程目录下，执行ant ejbjar,将编译打包发布此EJB<br /><br />　　在Eclipse的Ant视图中执行run target。或者在命令行下，进入到此工程目录下，执行ant run,测试这个EJB。<br /><img src ="http://www.blogjava.net/liaojiyong/aggbug/56453.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-07-04 09:23 <a href="http://www.blogjava.net/liaojiyong/archive/2006/07/04/56453.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB 3.0开发指南之消息驱动Bean</title><link>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56454.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Tue, 04 Jul 2006 01:23:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56454.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/56454.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/07/04/56454.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/56454.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/56454.html</trackback:ping><description><![CDATA[消息驱动Bean的业务接口已经被定义，对于使用JMS来说那就是MessageListener接口，这个接口定义了OnMessage方法。 <br /><br />　　实现类必须使用MessageDriven注释。可以实现也可以不实现setMessageDrivenContext和ejbRemove方法。<br /><br />　　在JBOSS中，通过ConnectionConfig指定消息的队列的JNDI名称。<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#d8d8d1" border="1"><tbody><tr><td>@ConnectionConfig(destinationType = javax.jms.Queue.class, destinationJndiName = "queue/kuaffejb3/sample", durable = true, subscriptionId = "kuaffMessage")</td></tr></tbody></table><br />　　在Eclipse中导入本文提供的例子Messager。<br /><br />　　这个例子从客户端发送一个TextMessage，这个Bean组件接收到这个消息后，将把这个消息输出到控制台上。<br /><br />　　这个例子主要有5个文件：<br /><br />　　　Messager.java：业务组件。<br />　　<br />　　　Client.java：测试EJB的客户端类。<br />　<br />　　　jndi.properties：jndi属性文件，提供访问jdni的基本配置属性。<br /><br />　　　Build.xml：ant 配置文件，用以编译、发布、测试、清除EJB。<br /><br />　　　queue-example-service.xml：消息服务，用来测试消息。<br /><br />　　下面针对每个文件的内容做一个介绍。<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#d8d8d1" border="1"><tbody><tr><td>Messager.java<br /><br />package com.kuaff.ejb3.messager;<br /><br />import org.jboss.ejb3.mdb.ConnectionConfig;<br />import javax.ejb.MessageDriven;<br />import javax.jms.JMSException;<br />import javax.jms.Message;<br />import javax.jms.TextMessage;<br />import javax.jms.MessageListener;<br /><br />@MessageDriven <br />@ConnectionConfig(destinationType = javax.jms.Queue.class, destinationJndiName = "queue/kuaffejb3/sample", durable = true, subscriptionId = "kuaffMessage") <br /><br />public class Messager implements MessageListener<br />{<br />　public void onMessage(Message recvMsg)<br />　{<br />　　System.out.println("接收到的消息:");<br />　　try<br />　　{<br />　　　TextMessage message = (TextMessage)recvMsg;<br />　　　System.out.println(message.getText());<br />　　}<br />　　catch (JMSException e)<br />　　{<br />　　　e.printStackTrace();<br />　　}<br />　}<br />}</td></tr></tbody></table><br />　　这个消息Bean很简单，接收到消息后不做什么处理，就是将消息内容输出到控制台上，<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#d8d8d1" border="1"><tbody><tr><td>Client.java<br /><br />package com.kuaff.ejb3.messager;<br /><br />import javax.jms.Queue;<br />import javax.jms.QueueConnection;<br />import javax.jms.QueueConnectionFactory;<br />import javax.jms.QueueSender;<br />import javax.jms.QueueSession;<br />import javax.jms.TextMessage;<br />import javax.naming.InitialContext;<br /><br />public class Client<br />{<br />　public static void main(String[] args) throws Exception<br />　{<br />　　QueueConnection cnn = null;<br />　　QueueSender sender = null;<br />　　QueueSession session = null;<br />　　InitialContext ctx = new InitialContext();<br />　　Queue queue = (Queue) ctx.lookup("queue/kuaffejb3/sample");<br />　　QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup("ConnectionFactory");<br />　　cnn = factory.createQueueConnection();<br />　　session = cnn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);<br />　　TextMessage msg = session.createTextMessage("江湖快报:玉树临风风流倜傥的公子小巢又出现了。");<br />　　sender = session.createSender(queue);<br />　　sender.send(msg);<br />　　System.out.println("消息已经发出");<br />　}<br />}</td></tr></tbody></table><br />　　这个客户端将发送一个文本消息到队列中。<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#d8d8d1" border="1"><tbody><tr><td>queue-example-service.xml<br />＜?xml version="1.0" encoding="UTF-8"?＞<br />＜server＞<br />＜mbean code="org.jboss.mq.server.jmx.Queue" name="jboss.mq.destination:service=Queue,name=kuaffMessage"＞<br />　＜attribute name="JNDIName"＞queue/kuaffejb3/sample＜/attribute＞<br />　＜depends optional-attribute-name="DestinationManager"＞jboss.mq:service=DestinationManager＜/depends＞<br />＜/mbean＞<br />＜/server＞</td></tr></tbody></table><br />　　配置这个程序所需的消息服务。<br /><br />　　请运行{$JBOSS_HOME}/bin目录下的run.bat: run ?call,启动JBOSS。<br /><br />　　在Eclipse的Ant视图中执行ejbjar target。或者在命令行下，进入到此工程目录下，执行ant ejbjar,将编译打包发布此EJB。<br /><br />　　在Eclipse的Ant视图中执行run target。或者在命令行下，进入到此工程目录下，执行ant run,测试这个EJB。 <br /><br /><br /><img src ="http://www.blogjava.net/liaojiyong/aggbug/56454.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-07-04 09:23 <a href="http://www.blogjava.net/liaojiyong/archive/2006/07/04/56454.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3.0开发指南之有状态会话Bean(转)</title><link>http://www.blogjava.net/liaojiyong/archive/2006/07/03/56244.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Mon, 03 Jul 2006 01:43:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/07/03/56244.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/56244.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/07/03/56244.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/56244.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/56244.html</trackback:ping><description><![CDATA[　和无状态会话Bean一样，一个有状态会话Bean必须有一个业务接口，这个接口由会话Bean来实现，或者也可以由会话Bean来产生。这样，你可以只写一个文件，就可以生成业务逻辑实现类、远程接口、本地接口等。 <br /><br />　　在目前jboss的实现中，必须要有一个独立的业务接口。<br /><br />　　这个接口不必实现EJBObject或者EJBLocalObject。<br /><br />　　一个有状态会话Bean 必须使用Statelfull注释，以表明它是一个有状态的会话Bean。EJB容器将根据这个注释来判定它的类型。或者实现javax.ejb.SessionBean接口。<br /><br />　　一个有状态的会话Bean可以实现setSessionContext方法，也可以不实现。<br /><br />　　在EJB2.0中调用EJBObject.remove方法以达到从容器中删除有状态会话Bean的功能。在EJB3.0中只需在一些方法加上Remove注释。一旦这些被标记的方法被调用后，此EJB将从容器中删除。<br /><br />　　一个有状态的会话Bean可以通过依赖注入获取容器的资源和环境属性。<br /><br />　　在Eclipse中导入本文提供的例子Stateful。<br /><br />　　这个例子和无状态会话Bean的例子类似，下面只列出了不同的代码。<br /><br />　　这个例子主要有5个文件：<br /><br />　　　Counter.java：业务接口。<br /><br />　　　CounterBean.java：业务实现类。将来我们开发的EJB也都是这样命名（在接口名上加上Bean）。<br /><br />　　　Client.java：测试EJB的客户端类。<br /><br />　　　jndi.properties：jndi属性文件，提供访问jdni的基本配置属性。<br /><br />　　　Build.xml：ant 配置文件，用以编译、发布、测试、清除EJB。<br /><br />　　下面针对每个文件的内容做一个介绍。<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#d8d8d1" border="1"><tbody><tr><td>Counter.java<br />……<br />import javax.ejb.Remove;<br />……<br />@Remote<br /><br />public interface Counter<br />{<br />　……<br />　@Remove<br />　public void clean();<br />}</td></tr></tbody></table><br /><br />　　这个接口很简单，和无状态会话Bean基本相同，但新增加了一个Clean方法，并为此方法加上Remove注释。一旦此方法被执行完毕，此Bean将被从容器中删除。<br /><br />　　JBOSS默认使用接口的全称作为它的JNDI名。在上面的例子中，它的全称就是：com.kuaff.ejb3.stateful.Counter，你也可以通过Counter.class得到。<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#d8d8d1" border="1"><tbody><tr><td>CounterBean.java<br />……<br />import javax.ejb.Stateful;<br />……<br />@Stateful<br /><br />public class CounterBean implements Counter<br />{<br />　//增加事务支持 <br />　@Tx(TxType.REQUIRESNEW)<br />　public int getNumber()<br />　{<br />　　return number;<br />　}<br /><br />　@Remove<br /><br />　public void clean()<br />　{<br />　　System.out.println("我，被删除了!");<br />　}<br />}</td></tr></tbody></table><br />　　这个是计数器的实现类。注意这个类使用Stateful做了注释，这是必须的。同时，这个例子也演示了如何使用事务。事务的详细用法将在后面的章节中介绍。<br /><br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#d8d8d1" border="1"><tbody><tr><td>Client.java<br />package com.kuaff.ejb3.stateful;<br /><br />import javax.ejb.EJBException;<br />import java.rmi.NoSuchObjectException;<br />import javax.naming.InitialContext;<br />import javax.naming.NamingException;<br /><br />public class Client<br />{<br />　public static void main(String[] args)<br />　{<br />　　InitialContext ctx;<br />　　try<br />　　{<br />　　　ctx = new InitialContext();<br />　　　Counter counter = (Counter) ctx.lookup(Counter.class.getName());<br />　　　counter.add(10);<br />　　　System.out.println("当前的number:" + counter.getNumber());<br />　　　counter.add(10);<br />　　　System.out.println("当前的number:" + counter.getNumber());<br />　　　Counter counter2 = (Counter) ctx.lookup(Counter.class.getName());<br />　　　counter2.add(10);<br />　　　System.out.println("当前的number:" + counter2.getNumber());<br />　　　//删除<br />　　　counter2.clean();<br />　　　//下面如果再使用counter2,将出错<br />　　　try<br />　　　{<br />　　　　System.out.println("当前的number:" + counter2.getNumber());<br />　　　}<br />　　　catch(EJBException ex)<br />　　　{<br />　　　　if (ex.getCausedByException() instanceof NoSuchObjectException)<br />　　　　{<br />　　　　　System.out.println("我都被删除啦，还找我！");<br />　　　　}<br />　　　　else<br />　　　　{<br />　　　　　throw ex;<br />　　　　}<br />　　　}<br />　　}<br />　　catch (NamingException e)<br />　　{<br />　　　e.printStackTrace();<br />　　}<br />　}<br />}</td></tr></tbody></table><br />　　这个类用来测试我们发布的计数器EJB。首先通过<br /><br />　　ctx = new InitialContext();得到上下文，然后通过lookup查找计数器，然后给计数器加10，显示当前的计数器信息。最后调用Clean方法，一旦这个方法执行完毕，此EJB将从容器中删除，在使用这个EJB将会出现异常。<br /><br />　　请运行{$JBOSS_HOME}/bin目录下的run.bat: run ?call,启动JBOSS。<br /><br />　　在Eclipse的Ant视图中执行ejbjar target。或者在命令行下，进入到此工程目录下，执行ant ejbjar,将编译打包发布此EJB。<br /><br />　　在Eclipse的Ant视图中执行run target。或者在命令行下，进入到此工程目录下，执行ant run,测试这个EJB。<br /><p><strong><font color="#212121" size="5"></font></strong> </p><img src ="http://www.blogjava.net/liaojiyong/aggbug/56244.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-07-03 09:43 <a href="http://www.blogjava.net/liaojiyong/archive/2006/07/03/56244.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB设计模式概述（转）</title><link>http://www.blogjava.net/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.blogjava.net/liaojiyong/archive/2006/07/03/56241.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/56241.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/07/03/56241.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/56241.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/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 href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=EJB">EJB</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=设计模式">设计模式</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=pattern">pattern</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=session bean">session bean</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=entity bean">entity bean</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=message driven bean">message driven bean</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=command">command</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=dto">dto</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=factory">factory</a></td>
								<td>
										<table class="box_content" cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td>
																		<span class="h2b">文章工具</span>
																		<br />
																		<img height="10" alt="推荐给朋友" src="http://dev2dev.bea.com.cn/images/letter001.gif" width="19" align="absMiddle" /> <a href="javascript:sendmail()">推荐给朋友</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 class="beas">
				<img height="1" alt="" src="http://dev2dev.bea.com.cn/images/dot6B6B6B.gif" width="100%" />
		</div>一． 设计模式重要性<br />采用ＥＪＢ技术的Ｊ２ＥＥ项目中，ＥＪＢ架构的设计好坏将直接影响系统的性能、可扩展性、可维护性、组件可重用性及开发效率。项目越复杂，项目队伍越庞大则越能体现良好设计的重要性。 
<p>二． 常见EJB设计模式<br /><br />Session Facade Pattern <br />通常项目中，客户端往往需要频繁的对服务器端数据进行操作。当采用实体ＥＪＢ作为数据的抽象层时，如果直接让客户端程序与实体ＥＪＢ交互，会产生实现一个业务需求便需要大量的ＥＪＢ属性操作（如下图１）。这直接导致如下问题：网络负载大（远程客户端时）、并发性能低、客户端与服务器端关联度大、可重用性和可维护性差、性能 <br />因此有必要在客户端与实体ＥＪＢ层间加入Session　ＥＪＢ层，在Sessino EJB中实现商业逻辑并封装对实体ＥＪＢ的操作。（如下图２）<br /><img height="384" src="http://dev2dev.bea.com.cn/images/article/other031028/image001.jpg" width="573" /><br />图１：客户端直接与实体ＥＪＢ交互<br /><img height="407" src="http://dev2dev.bea.com.cn/images/article/other031028/image002.gif" width="543" /><br />图２：通过SessionEJB层实现<br />Session Fa?ade模式的好处是：降低了网络负载，SessionEjb可以调用实体ＥＪＢ的本地接口；将商业逻辑与商业数据隔离；维护与开发方便；显著提高性能。<br />Session Fa?ade模式因其简单使用，是目前使用很广的模式。但具体应用过程中应注意：避免将所有的操作封装到一个很大的SessionEJB内；服务器端数据结构应由实体EJB实现,除非特例否则避免直接的数据库操作；SessionEjb内某些系统通用操作的代码容易重复（比如权限检查等，解决办法是将系统通用服务封装在Java Class内）。</p><p><b>Message Facade Pattern</b><br />很多时候，一次Request需要操作多个ＥＪＢ又不需要得到即时返回。对这种异步调用，通常应用Message Fa?ade Pattern.<br />这种时候，如采用Session Fa?ade Pattern存在如下问题：<br />1. 客户端等待返回的时间过长。一个SessionEjb的实例在完成客户请求过程中中涉及到的每一次对其他实体Ejb的调用过程中都会被锁定直到得到实体EJB返回信息后才能进行下一步操作。这样造成客户不必要的等待，并很容易因时间导致整个事务失败。<br />2. 系统可靠性和容错性低。如果需要调用不同系统或服务器上或多个异构数据源的多个ＥＪＢ时，任何一个环节出错，均导致客户请求失败。<br />以Message-Driven Bean为基础的Message Facade Pattern则可以解决上述异步请求需求。具体架构见下图３ <br /><img height="427" src="http://dev2dev.bea.com.cn/images/article/other031028/image004.jpg" width="672" /><br />　图３：使用Message Facade Pattern</p><p>Message Facade Pattern的不足之处在于：<br />１． Message-Driven Bean没有返回值。这样通知客户执行结果只能依赖于Ｅｍａｉｌ或人工等其他手段。<br />２． Message-Driven Bean执行过程中无法将捕获的异常直接返回给客户端，即无法使客户端直接直到错误信息。<br />３． Message-Driven Bean通过接收Message响应客户请求，对Message内容的合法性（比如对象的类型等）依赖与客户端.容易产生运行时错误。<br />Message Facade Pattern经常与Session Facade Pattern在同一个项目里共同使用。</p><p><b>EJB Command Pattern</b></p><p>Session Facade Pattern中将商业逻辑实现封装在Session EJB中，这种做法带来诸多益处之外也带来如下问题：<br />１． 由于业务经常的变化，导致经常需要更新Session EJB代码。<br />２． 客户端代码不得不包含大量EJB相关的ＡＰＩ，不利于后期项目维护。<br />３． 项目开发测试需要经常的EJB重部署过程。<br />引起上述问题的重要根结就是Session EJB本身重量级组件，其开发测试部署工作量较大，开发周期较长。以上不足可以通过EJB Command Pattern克服。<br />EJB Command Pattern中将商业逻辑实现封装在普通的Java Class（称之为Command Bean）中。该模式的具体实现有很多种，通常的框架都包括三部分： <br />１． Command Bean.由应用开发者写的具体实现某商业操作的Java Class.主要包含getXXX(),setXXX(),execute()方法。<br />２． Client-Side Routing Logic.由多个Class组成，用于将请求转发至Command Sever，这个过程对客户是透明的。这部分代码可以跨项目使用。路由规则中可以考虑用ＸＭＬ技术。<br />３． Remote Command Server.实际执行商业操作请求。通常可以用Session EJB层实现。</p><p>　整个框架见下图４：<br /></p><p><br /><img height="415" src="http://dev2dev.bea.com.cn/images/article/other031028/image006.jpg" width="684" /><br />　图４：Command的基本框架<br />EJB Command Pattern具有如下好处：<br />１． 适应与需要快速开发环境。因Command Bean是轻量级的Java Class，其编译和调试比较方便。<br />２． 将表现层与商业实现层隔离，同时将客户端代码与EJB层隔离。<br />３． 将客户端代码开发与服务器端代码开发相对清晰。早期可以创建空的Command Bean方便客户端代码调试。<br />　　　　EJB Command Pattern的弱处在于：<br />１． Command Bean中对事务的控制不如Session EJB中。<br />２． Command Bean是无状态的。<br />３． 无法将异常直接返回给客户。<br />４． 在大项目中，由于商业逻辑复杂，常导致大数量的Command Bean存在.<br />５． 作为Command Server的Session EJB打包时必须包含Command Bean以致存在维护上的不便。<br />　　EJB Command Pattern的一个实际实现可以参考IBM's Command Framework.</p><p><br /><b>Data Transfer Object Factory</b><br />基于EJB的J2EE项目，经常需要在客户端与服务器端传输大量数据。数据的组织形式常用的是DTO(Data Transfer Object，服务器端数据对象的抽象)。但因为客户端表现层经常是变化的，所需要服务器端数据也变动频繁，换句话说，DTO的数量和属性经常要更改。因此如何以及在何处生成和维护DTO便是需要考虑的问题。<br />一种解决方案是直接在Entity EJB中直接处理，即在Entity EJB的Bean类中加入getXXXDTO()、setXXXDTO()等。但这样做导致EJB与DTO层紧紧绑定。一旦DTO更改，与该DTO相关的EJB即需要重编译打包。EJB层与客户端层相关联不仅使维护困难而且导致EJB的重用性大大降低。<br />更好的解决方案是利用Data Transfer Object Factory封装对DTO的操作逻辑（如下图６）。<br /></p><p><img height="293" src="http://dev2dev.bea.com.cn/images/article/other031028/image008.jpg" width="278" /><br />图６：DTO Factory示例<br />DTO Factory具体实现方式通常有两种：<br />１． 普通Java Class实现，用于Session Facade Pattern使用DTO环境下。<br />２． Stateless Session EJB实现，用于非EJB客户端使用DTO环境下（见图７）。<br /></p><p><img height="382" src="http://dev2dev.bea.com.cn/images/article/other031028/image010.jpg" width="624" /><br />图７：SessionEJB实现DTOFactory<br />DTO Factory带来如下好处：<br />１． 使Entity EJB的重用成为可能。由于不含DTO处理逻辑，Entity EJB功能单一化，只作为数据源。不通客户端通过各自的DTO Factory可以从同一个Entity EJB得到各自所需的个性化数据（自定义DTO）。<br />２． 提高可维护性和性能。<br />３． 可以根据在DTO Factory层生成很复杂的DTO结构，诸如继承、关联关系等，而对客户端提供一个透明、细化的数据接口。<br />　　　使用DTO Factory时需要注意的是：不需为每个Entity EJB定义一个Factory。可以为一系列相关的Entity EJB创建一个Factory，或者只创建一个Factory。</p><p><b>Generic Attribute Access</b></p><p>使用Entity EJB作为商业数据层时，我们首先需要从数据库加载数据，创建对应的Entity EJB实例，之后对内存中Entity EJB实例的属性进行相应操作。对属性的操作比较直接的做法是：直接调用Entity EJB的getXXX()/setXXX()，通常利用EJB2.0的本地接口；通过DTO Factory生成DTO。但这两种做法都存在如下问题：<br />１． 当Entity EJB的属性特别多时候，以上做法会带来复杂罗嗦的代码，使EJB变的庞大无比。<br />２． 使Entity EJB的客户端（比如Session EJB）和Entity EJB的接口紧密关联。Entity EJB属性的增删都需要更改客户端代码，给项目开发和维护带来不便。<br />事实上可以利用更通用的方式访问Entity EJB的属性，即定义Generic Attribute Access Interface。见下图８：<br /></p><p><img height="118" src="http://dev2dev.bea.com.cn/images/article/other031028/image012.jpg" width="588" /><br />　图８：Generic Attribute Access Interface示例</p><p>Generic Attribute Access Interface由Entity EJB的本地或远程接口实现，并利用Hash Maps传输数据。实现方式常见如下：<br />１． BMP类型实体EJB可以在Bean类中定义包含所有属性的私有成员变量HashMap。<br />２． CMP类型实体EJB可以在Bean类中可以适用Java Reflection API实现。<br />３． 建立一个父类，在不同的情况下定义子类重载父类方法。<br />使用Generic Attribute Access Interface需要在客户端与服务器端对属性以及对应的关键字建立统一的命名习惯。常见的做法如下：<br />１． 建立并保持良好的文档记录和命名约定。<br />２． 在实体EJB的实现类中定义静态成员映射属性。<br />３． 创建共享静态类，通过成员变量映射实体EJB属性。<br />４． 通过JNDI在服务器端保存属性映射关系。<br />Generic Attribute Access Interface的运用带来一下益处：<br />１． 接口实现后对不通实体EJB都适用。<br />２． 对属性较多实体EJB能精简代码，并更具维护性。<br />３． 使运行中动态增删实体EJB属性成为可能。<br />Generic Attribute Access Interface的缺点在于：<br />１． 访问EJB属性时增加了额外的操作。需要通过关键字映射属性，最后还需进行类型转换。<br />２． 需要建立客户端与服务器端的命名约定。 <br />３． 因为通过HashMap操作时候需要进行类型转换，容易产生运行时类型不匹配异常。</p><p><b><br />Business Interface </b></p><p>EJB规范要求Bean实现类必须实现所有在远程（或本地）接口中定义的所有方法，同时不允许Bean实现类直接继承远程（或本地）接口。这就导致编译时候很容易产生两者不一致的问题，即远程（或本地）接口中定义的某方法为在Bean实现类中被实现等错误。为避免上诉错误，可以利用应用服务器厂商所提供的工具。但也可以应用EJB的设计架构来实现：定义商业接口。<br />Business Interface即创建自定义商业接口，在接口中定义所有EJB提供的商业方法，并让Bean实现类和远程（或本地）接口都实现该商业接口。其继承关系见下图９：<br /></p><p><img height="464" src="http://dev2dev.bea.com.cn/images/article/other031028/image014.jpg" width="552" /><br />图９：商业接口的使用<br />Business Interface是个普通的Java Class。依赖于使用本地接口与远程接口的不通，Business Interface的定义略有不同：应用与远程接口时，在接口中的方法需要抛出java.rmi.RemoteException；而应用与本地接口时候则不需要作任何特别处理。<br />应用Business Interface时候必须注意一点：EJB规范不允许直接EJB的实例将对自己的引用（this对象）返回给客户端，否则编译时候即报错。但使用Business Interface后，编译时候无法检查出有无将this对象返回给客户端。这一点需要程序员自己保证。</p><p><br />三． 内部数据转换策略</p><p><b>Data Transfer Object</b><br />基于EJB的J2EE多层架构应用中，经常涉及的一个问题就是如何在各层之间传递批量数据，比如客户端对服务器端数据的批量读写操作等。比如需要得到实体EJB的属性，直接的方法是多次调用不通的属性，如下图１０：<br /></p><p><img height="324" src="http://dev2dev.bea.com.cn/images/article/other031028/image016.jpg" width="496" /><br />图１０：低效的数据传递方式<br />　　但这种方法容易导致许多问题，比如性能以及代码的复杂度等，更有效的办法是在一个调用中得到所有需要的属性。所以可以引入Data Transfer Object来封装所需要的属性，并在客户与服务器端通过传递该对象一次实现对数据的操作。如下图１１：<br /><img height="310" src="http://dev2dev.bea.com.cn/images/article/other031028/image017.gif" width="501" /><br />　图１１：通过DTO传递数据<br />　　<br />DTO为普通的Java Class，通常是服务器端数据的快照。由于网络传输的需要，DTO应该实现java.io.Serializable接口。<br />DTO的设计有两种模型：Domain DTO以及Custom DTO。<br />Domain DTO仅仅实现对服务器数据的拷贝，通常与实体EJB为一对一的关系(也存在为多个相关联的实体EJB对应一个Domain DTO)。Domain DTO通常除用于读取更改实体EJB属性外也可用于创建实体EJB时候。实体EJB与Domain DTO对应关系如下图１２：<br /><img height="244" src="http://dev2dev.bea.com.cn/images/article/other031028/image018.gif" width="467" /><br />　图１２：Account EJB 与　Account DomainDTO<br />Domain DTO的应用除了DTO所具有的一般优点外，还有别的益处：<br />１． 开发迅速。因为一旦实体EJB设计好后，很容易转换得到Domain DTO。<br />２． 可以利用Domain DTO的setXXX()方法在客户端进行属性有效性效验。<br />Domain DTO的缺点有：<br />１． 客户端绑定了服务器端数据模型，不利于维护。<br />２． 不够灵活，无法处理客户端的多样化数据要求。对一个数百个属性的实体EJB请求一个属性时候却返回一个包含所有属性值的Domain DTO明显是笨重的实现。<br />３． 导致代码的重复。<br />４． Domain DTO中如果嵌套包含了别的Domain DTO时，一旦需服务器端数据的更改而需要重定义Domain DTO模型时候异常困难。</p><p>Custom DTO则可以克服上述的一些缺点。Customer DTO仅仅封装用户感兴趣的服务器数据集即可以根据客户端需求创建Customer DTO。这样作的优点是灵活高效；缺点是大项目中可能导致大量的Customer DTO存在。<br />通常Domain DTO可以用于数据的更新与创建；Customer DTO可以用于客户用于表现层的数据读取。两者可以相辅相成。而且使用DTO一般与DTO Factory同时使用。</p><p><b>Domain Transfer Hash Map</b><br />　　DTO的使用往往缺乏通用性。不通的用户案例需要创建不同的DTO。当项目很复杂时，从维护性考虑需要更好的数据传输的实现方式。 <br />Domain Transfer Hash Map即利用HashMap作为客户所需数据集的封装。好处是：<br />１． 良好的维护性。<br />２． 较大的通用性。不同的客户端可以使用相同的数据传递方式。<br />缺点是：<br />１． 需要维护客户端与服务器端在属性及其对应关键字的映射关系。<br />２． 当需要使用基本类型的数据时候，因为Hash Map的限制必须将基本类型先转换成对象。<br />３． 使用得到的数据时，需要进行类型强制转换。</p><p>Data Transfer RowSet<br />当需要处理直接的JDBC调用得到的结果集时，显然用DTO/Hash Map已经不合适，因为需要对大量数据进行类型转换等额外操作是很费资源和不必要的，而且最终用户常需要以表格式样显示数据。 <br />所以对二维表式数据，更好的处理方式是利用Data Transfer RowSet。Data Transfer RowSet通过将ResultSet直接转换为RowSet传递给客户端。<br />在Session EJB中使用RowSet的一段示例代码如下图１３：<br /><img height="170" src="http://dev2dev.bea.com.cn/images/article/other031028/image019.gif" width="467" /><br />图１３：使用RowSet<br />使用RowSet的好处很多：<br />１． 接口通用于各样的数据库查询操作。<br />２． 当需要表格式数据显示时，因为直接从ResultSet得到，所以不需要额外的数据类型转换。<br />缺点是：<br />１． 数据库结构暴露给客户端。<br />２． 不符合面向对象设计思想。<br />３． 依赖于SQL。<br />Data Transfer RowSet通常用于只读式数据的显示操作，经常和JDBC for Reading Pattern连用。</p><p>四．事务和数据持久机制</p><p>　　<b>JDBC for Reading Pattern</b><br /><br />基于EJB的J2EE应用中，通过EJB对数据库的操作可以有两种方式：实体EJB或者Session EJB中直接利用JDBC访问。<br />客户很多时候取出数据库中数据并以表格方式显示。这种情形如果使用实体EJB会导致如下问题：<br />１． 引用服务器端频繁的数据库查询和加载操作。因为加载N个实体EJB总需要进行一次find()操作　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　N次数据加载。<br />２． 如果使用Remote接口，引起频繁的额外网络操作。<br />３． 对关联关系比较复杂的数据库表结构，很难直接通过Entity EJB表现。<br />因此建议在只需对数据库表数据进行只读访问时候，应该采用JDBC for Reading Pattern，即通过JDBC直接访问数据库。除了避免上述使用实体EJB的缺点还带来一下好处：<br />１． 充分利用数据库能力，比如数据库的缓存机制。<br />２． 减少了对事务控制的资源。<br />３． 利用自定义SQL可以按需要比较灵活的读取数据。<br />４． 只需要一次数据查询，减少了数据库操作。<br />缺点是：<br />１． 于J2EE应用的面向对象设计相违背。<br />２． 因为Session EJB代码中包含了自定义SQL，维护性差。<br />３． Session EJB中不得不包含JDBC的API，并且需要了解数据库结构。</p><!--文章其他信息--><img src ="http://www.blogjava.net/liaojiyong/aggbug/56241.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-07-03 09:30 <a href="http://www.blogjava.net/liaojiyong/archive/2006/07/03/56241.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3.0之介绍Entity（转）</title><link>http://www.blogjava.net/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.blogjava.net/liaojiyong/archive/2006/07/03/56222.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/56222.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/07/03/56222.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/56222.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/56222.html</trackback:ping><description><![CDATA[
		<div class="contentBox">
				<div class="section">
						<a name="EJB3介绍:Overview">
						</a>
						<h2>EJB3介绍:Overview</h2>
						<p>EJB作为企业级的数据访问/持久化标准在1999年作为J2EE规范的核心规范出现，极大的转变了java企业级开发的模式，为java软件开发提供了一个良好的架构。 EJB从1.0到2.1在J2EE架构中，都是作为一个服务器端的(Server side)的数据访问中间件。开发人员通过EJB标准的API接口来访问操作数据，避免直接用JDBC和Sql操作底层的数据库。 </p>
						<p>采用EJB架构的目标在于： </p>
						<ul>
								<li>减轻直接操作底层数据库的工作量 
</li>
								<li>为企业级开发引入了面向对象/面向服务的开发架构 
</li>
								<li>数据对象生命周期的自动管理 
</li>
								<li>分布式能力 
</li>
								<li>集成/声明式的安全/事务管理 </li>
						</ul>
						<p>
						</p>
						<p>在旧的EJB模型中（2.1以前）,EJB实现了大部分的目标，但一个巨大的缺陷是原有的模型在试图减轻数据访问工作量的同时也引入了更多的复杂开发需求。 例如EJB核心的的Entity Bean必须特定的Home,Remote,Business接口，发布前需要预编译，只能实现单表映射操作，静态的EJB-QL(EJB查询语言）都不能满足简化数据库操作的目标。 EJB 2.1的复杂度，开发成本和性能问题使得EJB在问世4年后仍然等不到广泛的应用。 </p>
						<p>到了2004年，随着POJO( Plain Old Java Object )模型的出现，动态代码操作，IOC模式等先进，简单实用技术的发展和它们在各种独立产品中的表现，都证明POJO,IOC的技术比原有的EJB 2.1模型更适合作为数据访问中间件，开发的难度和成本远远小于目前的EJB模型，确有更灵活和可扩展。 2004年9月J2EE平台规范集众家所长，推出了跨越式的Java EE 5.0规范，最核心的是全面引入新的基于POJO和IOC技术的EJB3模型。到此，J2EE 5规范( Java EE 5 )成为一个集大成者，纳百家之长，成为java企业开发统一的标准规范。 </p>
				</div>
				<div 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持久化已经单独作为一个Persistence API规范和其他的EJB部分分离开来。下面我们主要讨论EJB 3和EJB 2.1在持久化API上的区别。 </p>
						<p>EJB 2.1模型存在复杂度高的缺陷： </p>
						<ul>
								<li>EJB 2.0 模型要求创建多个组件接口并实现多个不必要的回调方法 
</li>
								<li>组件接口要求实现 EJBObject 或 EJBLocalObject 以及处理许多不必要的异常 
</li>
								<li>基于XML的EJB 2.0 部署描述符比较复杂并容易出错 
</li>
								<li>基于 EJB 模型的容器管理持久性在开发和管理方面过于复杂，并且失去了几个基本特性--如使用数据库序列定义主键的标准方法 
</li>
								<li>EJBQL 语法非常有限，而且是静态的，无法做到运行期间的动态查询 
</li>
								<li>EJB 2.0 组件并非是真正面向对象的，因为它们在继承和多态性方面的有使用限制 
</li>
								<li>开发人员无法在 EJB 容器外部测试 EJB 模块，而在容器内部调试 EJB非常复杂和耗时 
</li>
								<li>查找和调用 EJB 2.0 是一项复杂的任务。即使是在应用程序中使用最基本的 EJB 也需要对 JNDI 有一个详细的了解 
</li>
								<li>对容器的依赖使得EJB 2.0只能用于服务器组件的开发，无法实现一次编写，四处运行的面向构件的开发 </li>
						</ul>所有这些复杂度和缺陷，都导致EJB 2.0的采用无法真正简化开发并提高生产力。 
<p></p><p>EJB 3.0 旨在解决以往EJB 2.0 模型的复杂性和提高灵活性，具体体现在： </p><ul><li>消除了不必要的接口Remote, Home, EJB以及回调方法实现 
</li><li>实体Bean采用了POJO模型，一个简单的java bean就可以是一个Entity Bean。无需依赖容器运行和测试 
</li><li>全面采用O/R Mapping技术来实现数据库操作 
</li><li>实体Bean可以运用在所有需要持久化的应用，不管是客户端还是服务器端。从而真正实现面向构件的开发 
</li><li>实体 bean 现在支持继承和多态性 
</li><li>灵活丰富的EJB3查询语言 
</li><li>SQL支持 
</li><li>使用元数据批注代替部署描述符，减少复杂配置和提高可维护性 
</li><li>将常规 Java 类用作 EJB 并将常规业务接口用于 EJB </li></ul><p></p></div>
				<div class="section">
						<a name="EJB_3中的元数据批注:Annotation">
						</a>
						<h2>EJB 3中的元数据批注:Annotation</h2>
						<p>EJB3 规范中引入了元数据批注(Annotation)。Annotation是从J2SE 1.5开始称为java语言的一部分。Annotation并不是一个新的事物，在J2SE 1.5以前，人们已经自行引入了象著名的XDoclet等外挂式的元数据批注方法。而在.NET中，元数据批注也早已经是C#语言的成分了。 </p>
						<p>在以往，我们都是采用xml作为配置批注，但采用文本的xml配置存在一些缺陷： </p>
						<ul>
								<li>描述符多，不容易记忆和掌握 
</li>
								<li>无法做自动的校验，需要人工排错 
</li>
								<li>当系统变大时，大量的xml配置难以管理 
</li>
								<li>读取和解析xml配置非常耗时，导致应用启动缓慢，不利于测试和维护 
</li>
								<li>做O/R Mapping的时候需要在java文件和xml配置文件之间交替，增大了工作量 
</li>
								<li>运行中保存xml配置需要消耗额外的内存 </li>
						</ul>
						<p>
						</p>
						<p>采用元数据可以很好的解决这些问题: </p>
						<ul>
								<li>描述符大量减少。以往在xml配置中往往需要描述java属性的类型，关系等等。而元数据本身就是java语言，从而省略了大量的描述符 
</li>
								<li>编译期校验。错误的批注在编译期间就会报错。 
</li>
								<li>元数据批注在java代码中，避免了额外的文件维护工作 
</li>
								<li>元数据被编译成java bytecode，消耗小的多内存，读取也非常迅速，往往比xml配置解析快几个数据量级，利于测试和维护 </li>
						</ul>
						<h2>第一个Entity Bean:HelloWorld</h2>
						<p>EJB3中的Entity Bean是如此的简单，就是一个普通的java bean加上一些精炼的元数据批注。 </p>
						<div 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" ) :顾名思义，定义当前Entity对应数据库中的表。</p>
						<p>@Id(generate=GeneratorType.NONE) :我们把HelloEntityBean的id属性定义为主键。主键产生策略为GeneratorType.NONE,意味这是一个业务主键。</p>
						<p>就这么简单！<br /><br /></p>
						<div class="contentBox">
								<div class="section">
										<a name="解说Entity">
										</a>
										<h2>解说Entity</h2>
										<p>从EJB3.0开始，Entity Bean持久化规范与EJB的其他规范如Session Bean, Message Driven Bean和EJB3容器规范开始分离，单独作为一个持久化API。而在将来，该持久化API很可能会从EJB3.0规范中脱离出来成为一个独立的规范Java Persistence API。作为Java平台上的通用数据访问标准接口。 为了跟规范一致，我们将在开发手册中将Entity Bean称为Entity。</p>
										<p>虽然EJB3 Entity可以是很简单的java bean，只要批注了@Entity或者在xml配置中作了说明，就被做一个可持久化的Entity处理。 但还是需要遵行一定的规则：</p>
										<ul>
												<li>Entity类必须要有一个无参数的public或者protected的Constructor。 
</li>
												<li>如果在应用中需要将该Entity类分离出来在分布式环境中作为参数传递，该Entity Class需要实现java.io.Serialzable接口。 
</li>
												<li>Entity类不可以是final，也不可有final的方法。 
</li>
												<li>abstract类和Concrete实体类都可以作为Entity类。 
</li>
												<li>Entity类中的属性变量不可以是public。Entity类的属性必须通过getter/setter或者其他的商业方法获得。 </li>
										</ul>
								</div>
								<div class="section">
										<a name="定义对Entity中属性变量的访问">
										</a>
										<h2>定义对Entity中属性变量的访问</h2>
										<p>在绝大部分的商业应用，开发人员都可以忽略这部分无需关心。但如果你需要编写复杂的Entity类的话，你需要了解这个部分。复杂的Entity类是指在Entity类的getter/setter和商业方法中包含比较复杂的业务逻辑而不是仅仅返回/符值某个属性。</p>
										<p>在大部分的情况下，我们都建议使Entity类中setter/getter中的逻辑尽可能简单，除了必要的校验符值外，不要包含复杂的业务逻辑，例如对关联的其他Entity类进行操作。但有些情况下，我们还是需要在Entity类的setter/getter方法中包含商业逻辑。这时候，采用何种属性访问方式就可能会影响代码的性能甚至是逻辑正确产生影响。</p>
										<p>EJB3持久化规范中,在默认情况下所有的属性都会自动的被持久化，除非属性变量用@Transient元数据进行了标注。针对可持久化属性定义了两种属性访问方式(access): FIELD和PROPERTY。</p>
										<ul>
												<li>如果采用access=FIELD, EJB3 Persistence运行环境（EJB3持久化产品，如Liberator EJB3)直接访问对象的属性变量，而不是通过getter。这种访问方式也不要求每个属性必须有getter/setter。如果需要在getter中包含商业逻辑，应该采用access=FIELD的方式。 
</li>
												<li>如果采用access=PROPERTY, EJB3 Persistence运行环境将通过Entity类上的getter来访问对象的属性变量，这就要求每个属性变量要有getter/setter方法。在EJB3中，默认的属性访问方式是PROPERTY。access=PROPERTY时getter/setter的逻辑应该尽量简单。 </li>
										</ul>
										<p>规范中access方式还有多一层含义。就是采用access=FIELD时，元数据应该批注在属性上。</p>
										<div 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 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>为了方便开发，Liberator EJB3实现对元数据批注的位置比规范规定的宽松，针对属性变量或它的getter进行批注都可以，不受access类型的影响。</p>
										<p>对Entity类中，getter/setter的命名规则遵从java bean规范。</p>
										<p>Entity类中的属性变量可以是以下数据类型：</p>
										<ul>
												<li>原始数据类型和他们的对象类型 
</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>Entity类 
</li>
												<li>嵌入实体类(embeddable classes) </li>
										</ul>
										<p>还可以是以下集合类型:</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 class="section">
										<a name="主键和实体标识（Primary_Key_and_Entity_Identity_">
										</a>
										<h2>主键和实体标识（Primary Key and Entity Identity)</h2>
										<p>每个Entity类都必须有一个主键。在EJB3中定义了两种主键：</p>
										<ul>
												<li>键单主键 
</li>
												<li>复合主键 </li>
										</ul>
										<p>简单主键必须对应Entity中的一个属性变量（Instance Variable)，而该属性对应数据库表中的一列。使用简单主键，我们只需要用@Id元数据对一个属性变量或者她的getter方法进行批注。</p>
										<p>当我们需要使用一个或多个属性变量（表中的一列或多列）联合起来作为主键，我们需要使用复合主键。复合主键要求我们编写一个复合主键类( Composite Primary Key Class )。复合主键类需要符合以下一些要求：</p>
										<ul>
												<li>复合主键类必须是public和具备一个没有参数的constructor 
</li>
												<li>复合主键类的每个属性变量必须有getter/setter，如果没有，每个属性变量则必须是public或者protected 
</li>
												<li>复合主键类必须实现java.io.serializable 
</li>
												<li>复合主键类必须实现equals()和hashcode()方法 
</li>
												<li>复合主键类中的主键属性变量的名字必须和对应的Entity中主键属性变量的名字相同 
</li>
												<li>一旦主键值设定后，不要修改主键属性变量的值 </li>
										</ul>一起看一个复合主键的例子。Entity类Person，它的主键属性变量是firstName和lastName。 
<div class="source"><pre>                
    @Id
    private String firstName;
    
    @Id
    private String lastName;

    public Person() {
    }
   
    
    
            </pre></div>Person的复合主键类： 
<div 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.blogjava.net/liaojiyong/aggbug/56222.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-07-03 00:57 <a href="http://www.blogjava.net/liaojiyong/archive/2006/07/03/56222.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3.0之操作Entity </title><link>http://www.blogjava.net/liaojiyong/archive/2006/07/03/56223.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Sun, 02 Jul 2006 16:57:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/07/03/56223.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/56223.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/07/03/56223.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/56223.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/56223.html</trackback:ping><description><![CDATA[
		<div class="contentBox">
				<div class="section">
						<a name="操作持久化Entity">
						</a>
						<h2>操作持久化Entity</h2>
						<p>对Entity进行操作的API都设计在javax.persistence.EntityManager接口上。EntityManager，顾名思义是管理所有EJB 3运行环境中的所有Entity。 EntityManager根据运行的环境不同分为容器管理的EntityManager和应用管理的EntityManager。Liberator EJB3是一个可以运行在J2SE环境中的 嵌入式的EJB3 Persistence实现，因此在Liberator EJB3中的 EntityManager都是指应用管理的EntityManager。</p>
				</div>
				<div class="section">
						<a name="配置和获得EntityManager">
						</a>
						<h2>配置和获得EntityManager</h2>在J2SE环境中，EJB3定义了一个javax.persistence.Persistence类用于启动EJB3运行环境。要获得EntityManager,首先需要通过javax.persistence.Persistence获得EntityManagerFactory，然后调用EntityManagerFactory.createEntityManager()方法获得。 
<div class="source"><pre>                
    // 获得默认当前的EntityManagerFactory                
    final EntityManagerFactory emf = Persistence.createEntityManagerFactory();
    final EntityManager entityManager = emf.createEntityManager();    
                
            </pre></div><p>当调用Persistence.createEntityManagerFactory()的时候，Persistence会做以下的步骤：</p><ul><li>搜索当前jar包的META-INFO/persistence.xml配置文件 
</li><li>如果没有在META-INFO下找到persistence.xml，搜索当前线程的ContextClassLoader中的persistence.xml 
</li><li>根据获得的persistence.xml初始化EntityManagerFactory </li></ul>每个EntityManagerFactory都必须有一个persistence.xml配置文件。下面是一个例子： 
<div class="source"><pre>                
&lt;entity-manager&gt;
    &lt;name&gt;myEntityManager&lt;/name&gt;
    &lt;provider&gt;com.redsoft.ejb3.PersistenceProviderImpl&lt;/provider&gt;
    &lt;class&gt;com.redsoft.samples.HelloEntityBean&lt;/class&gt;
    &lt;properties&gt;
        &lt;property name="ConnectionDriverName" value="com.mysql.jdbc.Driver"/&gt;
        &lt;property name="ConnectionURL" value="jdbc:mysql://localhost/EJB3Test"/&gt;
        &lt;property name="ConnectionUserName" value="ejb3"/&gt;
        &lt;property name="ConnectionPassword" value="ejb3"/&gt;
        &lt;property name="RetainValues" value="true"/&gt;
        &lt;property name="RestoreValues" value="false"/&gt;
        &lt;property name="IgnoreCache" value="false"/&gt;
        &lt;property name="NontransactionalRead" value="true"/&gt;
        &lt;property name="NontransactionalWrite" value="false"/&gt;
        &lt;property name="Multithreaded" value="false"/&gt;
        &lt;property name="Liberator.option.action" value="create"/&gt;
        &lt;property name="Liberator.option.cache" value="com.redsoft.jdo.enterprise.OscacheAdapter"/&gt;
        &lt;property name="Liberator.option.JMXEnabled" value="false"/&gt;
        &lt;property name="Liberator.option.NamingPort" value="3012"/&gt;
        &lt;property name="Liberator.option.JMXPort" value="3011"/&gt;
        &lt;property name="Liberator.option.JDBC.scrollable" value="false"/&gt;
        &lt;property name="Liberator.option.JDBC.fetchSize" value="500"/&gt;
        &lt;property name="cache.algorithm" value="LRUCache"/&gt;
        &lt;property name="cache.capacity" value="5000"/&gt;
        &lt;property name="log4j.logger.com.redsoft" value="FATAL"/&gt;
    &lt;/properties&gt;
&lt;/entity-manager&gt;   
                
            </pre></div><p>&lt;name&gt;&lt;/name&gt; 定义一个EntityManagerFactory的名字，这样当应用中需要多个EntityManagerFactory的时候可以区别。通常情况下，一个EntityManagerFactory对应一个数据源。</p><p>&lt;provider&gt;&lt;/provider&gt; 定义采用的什么EJB3 Persistence运行环境（也就是EJB3 Persistence产品)，例子中采用的的是Liberator EJB3的运行环境。正如前面说的，在EJB3规范中, EJB3 Persistence运行环境( Runtime )是作为一个独立的嵌入式模块，你可以随意的更换不同的EJB3 Persistence运行环境而不会影响你的应用程序。<strong>甚至在J2EE服务器内运行你也可以不用服务器本身提供的EJB3 Persistence运行环境，而采用第三方的EJB3 Persistence运行环境</strong>。</p><p>&lt;class&gt;&lt;/class&gt; 定义哪些类是Entity持久化类。如果是测试环境或者你不采用ear/war的方式发布你的应用，而只是把编译后的类直接拷贝到web容器中，在添加一个新的Entity类时，需要在这里添加一行。要求这个步骤是因为在J2EE 5架构中EJB3运行环境的嵌入式设计。采用这种松耦合设计使EJB3 Persistence运行环境不能控制持久化类的加载(由J2EE服务器负责加载), 这样EJB3 Persistence运行环境就无法分辨jvm中哪个类是持久化Entity类，哪个不是。因此需要一个额外的信息来让EJB3 Persistence知道那些是持久化Entity。</p><p>&lt;property&gt;&lt;/property&gt; 定义了了EJB3 Persistence运行环境需要的其他参数，这些参数不是标准的，而是由EJB3 Persistence运行环境的厂商自行定义。</p>详细的配置方法参看persistence.xml的语法。 </div>
				<div class="section">
						<a name="Entity的生命周期和状态">
						</a>
						<h2>Entity的生命周期和状态</h2>在EJB3中定义了四种Entity的状态: 
<ul><li>新实体(new)。Entity由应用产生，和EJB3 Persistence运行环境没有联系，也没有唯一的标示符(Identity)。 
</li><li>持久化实体(managed)。新实体和EJB3 Persistence运行环境产生关联（通过persist(), merge()等方法)，在EJB3 Persistence运行环境中存在和被管理，标志是在EJB3 Persistence运行环境中有一个唯一的标示(Identity)。 
</li><li>分离的实体(detached)。Entity有唯一标示符，但它的标示符不被EJB3 Persistence运行环境管理,　同样的该Entity也不被EJB3 Persistence运行环境管理。 
</li><li>删除的实体(removed)。Entity被remove()方法删除，对应的纪录将会在当前事务提交的时候从数据库中删除。 </li></ul></div>
				<div class="section">
						<a name="持久化Entity_Persist_">
						</a>
						<h2>持久化Entity(Persist)</h2>
						<div class="source">
								<pre>                
    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 );
    
    // 这时hello的状态变为managed
    
    trans.commit();

    entityManager.close();
    
    // 这时hellow的状态变为detached.
    
                 
            </pre>
						</div>Liberator EJB3支持Persistence by reachability。当保存一个Entity时，以该对象为根对象的整个对象图都会自动的被保存。但在EJB3中，我们仍然可以通过关系元数据（比如OneToOne,OneToMany)的cascade属性来精确定义保存的级联行为。 下面我们来看看不同的cascade属性的区别。 
<p>不配置cascade的情况下，EJB3 Persistence运行环境默认不会采用Persistence by reachability。</p><div class="source"><pre>                
    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;
        }
    }
                  </pre></div>现在来保存一个Father和Son。 
<div class="source"><pre>                
    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();
                 </pre></div>现在我们配置casacde=CascadeType.ALL 
<div class="source"><pre>                
    public class Father{
        @Id
        int id
        
        String name;
        
        // OneToOne配置cascade=CascadeType.ALL,配置cascade=CascadeType.PERSIT也对persist操作也可以获得同样的效果。
        // 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;
        }
    }
                  </pre></div>在代码中同样持久化Father和mySon。 
<div class="source"><pre>                
    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();
                 </pre></div>由于Liberator EJB3运行环境采用了弱引用POJO管理技术，能很好的支持Persistence by reachablity而不会有其他产品有的潜在内存回收的问题， 因此建议在应用中<strong>尽可能使用cascade=CascadeType.ALL来减少持久化操作的复杂性和代码量</strong>，特别是在有复杂对象关系图的时候。 </div>
				<div class="section">
						<a name="获取Entity">
						</a>
						<h2>获取Entity</h2>如果知道Entity的唯一标示符，我们可以用find()方法来获得Entity。 
<div class="source"><pre>                        
    Father father = manager.find( Father.class, new Integer( 1 ) );
            
    // 由于JDK1.5支持自动转型，也可以如下使用
            
    Father father = manager.find( Father.class, 1 );
    
    /* 
    *　或者,可以用Entity名字作为查找。但无法利用JDK 1.5的自动转型功能，
    *  需要使用对象作为查找主键，并需要对获得Entity进行转型
    */
    
    Father father = (Father)manager.find( "com.redsoft.samples.Father", new Integer( 1 ) );
            
          </pre></div></div>
				<div class="section">
						<a name="更新Entity">
						</a>
						<h2>更新Entity</h2>对Entity的更新必须在事物内完成。和persist中一样，关系元数据的cascade属性对是否集联删除有影响。 
<div class="source"><pre>                
    transaction.begin();                
    Father father = manager.find( Father.class, 1 );
    
    // 更新原始数据类型
    father.setName( "newName" );
    
    // 更新对象引用
    Son newSon = new Son();
    father.setSon( newSon );
    
    
    // 提交事务，刚才的更新同步到数据库
    transaction.commit();
                 </pre></div></div>
				<div class="section">
						<a name="删除Entity">
						</a>
						<h2>删除Entity</h2>对Entity的删除必须在事物内完成。 
<div class="source"><pre>                
    transaction.begin();                
    
    Father father = manager.find( Father.class, 1 );
        
    // 如果father/son的@OneToOne的cascade=CascadeType.ALL，在删除father时候，也会把son删除。
    // 把cascade属性设为cascade=CascadeType.REMOVE有同样的效果。
    manager.remove( father );
        
    // 提交事务，刚才的更新同步到数据库
    transaction.commit();
                 </pre></div></div>
				<div class="section">
						<a name="脱离_附合_Detach_Merge_">
						</a>
						<h2>脱离/附合(Detach/Merge)</h2>
						<p>在三层或者分布式应用中，我们很多时候需要Entity能脱离EntityManager，避免长时间保持EntityManager打开占用资源和可以在不同的JVM之间传递Entity。</p>
						<p>在脱离EJB3 Persistence Runtime(EntityManager)的管理后,我们仍然可以读取或者修改Entity中的内容。而在稍后的时间，我们又可以将Entity重新和原有或者新的EntityManager附合，如果附合前Entity被改动过，更改的数据可以自动的被发现并和数据库同步。</p>
						<div class="source">
								<pre>                
    EntityManager entityManager = emf.createEntityManager();
    
    // 这时Father还是被EntityManager管理的
    Father father = manager.find( Father.class, 1 );
    
    // 当entityManger关闭的时候，当前被entityManager管理的Entity都会自动的脱离EntityManager，状态转变为detached
    entityManager.close();
    
    // 脱离EntityManager后，我们仍然可以修改Father的属性
    father.setName( "newName" );
    
    // 在稍后的，我们可以将father重新附和到一个新的或者原来的EntityManager中
    EntityManager newEntityManager = emf.createEntityManager();
    
    // 附合( merge )需要在事务中进行
    newEntityManager.getTransaction().begin();
    newEntityManager.merge( father );
    
    // commit后father中的被修改的内容会同步到数据库。
    newEntityManager.getTransaction().commit();
    

                 </pre>
						</div>
						<p>Liberator EJB3 Persistnece运行环境由于支持Persistence-by-reachablity。我们建议采用cascade=CascadeType.ALL，这样当需要附合的是一个对象图的时候，我们只需要merge根对象即可，整个对象图，对象图中被修改过的对象都会被自动识别和同步。</p>
						<p>需要注意的是在脱离EJB3 Persistence Runtime的管理后，如果对象中有定义为lazy-load的属性将无法访问。</p>
				</div>
		</div>
<img src ="http://www.blogjava.net/liaojiyong/aggbug/56223.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-07-03 00:57 <a href="http://www.blogjava.net/liaojiyong/archive/2006/07/03/56223.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3.0之关系对象映射元数据（转）</title><link>http://www.blogjava.net/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.blogjava.net/liaojiyong/archive/2006/07/03/56221.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/56221.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/07/03/56221.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/56221.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/56221.html</trackback:ping><description><![CDATA[
		<div class="contentBox">
				<div class="section">
						<a name="Table">
						</a>
						<h2>Table</h2>
						<p>Table用来定义entity主表的name，catalog，schema等属性。</p>
						<p>元数据属性说明：</p>
						<ul>
								<li>name: 表名 
</li>
								<li>catalog: 对应关系数据库中的catalog 
</li>
								<li>schema：对应关系数据库中的schema 
</li>
								<li>UniqueConstraints:定义一个UniqueConstraint数组，指定需要建唯一约束的列（具体参看<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#UniqueConstraint"><font color="#002c99">UniqueConstraint</font></a>） </li>
						</ul>
						<div class="source">
								<pre>    
    @Entity
    @Table(name="CUST")
    public class Customer { ... }
    
    </pre>
						</div>　　</div>
				<div 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>schema：对应关系数据库中的schema 
</li>
								<li>pkJoin: 定义一个PrimaryKeyJoinColumn数组，指定从表的主键列（具体参看<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#PrimaryKeyJoinColumn"><font color="#002c99">PrimaryKeyJoinColumn</font></a>） 
</li>
								<li>UniqueConstraints:定义一个UniqueConstraint数组，指定需要建唯一约束的列（具体参看<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#UniqueConstraint"><font color="#002c99">UniqueConstraint</font></a>） </li>
						</ul>
						<p>下面的代码说明Customer类映射到两个表，主表名是CUSTOMER，从表名是CUST_DETAIL，从表的主键列和主表的主键列类型相同，列名为CUST_ID。</p>
						<div class="source">
								<pre>                
    @Entity
    @Table(name="CUSTOMER")
	@SecondaryTable(name="CUST_DETAIL",pkJoin=@PrimaryKeyJoinColumn(name="CUST_ID"))
	public class Customer { ... }
    
    </pre>
						</div>
				</div>
				<div class="section">
						<a name="SecondaryTables">
						</a>
						<h2>SecondaryTables</h2>
						<p>当一个entity class映射到一个主表和多个从表时，用SecondaryTables来定义各个从表的属性。</p>
						<p>元数据属性说明：</p>
						<ul>
								<li>value： 定义一个SecondaryTable数组，指定每个从表的属性。 </li>
						</ul>
						<div 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 class="section">
						<a name="UniqueConstraint">
						</a>
						<h2>UniqueConstraint</h2>
						<p>UniqueConstraint定义在Table或SecondaryTable元数据里，用来指定建表时需要建唯一约束的列。</p>
						<p>元数据属性说明：</p>
						<ul>
								<li>columnNames:定义一个字符串数组，指定要建唯一约束的列名。 </li>
						</ul>
						<div class="source">
								<pre>                
		@Entity
		@Table(name="EMPLOYEE",
			uniqueConstraints={@UniqueConstraint(columnNames={"EMP_ID", "EMP_NAME"})}
		)
		public class Employee { ... }
    
    </pre>
						</div>
				</div>
				<div class="section">
						<a name="Column">
						</a>
						<h2>Column</h2>
						<p>Column元数据定义了映射到数据库的列的所有属性：列名，是否唯一，是否允许为空，是否允许更新等。</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: 从表名。如果此列不建在主表上（默认建在主表），该属性定义该列所在从表的名字。 </li>
						</ul>
						<div 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 class="section">
						<a name="JoinColumn">
						</a>
						<h2>JoinColumn</h2>
						<p>如果在entity class的field上定义了关系（one2one或one2many等），我们通过JoinColumn来定义关系的属性。JoinColumn的大部分属性和Column类似。</p>
						<p>元数据属性说明：</p>
						<ul>
								<li>name:列名。 
</li>
								<li>referencedColumnName:该列指向列的列名（建表时该列作为外键列指向关系另一端的指定列） 
</li>
								<li>unique: 是否唯一 
</li>
								<li>nullable: 是否允许为空 
</li>
								<li>insertable: 是否允许插入 
</li>
								<li>updatable: 是否允许更新 
</li>
								<li>columnDefinition: 定义建表时创建此列的DDL 
</li>
								<li>secondaryTable: 从表名。如果此列不建在主表上（默认建在主表），该属性定义该列所在从表的名字。 </li>
						</ul>
						<p>下面的代码说明Custom和Order是一对一关系。在Order对应的映射表建一个名为CUST_ID的列，该列作为外键指向Custom对应表中名为ID的列。</p>
						<div 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 class="section">
						<a name="JoinColumns">
						</a>
						<h2>JoinColumns</h2>
						<p>如果在entity class的field上定义了关系（one2one或one2many等），并且关系存在多个JoinColumn，用JoinColumns定义多个JoinColumn的属性。</p>
						<p>元数据属性说明：</p>
						<ul>
								<li>value: 定义JoinColumn数组，指定每个JoinColumn的属性。 </li>
						</ul>
						<p>下面的代码说明Custom和Order是一对一关系。在Order对应的映射表建两列，一列名为CUST_ID，该列作为外键指向Custom对应表中名为ID的列,另一列名为CUST_NAME，该列作为外键指向Custom对应表中名为NAME的列。</p>
						<div 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 class="section">
						<a name="Id">
						</a>
						<h2>Id</h2>
						<p>声明当前field为映射表中的主键列。id值的获取方式有五种：TABLE, SEQUENCE, IDENTITY, AUTO, NONE。Oracle和DB2支持SEQUENCE，SQL Server和Sybase支持IDENTITY,mysql支持AUTO。所有的数据库都可以指定为AUTO，我们会根据不同数据库做转换。NONE(默认)需要用户自己指定Id的值。Table类型详见<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#TableGenerator"><font color="#002c99">TableGenerator</font></a>的介绍。</p>
						<p>元数据属性说明：</p>
						<ul>
								<li>generate():主键值的获取类型 
</li>
								<li>generator():<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#TableGenerator"><font color="#002c99">TableGenerator</font></a>的名字（当generate=GeneratorType.TABLE才需要指定该属性） </li>
						</ul>
						<p>下面的代码声明Task的主键列id是自动增长的。(Oracle和DB2从默认的SEQUENCE取值，SQL Server和Sybase该列建成IDENTITY，mysql该列建成auto increment。)</p>
						<div class="source">
								<pre>                
    @Entity
    @Table(name = "OTASK")
    public class Task {
	  @Id(generate = GeneratorType.AUTO)
	  public Integer getId() {
		  return id;
	  }
    }
    
    </pre>
						</div>
				</div>
				<div class="section">
						<a name="IdClass">
						</a>
						<h2>IdClass</h2>
						<p>当entity class使用复合主键时，需要定义一个类作为id class。id class必须符合以下要求:类必须声明为public，并提供一个声明为public的空构造函数。必须实现Serializable接，覆写equals()和hashCode（）方法。entity class的所有id field在id class都要定义，且类型一样。</p>
						<p>元数据属性说明：</p>
						<ul>
								<li>value: id class的类名 </li>
						</ul>
						<p>
						</p>
						<div 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 class="section">
						<a name="MapKey">
						</a>
						<h2>MapKey</h2>
						<p>在一对多，多对多关系中，我们可以用Map来保存集合对象。默认用主键值做key，如果使用复合主键，则用id class的实例做key，如果指定了name属性，就用指定的field的值做key。</p>
						<p>元数据属性说明：</p>
						<ul>
								<li>name: 用来做key的field名字 </li>
						</ul>
						<p>下面的代码说明Person和Book之间是一对多关系。Person的books字段是Map类型，用Book的isbn字段的值作为Map的key。</p>
						<div class="source">
								<pre>                
    @Table(name = "PERSON")
    public class Person {

	@OneToMany(targetEntity = Book.class, cascade = CascadeType.ALL, mappedBy = "person")
	@MapKey(name = "isbn")
	private Map&lt;String, Book&gt; books = new HashMap&lt;String, Book&gt;();
    }
    
    </pre>
						</div>
				</div>
				<div class="section">
						<a name="OrderBy">
						</a>
						<h2>OrderBy</h2>
						<p>在一对多，多对多关系中，有时我们希望从数据库加载出来的集合对象是按一定方式排序的，这可以通过OrderBy来实现，默认是按对象的主键升序排列。</p>
						<p>元数据属性说明：</p>
						<ul>
								<li>value: 字符串类型，指定排序方式。格式为"fieldName1 [ASC|DESC],fieldName2 [ASC|DESC],......",排序类型可以不指定，默认是ASC。 </li>
						</ul>
						<p>下面的代码说明Person和Book之间是一对多关系。集合books按照Book的isbn升序，name降序排列。</p>
						<div 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&lt;Book&gt; books = new ArrayList&lt;Book&gt;();
    }
    
    </pre>
						</div>
				</div>
				<div class="section">
						<a name="PrimaryKeyJoinColumn">
						</a>
						<h2>PrimaryKeyJoinColumn</h2>
						<p>在三种情况下会用到PrimaryKeyJoinColumn。 
</p>
						<ul>
								<li>继承(详见<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#Inheritance"><font color="#002c99">Inheritance</font></a>)。 
</li>
								<li>entity class映射到一个或多个从表。从表根据主表的主键列（列名为referencedColumnName值的列），建立一个类型一样的主键列，列名由name属性定义。 
</li>
								<li>one2one关系，关系维护端的主键作为外键指向关系被维护端的主键，不再新建一个外键列(与<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#JoinColumn"><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映射到两个表，主表CUSTOMER,从表CUST_DETAIL，从表需要建立主键列CUST_ID，该列和主表的主键列id除了列名不同，其他定义一样。 </p>
						<div class="source">
								<pre>            
    @Entity
    @Table(name="CUSTOMER")
	@SecondaryTable(name="CUST_DETAIL",pkJoin=@PrimaryKeyJoinColumn(name="CUST_ID"，referencedColumnName="id"))
	public class Customer { 
	 @Id(generate = GeneratorType.AUTO)
	  public Integer getId() {
		  return id;
	  }
	}
    
    </pre>
						</div>
						<p>下面的代码说明Employee和EmployeeInfo是一对一关系，Employee的主键列id作为外键指向EmployeeInfo的主键列INFO_ID。 </p>
						<div class="source">
								<pre>            
    @Table(name = "Employee")
    public class Employee {
	@OneToOne
	@PrimaryKeyJoinColumn(name = "id", referencedColumnName="INFO_ID")
	EmployeeInfo info;
	}
    
    </pre>
						</div>
				</div>
				<div class="section">
						<a name="PrimaryKeyJoinColumns">
						</a>
						<h2>PrimaryKeyJoinColumns</h2>
						<p>如果entity class使用了复合主键，指定单个PrimaryKeyJoinColumn不能满足要求时，可以用PrimaryKeyJoinColumns来定义多个PrimaryKeyJoinColumn。 </p>
						<p>元数据属性说明：</p>
						<ul>
								<li>value: 一个PrimaryKeyJoinColumn数组，包含所有PrimaryKeyJoinColumn。 </li>
						</ul>
						<p>下面的代码说明了Employee和EmployeeInfo是一对一关系。他们都使用复合主键，建表时需要在Employee表建立一个外键，从Employee的主键列id,name指向EmployeeInfo的主键列INFO_ID和INFO_NAME. </p>
						<div 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 class="section">
						<a name="Transient">
						</a>
						<h2>Transient</h2>
						<p>Transient用来注释entity的属性，指定的这些属性不会被持久化，也不会为这些属性建表。</p>
						<div class="source">
								<pre>    
    @Transient
    private String name;
    
    </pre>
						</div>　　</div>
				<div class="section">
						<a name="Version">
						</a>
						<h2>Version</h2>
						<p>Version指定实体类在乐观事务中的version属性。在实体类重新由EntityManager管理并且加入到乐观事务中时，保证完整性。每一个类只能有一个属性被指定为version，version属性应该映射到实体类的主表上。</p>
						<p>下面的代码说明versionNum属性作为这个类的version，映射到数据库中主表的列名是OPTLOCK。</p>
						<div class="source">
								<pre>                
    @Version
    @Column("OPTLOCK")
    protected int getVersionNum() { return versionNum; }
    
    </pre>
						</div>
				</div>
				<div class="section">
						<a name="Lob">
						</a>
						<h2>Lob</h2>
						<p>Lob指定一个属性作为数据库支持的大对象类型在数据库中存储。使用LobType这个枚举来定义Lob是二进制类型还是字符类型。</p>
						<p>LobType枚举类型说明：</p>
						<ul>
								<li>BLOB 二进制大对象，Byte[]或者Serializable的类型可以指定为BLOB。 
</li>
								<li>CLOB 字符型大对象，char[]、Character[]或String类型可以指定为CLOB。 </li>
						</ul>
						<p>元数据属性说明：</p>
						<ul>
								<li>fetch： 定义这个字段是lazy loaded还是eagerly fetched。数据类型是FetchType枚举，默认为LAZY,即lazy loaded. 
</li>
								<li>type： 定义这个字段在数据库中的JDBC数据类型。数据类型是LobType枚举，默认为BLOB。 </li>
						</ul>
						<p>下面的代码定义了一个BLOB类型的属性和一个CLOB类型的属性。</p>
						<div 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 class="section">
						<a name="JoinTable">
						</a>
						<h2>JoinTable</h2>
						<p>JoinTable在many-to-many关系的所有者一边定义。如果没有定义JoinTable，使用JoinTable的默认值。</p>
						<p>元数据属性说明：</p>
						<ul>
								<li>table:这个join table的<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#Table"><font color="#002c99">Table</font></a>定义。 
</li>
								<li>joinColumns:定义指向所有者主表的外键列，数据类型是<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#JoinColumn"><font color="#002c99">JoinColumn</font></a>数组。 
</li>
								<li>inverseJoinColumns:定义指向非所有者主表的外键列，数据类型是<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#JoinColumn"><font color="#002c99">JoinColumn</font></a>数组。 </li>
						</ul>
						<p>下面的代码定义了一个连接表CUST和PHONE的join table。join table的表名是CUST_PHONE，包含两个外键，一个外键是CUST_ID，指向表CUST的主键ID，另一个外键是PHONE_ID，指向表PHONE的主键ID。</p>
						<div 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 class="section">
						<a name="TableGenerator">
						</a>
						<h2>TableGenerator</h2>
						<p>TableGenerator定义一个主键值生成器，在<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#Id"><font color="#002c99">Id</font></a>这个元数据的generate＝TABLE时，generator属性中可以使用生成器的名字。生成器可以在类、方法或者属性上定义。</p>
						<p>生成器是为多个实体类提供连续的ID值的表，每一行为一个类提供ID值，ID值通常是整数。</p>
						<p>元数据属性说明：</p>
						<ul>
								<li>name:生成器的唯一名字，可以被Id元数据使用。 
</li>
								<li>table:生成器用来存储id值的<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#Table"><font color="#002c99">Table</font></a>定义。 
</li>
								<li>pkColumnName:生成器表的主键名称。 
</li>
								<li>valueColumnName:生成器表的ID值的列名称。 
</li>
								<li>pkColumnValue:生成器表中的一行数据的主键值。 
</li>
								<li>initialValue:id值的初始值。 
</li>
								<li>allocationSize:id值的增量。 </li>
						</ul>
						<p>下面的代码定义了两个生成器empGen和addressGen，生成器的表是ID_GEN。</p>
						<div 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 class="section">
						<a name="SequenceGenerator">
						</a>
						<h2>SequenceGenerator</h2>
						<p>SequenceGenerator定义一个主键值生成器，在<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#Id"><font color="#002c99">Id</font></a>这个元数据的generator属性中可以使用生成器的名字。生成器可以在类、方法或者属性上定义。生成器是数据库支持的sequence对象。</p>
						<p>元数据属性说明：</p>
						<ul>
								<li>name:生成器的唯一名字，可以被Id元数据使用。 
</li>
								<li>sequenceName:数据库中，sequence对象的名称。如果不指定，会使用提供商指定的默认名称。 
</li>
								<li>initialValue:id值的初始值。 
</li>
								<li>allocationSize:id值的增量。 </li>
						</ul>
						<p>下面的代码定义了一个使用提供商默认名称的sequence生成器。</p>
						<div class="source">
								<pre>                
    @SequenceGenerator(name="EMP_SEQ", allocationSize=25)	
    
    </pre>
						</div>
				</div>
				<div class="section">
						<a name="DiscriminatorColumn">
						</a>
						<h2>DiscriminatorColumn</h2>
						<p>DiscriminatorColumn定义在使用SINGLE_TABLE或JOINED继承策略的表中区别不继承层次的列。</p>
						<p>元数据属性说明：</p>
						<ul>
								<li>name:column的名字。默认值为TYPE。 
</li>
								<li>columnDefinition:生成DDL的sql片断。 
</li>
								<li>length:String类型的column的长度，其他类型使用默认值10。 </li>
						</ul>
						<p>下面的代码定义了一个列名为DISC，长度为20的String类型的区别列。</p>
						<div 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.blogjava.net/liaojiyong/aggbug/56221.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-07-03 00:53 <a href="http://www.blogjava.net/liaojiyong/archive/2006/07/03/56221.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3.0之映射（转）</title><link>http://www.blogjava.net/liaojiyong/archive/2006/07/03/56220.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Sun, 02 Jul 2006 16:52:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/07/03/56220.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/56220.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/07/03/56220.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/56220.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/56220.html</trackback:ping><description><![CDATA[
		<h2>一对一映射</h2>
		<p>双向一对一关系需要在关系维护端（owner side）的one2one Annotition定义mappedBy属性。建表时在关系被维护端（inverse side）建立外键列指向关系维护端的主键列。</p>
		<p>假设Country 和 Capital 是双向一对一的关系，具体元数据声明如下:</p>
		<div class="source">
				<pre>				
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;
                
			</pre>
		</div>
		<p>代码中元数据的说明：</p>
		<p>元数据描述: 
</p>
		<p>@OneToOne(optional = true,cascade = CascadeType.ALL, mappedBy = "country")</p>
		<p>optional声明关系是否是必须存在的，即是否允许其中一端为null。</p>
		<p>cascade声明级联操作。</p>
		<p>@JoinColumn(name = "COUNTRY_ID", referencedColumnName = "id")</p>
		<p>name声明外键列的名字，referencedColumnName声明外键指向列的列名。<br /><br /></p>
		<h2>一对多映射</h2>
		<p>双向一对多关系，一是关系维护端（owner side），多是关系被维护端（inverse side）。 建表时在关系被维护端建立外键列指向关系维护端的主键列。</p>
		<p>假设Father 和 Child 是双向一对多的关系，具体元数据声明如下:</p>
		<div class="source">
				<pre>				
public class Father {
	@OneToMany(targetEntity = Child.class, cascade = CascadeType.ALL, mappedBy = "father")
	public List&lt;Child&gt; getChildren() {
		return children;
	}
}

public class Child {
	@ManyToOne
	@JoinColumn(name = "FATHER_ID", referencedColumnName = "id")
	public Father getFather() {
		return father;
	}
}

                
			</pre>
		</div>
		<p>代码中元数据的说明：</p>
		<p>元数据描述: 
</p>
		<p>@OneToMany(targetEntity = Child.class, cascade = CascadeType.ALL, mappedBy = "father")</p>
		<p>targetEntity = Child.class表明关系另一端的实体类型</p>
		<p>cascade声明级联操作。</p>
		<p>mappedBy声明关系维护端的字段（field）名。</p>
		<p>@ManyToOne</p>
		<p>@JoinColumn(name = "FATHER_ID", referencedColumnName = "id")</p>
		<p>name声明外键列的名字，referencedColumnName声明外键指向列的列名。<br /><br /></p>
		<h2>多对多映射</h2>
		<p>多对多映射采取中间表连接的映射策略，建立的中间表将分别引入两边的主键作为外键。</p>
		<p>EJB3对于中间表的元数据提供了可配置的方式，用户可以自定义中间表的表名，列名。</p>
		<p>假设Teacher 和 Student是多对多的关系，具体元数据声明如下:</p>
		<div class="source">
				<pre>				
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&lt;Student&gt; getStudents() {return students;}
					
}
public class Student{
	@ManyToMany(targetEntity = Teacher.class, mappedBy = "students")
	public List&lt;Teacher&gt; getTeachers() {
		return teachers;
	}
}
			
			</pre>
		</div>
		<p>代码中元数据的说明：</p>
		<p>元数据描述:</p>
		<p>@ManyToMany(targetEntity = Student.class, cascade = CascadeType.PERSIST)</p>
		<p>targetEntity = Student.class表明关系另一端的实体类型。cascade声明级联操作。</p>
		<p>@JoinTable(table = @Table(name = "M2M_TEACHER_STUDENT"), </p>
		<p>joinColumns = @JoinColumn(name = "TEACHER_ID", referencedColumnName = "ID"), </p>
		<p>inverseJoinColumns = @JoinColumn(name = "STUDENT_ID", referencedColumnName = "ID"))</p>
		<p>JoinTable配置中间表信息，它由3个部分组成:</p>
		<p>1) table = @Table(name = "M2M_TEACHER_STUDENT") ,声明中间表的名字</p>
		<p>2） joinColumns ，定义中间表与关系维护端的外键关系。</p>
		<p>3） inverseJoinColumns，定义中间表与inverse端的外键关系.<br /></p>
		<div class="section">
				<a name="Inheritance_strategy">
				</a>
				<h2>Inheritance strategy</h2>
				<p>EJB3规定了三种基本的继承映射策略：</p>
				<p>.每个类分层结构一张表(table per class hierarchy) </p>
				<p>.每个子类一张表(table per subclass) </p>
				<p>.每个具体类一张表(table per concrete class)</p>
				<p>在我们提供的Alpha版本中仅支持第一种映射策略，即每个类层次一个表。我们将在下一个版本中提供每个具体类一张表的支持， 考虑到性能，这两个映射策略也是推荐的映射策略. </p>
		</div>
		<div class="section">
				<a name="每个类分层结构一张表_Table_per_class_hierarchy_">
				</a>
				<h2>每个类分层结构一张表(Table per class hierarchy)</h2>假设有这么一个继承类层次:Employee,两个子类FullTimeEmployee,PartTimeEmployee 源代码如下所示: 
<div class="source"><pre>				
@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 {...}
                
			</pre></div><p>代码中元数据的说明：</p><p>基类中元数据描述:</p><p>@Inheritance(strategy=InheritanceType.SINGLE_TABLE,</p><p>discriminatorType=DiscriminatorType.STRING,discriminatorValue="employee")</p><p>strategy=InheritanceType.SINGLE_TABLE表示继承映射采用第一种映射策略。</p><p>discriminatorType=DiscriminatorType.STRING表示继承层次中类型识别列类型为String.</p><p>discriminatorValue="employee" 表示此类对应的类型识别码为employee.</p></div>
<img src ="http://www.blogjava.net/liaojiyong/aggbug/56220.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-07-03 00:52 <a href="http://www.blogjava.net/liaojiyong/archive/2006/07/03/56220.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3 QL查询(转)</title><link>http://www.blogjava.net/liaojiyong/archive/2006/07/02/56216.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Sun, 02 Jul 2006 15:35:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/07/02/56216.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/56216.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/07/02/56216.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/56216.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/56216.html</trackback:ping><description><![CDATA[
		<div class="contentBox">
				<div class="section">
						<a name="EJB3_QL查询">
						</a>
						<h2>EJB3 QL查询</h2>
						<p>EJB3的查询语言是一种和SQL非常类似的中间性和对象化查询语言。它可以被编译成不同的底层数据库能接受的SQL，从而屏蔽不同数据库的差异，确保用EJB3 QL查询语言编写的代码可在不同的数据库上运行。比起EJB 2.1的查询语言，EJB3可以运行期构造，支持多态，远远比EJB 2.1的查询更灵活和功能强大。在程序中使用EJB3 QL可以使用大写(SELECT)或者小写(select)，但不要大小写(比如:Select)混合使用。</p>　　　 </div>
				<div class="section">
						<a name="Query接口">
						</a>
						<h2>Query接口</h2>
						<p>javax.persistence.Query是EJB3查询操作的接口。进行查询，首先要通过EntityManager 获得Query对象。</p>
						<div class="source">
								<pre>                
    public Query createQuery(String ejbqlString);                 
                
            </pre>
						</div>
						<p>下面我们做一个最简单的查询，查询所有的com.redsoft.samples.Order类。</p>
						<div class="source">
								<pre>                
    final Query query = entityManager.createQuery( "select o from Order o"); 
    final List result = query.getResultList();
    final Iterator iterator = result.iterator();
    while( iterator.hasNext() ){
        //　处理Order
    }
                
            </pre>
						</div>
						<p>注意"from Order"。"Order"在EJB3查询中称为com.redsoft.samples.Order类的abstract schema Type。查询Entity在EJB3 QL中都是针对Entity的Abstract Schema Type进行查询。 在同一个EntityManagerFactory中，不允许同时有两个Abstract Schema Type相同的Entity类。比如不允许同时有com.redsoft.samples.Order和com.redsoft.foo.Order。　　 </p>
						<p>Query返回一个List的集合结果，我们可以用Iterator或者List.get( int )的方法来获得每个符合条件的Entity。Liberator EJB3 Persistence运行环境的Query查询 在构造Query的时候的只是把EJB3 QL编译成相应的SQL，但并不执行。只有当应用代码第一次调用Iterator.next(),Iterator.hasNext()或者List.get( int )方法的时候,编译后的SQL才会被真正的执行。 </p>
						<p>在Liberator EJB3 Persistence运行环境返回的结果集合中，并不保存所有的结果，而只是保持一个指向JDBC ResultSet或者缓存ResultSet的一个行(row)指针。只有当用户确实需要获得Entity实例的时候，才会从ResultSet中获取数据并填充到Entity实例中返回给应用。 </p>
						<p>如果查询结果结合中包含所有符合条件的Entity, Liberator EJB3 Persistence运行环境默认会自动缓存每次查询的结果。这样下次同样的查询操作就无需访问数据库，而直接从缓存中返回结果集合。但如果在下次查询操作之前，有针对被缓存的Entity类进行update/insert/delete操作，则缓存的结果集合会自动被清空，这样下次查询就会从数据库获得数据， 确保查询总是获得正确的结果，避免缓存脏数据。</p>
						<p>有时候查询会返回海量的数据。Liberator EJB3运行环境采用了自适应的弱引用POJO管理机制，可以处理海量的数据。在我们的测试中和客户的环境可以处千万级别的数据量。但在处理大数据量的时候，注意关闭对集合结果的缓存。</p>
						<div class="source">
								<pre>                
    
    // 假设返回的结果数量巨大
    final Query query = entityManager.createQuery( "select o from Order o");
    
    // 关闭对查询结果的缓存
    query.setHint( Constants.QUERY_RESULT_CACHE, "false");
    final List result = query.getResultList();
    final Iterator iterator = result.iterator();
    
    // 这里我们可以处理海量的数据
    while( iterator.hasNext() ){
        //　处理Order
    }
                
            </pre>
						</div>　　</div>
				<div class="section">
						<a name="简单查询">
						</a>
						<h2>简单查询</h2>下面是一个简单查询的例子，可以看到和SQL的使用方法很类似。 
<div class="source"><pre>                
    final Query query = entityManager.createQuery( "select o from Order o where o.id = 1");
    
    final Query query = entityManager.createQuery( "select o from Order o where o.id = 1 and o.confirm = 'true' ");
    
    final Query query = entityManager.createQuery( "select o from Order o where o.id = 1 or o.customer = 'foo' ");
    
    
    // address是Order类上的一个对象变量属性，Address有一个streetNumber的属性
    final Query query = entityManager.createQuery( "select o from Order o where o.address.streetNumber &gt;= 123" );

              
    </pre></div>注意条件语句中查询的是Entity的属性，属性的名字需要和Entity中的属性变量名字一致。 </div>
				<div class="section">
						<a name="使用参数查询">
						</a>
						<h2>使用参数查询</h2>
						<p>参数查询也和SQL中的参数查询类似。EJB3 QL支持两种方式的参数定义方式: 命名参数和位置参数。在同一个查询中只允许使用一种参数定义方式。</p>命名参数: 
<div class="source"><pre>                
    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" );
              
    </pre></div>注意不允许在同一个查询中使用两个相同名字的命名参数。 
<p>位置参数： </p><div class="source"><pre>                
    final Query query = entityManager.createQuery( "select o from Order o where o.id = ?1");
    
    // 设置查询中的参数
    query.setParameter( 1, 2 );// 1表示第一个参数，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" );
              
    </pre></div>如果在未来需要在不同的EJB3 运行环境中运行，请使用位置参数，保证应用是可移植的。 </div>
				<div class="section">
						<a name="排序_order_by_">
						</a>
						<h2>排序(order by)</h2>下面是一个简单查询的例子，可以看到和SQL的使用方法很类似。"ASC"和"DESC"分别为升序和降序，如果不显式注明，EJB3 QL中默认为asc升序。 
<div class="source"><pre>                
    // 不注明的话，默认为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");
            
    </pre></div></div>
				<div class="section">
						<a name="查询部分属性">
						</a>
						<h2>查询部分属性</h2>在前面的例子中，都是对针对Entity类的查询，返回的也是被查询的Entity类的实体。EJB3 QL也允许我们直接查询返回我们需要的属性，而不是返回整个Entity。在一些Entity中属性特别多的情况，这样的查询可以提高性能。 
<div class="source"><pre>                
    // 直接查询我们感兴趣的属性(列）
    final Query query = entityManager.createQuery( "select o.id, o.customerName, o.address.streetNumber from Order o order by o.id");
    
    // 集合中的不再是Order,而是一个Object[]对象数组
    final List result = query.getResultList();
    
    // 第一个行
    Object[] row = result.get( 0 );
    
    // 数组中的第一个值是id
    int id = Integer.parseInt( row[0].toString() );
    String customerName = row[1].toString();
    String streetNumber = Integer.parseInt( row[2].toString() );
   
            
    </pre></div></div>
				<div class="section">
						<a name="查询中使用构造器_Constructor_">
						</a>
						<h2>查询中使用构造器(Constructor)</h2>EJB3 QL支持将查询的属性结果直接作为一个java class的构造器参数，并产生实体作为结果返回。 
<div class="source"><pre>                
    // 我们把需要的三个属性作为一个class( OrderHolder )的构造器参数，并使用new函数。                
    Query query = entityManager.createQuery("select new com.redsoft.ejb3.dummy.OrderHolder (   o.id, o.vender, o.partNumber  )  FROM Order AS o");
    
    // 集合中的结果是OrderHolder
    List result = query.getResultList();
            
         
    </pre></div>该java class不需要是Entity Class。<strong>NEW</strong>要求java class使用全名。 </div>
				<div class="section">
						<a name="聚合查询_Aggregation_">
						</a>
						<h2>聚合查询(Aggregation)</h2>
						<p>象大部分的SQL一样,EJB3 QL也支持查询中的聚合函数。目前EJB QL支持的聚合函数包括：</p>
						<ul>
								<li>AVG 
</li>
								<li>SUM 
</li>
								<li>COUNT 
</li>
								<li>MAX 
</li>
								<li>MIN </li>
						</ul>
						<div class="source">
								<pre>                    
                    
    final Query query = entityManager.createQuery( "select MAX( o.id ) from Order where o.customerName='foo'");
        
    // 如果我们知道结果是单个，我们可以用getSingleResult()获得结果
    final Object result = query.getSingleResult();
        
    // 由于Order中id的类型为long,
    final Long max = (Long)result;
        
        
    // 在一些数据库中max函数返回的结果的类型不一定于id对应的列的类型相符，更安全的方式可以采用string来转型
    fina long max = Long.parseLong( result.toString() );
                
        </pre>
						</div>聚合函数也可以作为被查询的一个属性返回。 
<div class="source"><pre>                    
    
    // 返回所有的订单的生产厂商和他们的订单价值总额
    final Query query 
        = entityManager.createQuery( "select o.vender, sum(o.amount) FROM Order o　group by o.vender");");
                
        </pre></div><p>和SQL一样，如果聚合函数不是select...from的唯一一个返回列，需要使用"GROUP BY"语句。"GROUP BY"应该包含select语句中除了聚合函数外的所有属性。</p><div class="source"><pre>                    
    
    // 返回所有的订单的生产厂商的的名字，货物号码和每种货物的订单价值总额
    // 注意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.vender，o.partNumber");
                
        </pre></div><p>如果还需要加上查询条件，需要使用"HAVING"条件语句而不是"WHERE"语句。</p><div class="source"><pre>                    
    
    // 返回所有的订单的生产厂商是"foo"的货物号码和每种货物的订单价值总额
    // 这里"having o.vender = 'foo'为条件
    final Query query 
        = entityManager.createQuery( "select o.vender, o.partNumber, sum(o.amount) FROM Order o　
            group by o.vender，o.partNumber having o.vender='foo'");
        
        </pre></div><p>在"HAVING"语句里可以跟"WHERE"语句一样使用参数。</p><div class="source"><pre>                    
    
    // 返回所有的订单的生产厂商是"foo"的货物号码和每种货物的订单价值总额
    // 这里"having o.vender = 'foo'为条件
    final Query query 
        = entityManager.createQuery( "select o.vender, o.partNumber, sum(o.amount) FROM Order o　
            group by o.vender，o.partNumber having o.vender=?1");
    query.setParameter( 1, "foo" );
    final List result = query.getResultList();
        
        </pre></div></div>
				<div class="section">
						<a name="关联_join_">
						</a>
						<h2>关联(join)</h2>
						<p>在EJB3 QL中，大部分的情况下，使用对象属性都隐含了关联(join)。例如在以下查询中：</p>
						<div class="source">
								<pre>                
    final Query query = entityManager.createQuery( "select o from Order o
         where o.address.streetNumber=2000 order by o.id");
   
            
    </pre>
						</div>当这个句EJB3 QL编译成以下的SQL时就会自动包含了关联,EJB3 QL编译成SQL时关联默认取左关联(left join)。 
<div class="source"><pre>    
    select o.id, o.vender, o.partNumber, o.amount, addressTable.id, addressTable.streetNumber 
        from orderTable as o left join addressTable where addressTable.streetNumber = 2000
      
    </pre></div><p>但在一些情况下，我们仍然需要对关联做精确的控制。因此EJB3 QL仍然支持和SQL中类似的关联语法：</p><ul><li>left out join/left join 
</li><li>inner join 
</li><li>left join/inner join fetch </li></ul><p><strong>left join, left out join</strong>等义，都是允许符合条件的右边表达式中的Entiies为空。</p><div class="source"><pre>                
    // 返回所有地址为2000的Order纪录，不管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");
   
                
    </pre></div><p>由于EJB3 QL默认采用left join。这样的查询和以下的EJB3 QL其实是等价的。</p><div class="source"><pre>                
    // 返回所有地址为2000的Order纪录，不管Order中是否有OrderItem                
    final Query query = entityManager.createQuery( "select o from Order o
          where o.address.streetNumber=2000 order by o.id");
   
                
    </pre></div><p>需要显式使用left join/left outer join的情况会比较少。</p><p><strong>inner join</strong>要求右边的表达式必须返回Entities。</p><div class="source"><pre>                
    // 返回所有地址为2000的Order纪录，Order中必须有OrderItem                
    final Query query = entityManager.createQuery( "select o from Order o
         inner join o.orderItems where o.address.streetNumber=2000 order by o.id");
   
                
    </pre></div><p><strong>left/left out/inner join fetch</strong>提供了一种灵活的查询加载方式来提高查询的性能。在默认的查询中，Entity中的集合属性默认不会被关联，集合属性默认是缓加载( lazy-load )。</p><div class="source"><pre>                
                
``` // 默认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();
    
    // 这时获得Order实体中orderItems( 集合属性变量 )为空
    final Order order = (Order)result.get( 0 )
    
    // 当应用需要时，EJB3 Runtime才会执行一条SQL语句来加载属于当前Order的OrderItems
    Collection orderItems = order.getOrderItems();
   
                
    </pre></div><p>这样的查询性能上有不足的地方。为了查询N个Order，我们需要一条SQL语句获得所有的Order的原始/对象属性， 但需要另外N条语句获得每个Order的orderItems集合属性。为了避免N+1的性能问题，我们可以利用join fetch一次过用一条SQL语句把Order的所有信息查询出来。</p><div class="source"><pre>                
    // 返回所有地址为2000的Order纪录，Order中必须有OrderItem                
    final Query query = entityManager.createQuery( "select o from Order o
         inner join fetch o.orderItems where o.address.streetNumber=2000 order by o.id");
   
             
    </pre></div><p>由于使用了fetch,这个查询只会产生一条SQL语句，比原来需要N+1条SQL语句在性能上有了极大的提升。</p></div>
				<div class="section">
						<a name="比较Entity">
						</a>
						<h2>比较Entity</h2>
						<p>在查询中使用参数查询时，参数类型除了String, 原始数据类型( int, double等)和它们的对象类型( Integer, Double等),也可以是Entity的实例。</p>
						<div class="source">
								<pre>                
    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 );
  
             
    </pre>
						</div>
				</div>
				<div class="section">
						<a name="批量更新_Batch_Update_">
						</a>
						<h2>批量更新(Batch Update)</h2>
						<p>EJB3 QL支持批量更新。</p>
						<div class="source">
								<pre>                
   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();
            
    </pre>
						</div>
				</div>
				<div class="section">
						<a name="批量删除_Batch_Remove_">
						</a>
						<h2>批量删除(Batch Remove)</h2>
						<p>EJB3 QL支持批量删除。</p>
						<div class="source">
								<pre>                
    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();            
    
    
    
    </pre>
						</div>
				</div>
				<div class="section">
						<a name="使用操作符NOT">
						</a>
						<h2>使用操作符NOT</h2>
						<div class="source">
								<pre>                
                
    // 查询所有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();            
    </pre>
						</div>
				</div>
				<div class="section">
						<a name="使用操作符BETWEEN">
						</a>
						<h2>使用操作符BETWEEN</h2>
						<div class="source">
								<pre>                
                
    // 查询所有价值amount在５和10之间的(包含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();
         
    </pre>
						</div>
				</div>
				<div class="section">
						<a name="使用操作符IN">
						</a>
						<h2>使用操作符IN</h2>
						<div class="source">
								<pre>                
    // 查询所有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();
                        
         
    </pre>
						</div>
				</div>
				<div class="section">
						<a name="使用操作符LIKE">
						</a>
						<h2>使用操作符LIKE</h2>
						<div class="source">
								<pre>                
    // 查询所有vender以字符串"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以字符串"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();
    
    
    // 可以结合NOT一起使用，比如查询所有vender不以以字符串"foo"结尾的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();
    
    // 可以结合escape使用，比如查询所有vender以"foo"开始的Order并忽略'3'字符。
    // 如果vender是"foo1", "foo2", "foo3"符合这个条件, 另外"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();
    
    
                        
         
    </pre>
						</div>
				</div>
				<div class="section">
						<a name="使用操作符IS_NULL">
						</a>
						<h2>使用操作符IS NULL</h2>
						<div class="source">
								<pre>                
    // 查询所有没有地址的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();
    
                        
         
    </pre>
						</div>
				</div>
				<div class="section">
						<a name="使用操作符IS_EMPTY">
						</a>
						<h2>使用操作符IS EMPTY</h2>
						<p>
								<strong>IS EMPTY</strong>是针对集合属性(Collection)的操作符。可以和<strong>NOT</strong>一起使用。</p>
						<div class="source">
								<pre>                
    // 查询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();                     
         
    </pre>
						</div>
				</div>
				<div class="section">
						<a name="使用操作符EXISTS">
						</a>
						<h2>使用操作符EXISTS</h2>
						<p>
								<strong>[NOT]EXISTS</strong>需要和子查询配合使用。</p>
						<div class="source">
								<pre>                
    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");
         
    </pre>
						</div>
				</div>
				<div class="section">
						<a name="使用操作符ALL_SOME_ANY">
						</a>
						<h2>使用操作符ALL/SOME/ANY</h2>
						<div class="source">
								<pre>                
    Query query = managerNew.createQuery("select emp from EmployeeA emp where emp.salary &gt; 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 &gt; 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 &gt; some ( select m.salary from Manager m where m.department = emp.department)");
    List result = query.getResultList();
         
    </pre>
						</div>
				</div>
				<div class="section">
						<a name="字符串函数">
						</a>
						<h2>字符串函数</h2>
						<p>EJB3 QL定义了内置函数方便使用。这些函数的使用方法和SQL中相应的函数方法类似。EJB3 QL中定义的字符串函数包括：</p>
						<ul>
								<li>CONCAT　字符串拼接 
</li>
								<li>SUBSTRING　字符串截取 
</li>
								<li>TRIM 去掉空格 
</li>
								<li>LOWER　转换成小写 
</li>
								<li>UPPER　装换成大写 
</li>
								<li>LENGTH 字符串长度 
</li>
								<li>LOCATE 字符串定位 </li>
						</ul>
						<div class="source">
								<pre>       
    // concat将参数中的两个字符串并结成一个字符串,这里firstName是"foo", lastName是"bar"
    Query query = entityManager.createQuery("select concat( o.owner.firstName, o.owner.lastName ) FROM Order AS o left outer join o.orderItems as oi where o.owner.firstName='foo'");
    List result = query.getResultList();
    assertEquals("foobar", result.get(0).toString()); 
        
    // firstName是"fooBar",结果应该返回"oo"
    Query query = entityManager.createQuery("select o.vender,substring( o.owner.firstName, 1, 3 ), o.owner.info.age FROM Order AS o left outer join o.orderItems as oi where o.owner.firstName='charles'");
    List result = query.getResultList();
    Object[] row1 = (Object[]) result.get(0);
    assertEquals("oo", row1[1].toString());
    
    // 获得"ar"在firstName中地起始位置
    Query query = managerNew.createQuery("SELECT emp.firstName , emp.salary , locate( emp.firstName, 'ar') FROM EmployeeA as emp where emp.firstName='charles1111'");
    List result = query.getResultList();
        
         
    </pre>
						</div>
				</div>
				<div class="section">
						<a name="计算函数">
						</a>
						<h2>计算函数</h2>
						<p>EJB3 QL中定义的计算函数包括：</p>
						<ul>
								<li>ABS　绝对值 
</li>
								<li>SQRT 平方根 
</li>
								<li>MOD 取余数 
</li>
								<li>SIZE 取集合的数量 </li>
						</ul>
						<div class="source">
								<pre>       
    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");
        
         
    </pre>
						</div>
				</div>
				<div class="section">
						<a name="子查询">
						</a>
						<h2>子查询</h2>
						<p>子查询可以用于WHERE和HAVING条件语句中。</p>
						<div class="source">
								<pre>       
    Query query = managerNew.createQuery("select emp from EmployeeA as emp where ( select count(m) from Manager as m where m.department = emp.department) &gt; 0 ");
    List result = query.getResultList();   
         
    </pre>
						</div>
				</div>
		</div>
<img src ="http://www.blogjava.net/liaojiyong/aggbug/56216.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-07-02 23:35 <a href="http://www.blogjava.net/liaojiyong/archive/2006/07/02/56216.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用EJB3.O简化EJB开发（全中文）（转）</title><link>http://www.blogjava.net/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.blogjava.net/liaojiyong/archive/2006/06/30/55919.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/55919.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/06/30/55919.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/55919.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/55919.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 使用EJB3.O简化EJB开发    原著：Debu Panda								我们引入EJB来构造分布式的组件。它诞生之时是为了解决所有CORBA的问题和复杂性。经历过几次重要的版本更新和增加许多特性之后，EJB已经成为了J2EE的核心。在早期，很多开发人员沉迷于EJB甚至在没有任何意义的情况下在他们的工程中使用EJB。而当他们发现所使用的工程并没有质的变化后，谴责EJB成了一种趋势...&nbsp;&nbsp;<a href='http://www.blogjava.net/liaojiyong/archive/2006/06/30/55919.html'>阅读全文</a><img src ="http://www.blogjava.net/liaojiyong/aggbug/55919.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-06-30 11:49 <a href="http://www.blogjava.net/liaojiyong/archive/2006/06/30/55919.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用EJB3.O简化EJB开发（转）</title><link>http://www.blogjava.net/liaojiyong/archive/2006/06/30/55914.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Fri, 30 Jun 2006 03:46:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/06/30/55914.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/55914.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/06/30/55914.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/55914.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/55914.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Simplifying EJB Development with EJB3.0								使用EJB3.O简化EJB开发October 2004																																Discussion																												讨论												Enterp...&nbsp;&nbsp;<a href='http://www.blogjava.net/liaojiyong/archive/2006/06/30/55914.html'>阅读全文</a><img src ="http://www.blogjava.net/liaojiyong/aggbug/55914.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-06-30 11:46 <a href="http://www.blogjava.net/liaojiyong/archive/2006/06/30/55914.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第一个EJB3.0范例（转）</title><link>http://www.blogjava.net/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.blogjava.net/liaojiyong/archive/2006/06/30/55909.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/55909.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/06/30/55909.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/55909.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/55909.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 2004				年				7				月，				EJB				专家委员会公布了新的				EJB3.0				规范草本。				2004				年				10				月				7				号，				JBoss				发布了支持				EJB3.0				的第一个预览版本				jboss-EJB-3.0_Preview_1...&nbsp;&nbsp;<a href='http://www.blogjava.net/liaojiyong/archive/2006/06/30/55909.html'>阅读全文</a><img src ="http://www.blogjava.net/liaojiyong/aggbug/55909.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-06-30 11:38 <a href="http://www.blogjava.net/liaojiyong/archive/2006/06/30/55909.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JBoss4中对EJB3.0支持的Hibernate3和数据源的配置（转）</title><link>http://www.blogjava.net/liaojiyong/archive/2006/06/30/55906.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Fri, 30 Jun 2006 03:35:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/06/30/55906.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/55906.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/06/30/55906.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/55906.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/55906.html</trackback:ping><description><![CDATA[
		<div class="postText">
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
						<span>
								<font face="宋体">
										<strong>JBoss4中对EJB3.0支持的Hibernate3和数据源的配置</strong>
								</font>
								<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?>
								<o:p>
								</o:p>
						</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">    JBoss EJB3.0</span>
						<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">建立在<span lang="EN-US">Hibernate 3.0</span>之上。配置数据源你的实体<span lang="EN-US">bean</span>需要创建<span lang="EN-US">hibernate. Properties</span>配置文件。在<span lang="EN-US">EJB 3.0</span>部署包下有一个默认的<span lang="EN-US">hibernate</span>配置文件<span lang="EN-US">ejb3.deployer/META-INF/hibernate.properties</span>。<br /><br /><span lang="EN-US"><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" align="left">
						<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">    请参考我们附带的<span lang="EN-US">Hibernate 3.0</span>的文档来了解如何配置<span lang="EN-US">hibernate.properties</span>文件中的各个值。这里只做一些说明。<br /><br /><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">hibernate.transaction.manager_lookup_class=org.hibernate.transaction.JBossTransactionManagerLookup<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">hibernate.hbm2ddl.auto=create-drop<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">hibernate.cache.provider_class=org.hibernate.cache.HashtableCacheProvider<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">hibernate.connection.datasource=java:/DefaultDS<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">hibernate.dialect=org.hibernate.dialect.HSQLDialect<br /><br /><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" align="left">
						<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">    上面是<span lang="EN-US">EJB3.0</span>应用程序下<span lang="EN-US">ejb3.deployer/META-INF/hibernate.properties</span>默认的配置文件<br /><br /><span lang="EN-US"><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" align="left">
						<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">hibernate.connection.datasource</span>
						<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">指向<span lang="EN-US">JBoss</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-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-pagination: widow-orphan" align="left">
						<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">hibernate.dialect</span>
						<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">默认为<span lang="EN-US">Hypersonic SQL</span>，但是你可以改变为其他数据库方言如<span lang="EN-US">Oracle</span>。可以参考<span lang="EN-US">Hibernate 3.0</span>的文档。<span lang="EN-US"><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" align="left">
						<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">hibernate.hbm2ddl.auto=create-drop</span>
						<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">建立部署中的数据库图表，并在取消部署的时候删除他们。<span lang="EN-US"><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" align="left">
						<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">hibernate.transaction.manager_lookup_class</span>
						<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">定义了<span lang="EN-US">Hibernates</span>的事务管理。它一般不能改变。<span lang="EN-US"><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" align="left">
						<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">hibernate.cache.provider_class</span>
						<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">定义了<span lang="EN-US">Hibernate</span>将要使用的缓存结构。如果你在集群中使用你也许要考虑<span lang="EN-US">JBoss</span>的缓存。<br /><br /><span lang="EN-US"><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">Hibernate.properties</span>文件<span lang="EN-US"><o:p></o:p></span></span>
						</b>
				</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
						<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">    你或许需要替换默认的<span lang="EN-US">hibernate.properties</span>文件。那么使用上面提到的变量定义一个最小配置来建立一个你自己的<span lang="EN-US">hibernate.properties</span>文件。然后将文件放在你得<span lang="EN-US">.ejb3 jar </span>目录下的<span lang="EN-US">META-INF/</span>下或打入<span lang="EN-US">JAR</span>包。</span>
				</p>
		</div>
<img src ="http://www.blogjava.net/liaojiyong/aggbug/55906.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-06-30 11:35 <a href="http://www.blogjava.net/liaojiyong/archive/2006/06/30/55906.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3.0中JNDI的绑定和多通路传输（转）</title><link>http://www.blogjava.net/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.blogjava.net/liaojiyong/archive/2006/06/30/55903.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/55903.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/06/30/55903.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/55903.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/55903.html</trackback:ping><description><![CDATA[
		<div class="postTitle">
				<a href="http://blog.csdn.net/yiboo/archive/2005/01/22/263869.aspx">
				</a> </div>
		<div 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>会以路径或远程接口的全名绑定到<span lang="EN-US">JNDI</span>。你可以通过定义你自己的<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>绑定<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">远程接口的<span lang="EN-US">JNDI</span>绑定<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>来改变你远程接口的<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">多通路传输和客户端拦截（<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">）<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>架构来展现一个会话<span lang="EN-US">bean</span>通过多通路传输的远程调用。现在仅仅一些插件支持。可以查看<span lang="EN-US">JBoss</span>文档中怎样定义传送<span lang="EN-US">MBean</span>。要展现一个会话<span lang="EN-US">bean</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" 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 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">绑定指定了代理将捆绑的<span lang="EN-US">JNDI</span>名字。<span lang="EN-US"><o:p></o:p></span></span>
						</li>
						<li 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">拦截堆栈（<span lang="EN-US">interceptorStack</span>）允许你插入数据到一个<span lang="EN-US">JBoss AOP</span>（栈结构）。会话<span lang="EN-US">bean</span>客户端拦截器（<span lang="EN-US">SessionBeanClientInterceptors</span>）栈可以在你部署得文件夹下的<span lang="EN-US">ejb3-interceptors-aop.xml</span>配置文件中找到。<span lang="EN-US"><o:p></o:p></span></span>
						</li>
						<li 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">定义了客户端用来绑定服务器的<span lang="EN-US">JBoss</span>远程<span lang="EN-US">URL</span>。<span lang="EN-US"><o:p></o:p></span></span>
						</li>
						<li 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">这里是一个例子：<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.blogjava.net/liaojiyong/aggbug/55903.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-06-30 11:30 <a href="http://www.blogjava.net/liaojiyong/archive/2006/06/30/55903.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>什么时候用EJB ，什么时候不用EJB？</title><link>http://www.blogjava.net/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.blogjava.net/liaojiyong/archive/2006/06/30/55899.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/55899.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/06/30/55899.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/55899.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/55899.html</trackback:ping><description><![CDATA[
		<h3> </h3>
		<p>
		</p>
		<p>参考 Enterprise JavaBeans 4</p>
		<p>这篇文章 讲述了何时使用EJB，何时不用EJB，以及用哪些可以替代EJB！</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 href="http://www.exolab.org/" rel="nofollow">http://www.exolab.org</a>)</p>
		<p>Hibernate (<a href="http://www.hibernate.org/" rel="nofollow">http://www.hibernate.org</a>)</p>
		<p>Prevayler (<a href="http://www.prevayler.org/" 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.blogjava.net/liaojiyong/aggbug/55899.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-06-30 11:21 <a href="http://www.blogjava.net/liaojiyong/archive/2006/06/30/55899.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3.0开发指南之无状态会话Bean</title><link>http://www.blogjava.net/liaojiyong/archive/2006/06/30/55845.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Fri, 30 Jun 2006 00:31:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/06/30/55845.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/55845.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/06/30/55845.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/55845.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/55845.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 在所有的				EJB3.0				规范中定义的				EJB				，都不必实现				Home				接口。																																　　一个会话				Bean				必须有一个业务接口，这个接口由会话				Bean				来实现，或者也可以由会话				Bean				来产生...&nbsp;&nbsp;<a href='http://www.blogjava.net/liaojiyong/archive/2006/06/30/55845.html'>阅读全文</a><img src ="http://www.blogjava.net/liaojiyong/aggbug/55845.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-06-30 08:31 <a href="http://www.blogjava.net/liaojiyong/archive/2006/06/30/55845.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3 Persistence开发手册</title><link>http://www.blogjava.net/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.blogjava.net/liaojiyong/archive/2006/06/28/55514.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/55514.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/06/28/55514.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/55514.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/55514.html</trackback:ping><description><![CDATA[
		<ol>
				<li>
						<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/overview.html">EJB3 Persistence API介绍</a>
						<ol>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/overview.html#Why EJB3(为什么要引入EJB3)">为什么要引入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 href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/overview.html#EJB_3中的元数据批注:Annotation">EJB 3中的元数据批注:Annotation</a>
								</li>
						</ol>
				</li>
				<li>
						<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/helloWorld.html">第一个Entity Bean:HelloWorld</a>
				</li>
				<li>
						<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/Entity.html">解说Entity</a>
						<ol>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/Entity.html#定义对Entity中属性的访问">定义对Entity中属性的访问</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/Entity.html#主键和实体标识（Primary_Key_and_Entity_Identity_">主键和实体标识（Primary Key and Entity Identity)</a>
								</li>
						</ol>
				</li>
				<li>
						<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/EntityManager.html#操作持久化Entity">操作Entity</a>
						<ol>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/EntityManager.html#配置和获得EntityManager">配置和获得EntityManager</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/EntityManager.html#Entity的生命周期和状态">Entity的生命周期和状态</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/EntityManager.html#持久化Entity_Persist_">持久化Entity</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/EntityManager.html#获取Entity">获取Entity</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/EntityManager.html#更新Entity">更新Entity</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/EntityManager.html#删除Entity">删除Entity</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/EntityManager.html#分离_附合_Detach_Merge_">分离/附合(Detach/Merge)</a>
								</li>
						</ol>
				</li>
				<li>
						<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#EJB3_QL查询">EJB3 QL查询</a>
						<ol>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#Query接口">Query接口</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#简单查询">简单查询</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#使用参数查询">使用参数查询</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#排序_order_by_">排序(order by)</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#查询部分属性">查询部分属性</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#查询中使用构造器_Constructor_">查询中使用构造器(Constructor)</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#聚合查询_Aggregation_">聚合查询(Aggregation)</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#关联_join_">关联(join)</a>
										<ul>
												<li>
														<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#关联_join_">left join/left out join</a>
												</li>
												<li>
														<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#关联_join_">inner join</a>
												</li>
												<li>
														<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#关联_join_">left/inner join fetch</a>
												</li>
										</ul>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#比较Entity">比较Entity</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#批量更新_Batch_Update_">批量更新(Batch Update)</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#批量删除_Batch_Remove_">批量删除(Batch Remove)</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#使用操作符NOT">使用操作符NOT</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#使用操作符BETWEEN">使用操作符BETWEEN</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#使用操作符IN">使用操作符IN</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#使用操作符LIKE">使用操作符LIKE</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#使用操作符IS_NULL">使用操作符IS NULL</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#使用操作符IS_EMPTY">使用操作符IS EMPTY</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#使用操作符EXISTS">使用操作符EXISTS</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#使用操作符ALL_SOME_ANY">使用操作符ALL/SOME/ANY</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#字符串函数">字符串函数</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#计算函数">计算函数</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/query.html#子查询">子查询</a>
								</li>
						</ol>
				</li>
				<li>
						<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/nativeSql.html#原生SQL查询">原生SQL查询(Native SQL)</a>
				</li>
				<li>关系／对象映射 
<ol><li><a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/one2one.html">一对一映射</a></li><li><a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/one2many.html">一对多映射</a></li><li><a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/many2many.html">多对多映射</a></li><li><a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/inheritance.html">继承</a></li></ol></li>
				<li>
						<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html">关系对象映射元数据</a>
						<ol>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#Table">Table</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#SecondaryTable">SecondaryTable</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#SecondaryTables">SecondaryTables</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#UniqueConstraint">UniqueConstraint</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#Column">Column</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#JoinColumn">JoinColumn</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#JoinColumns">JoinColumns</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#Id">Id</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#IdClass">IdClass</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#MapKey">MapKey</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#OrderBy">OrderBy</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#PrimaryKeyJoinColumn">PrimaryKeyJoinColumn</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#PrimaryKeyJoinColumns">PrimaryKeyJoinColumns</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#Transient">Transient</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#Version">Version</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#Lob">Lob</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#JoinTable">JoinTable</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#TableGenerator">TableGenerator</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#SequenceGenerator">SequenceGenerator</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#DiscriminatorColumn">DiscriminatorColumn</a>
								</li>
								<li>
										<a href="http://www.redsoftfactory.com/chinese/ejb3/docs/zh/ref/ormannotation.html#DiscriminatorColumn">DiscriminatorColumn</a>
								</li>
						</ol>
				</li>
		</ol>
<img src ="http://www.blogjava.net/liaojiyong/aggbug/55514.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-06-28 12:23 <a href="http://www.blogjava.net/liaojiyong/archive/2006/06/28/55514.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3 Demo(转)</title><link>http://www.blogjava.net/liaojiyong/archive/2006/06/27/55367.html</link><dc:creator>liaojiyong</dc:creator><author>liaojiyong</author><pubDate>Tue, 27 Jun 2006 09:14:00 GMT</pubDate><guid>http://www.blogjava.net/liaojiyong/archive/2006/06/27/55367.html</guid><wfw:comment>http://www.blogjava.net/liaojiyong/comments/55367.html</wfw:comment><comments>http://www.blogjava.net/liaojiyong/archive/2006/06/27/55367.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liaojiyong/comments/commentRss/55367.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liaojiyong/services/trackbacks/55367.html</trackback:ping><description><![CDATA[
		<div class="h2" id="longdescription">
				<h2>描述</h2>
				<div>
						<h1>EJB3 Demo</h1>
						<p>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:</p>
						<ol>
								<li>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. 
</li>
								<li>Establish design and coding patterns that result in simplicity, and promote a rapid development approach, without sacrificing good design principles. </li>
						</ol>
						<h2>Current status</h2>
						<p>A few experimental projects are available from the download area. These are:</p>
						<ol>
								<li>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. 
</li>
								<li>tpcc-persist-oracle - this packages the same entity classes for Oracle. 
</li>
								<li>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. 
</li>
								<li>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. 
</li>
								<li>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. 
</li>
								<li>tpcc-web - Contains very simple web interfaces that allow experimentation with EJBs. 
</li>
								<li>tpcc-ea - Builds and deploys EAR file to the J2EE server. The objective here is to explore packaging options. </li>
						</ol>
						<h2>How you can help</h2>
						<p>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.</p>
						<p>I would also welcome essays and articles that describe design patterns that will lead to portability, simplicity, and reusability of code.</p>
						<p>It would be nice if someone could take these projects and make them work under JBOSS.</p>
						<p>A test of the EJB 3.0 technology will be to deploy the Business Logic and DAO layer as Beans using the Spring Framework.</p>
						<p>If you would like to participate in this project, please request an appropriate role and <a href="mailto:dibyendumajumdar@dev.java.net">email</a> me describing what you would like to work on.</p>
						<h2>News</h2>
						<ul>
								<li>09-Mar-06 - Ported the entities to Oracle. 
</li>
								<li>23-Feb-06 - Refreshed the project code. 
</li>
								<li>14-Feb-06 - Uploaded an initial set of projects. </li>
						</ul>
						<h2>Downloads</h2>
						<p>The latest code can be obtained <a href="https://ejb3demo.dev.java.net/servlets/ProjectDocumentList">here</a>. Note that this is work in progress, and therefore changing frequently.</p>
						<h2>Articles</h2>
						<p>Todo.</p>
						<h2>Links</h2>
						<ul>
								<li>
										<a href="http://trycatchfinally.blogspot.com/">Blog</a> about EJB 3.0 and Java programming in general. 
</li>
								<li>
										<a href="https://glassfish.dev.java.net/">Glassfish</a> - Sun's OpenSource Java EE 5.0 Application Server. </li>
						</ul>
				</div>
		</div>
<img src ="http://www.blogjava.net/liaojiyong/aggbug/55367.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liaojiyong/" target="_blank">liaojiyong</a> 2006-06-27 17:14 <a href="http://www.blogjava.net/liaojiyong/archive/2006/06/27/55367.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>