﻿<?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-delvin</title><link>http://www.blogjava.net/devin/</link><description /><language>zh-cn</language><lastBuildDate>Sun, 12 Apr 2026 18:08:43 GMT</lastBuildDate><pubDate>Sun, 12 Apr 2026 18:08:43 GMT</pubDate><ttl>60</ttl><item><title>配置连接池（Tomcat+Spring）</title><link>http://www.blogjava.net/devin/archive/2010/08/17/329129.html</link><dc:creator>delvin</dc:creator><author>delvin</author><pubDate>Tue, 17 Aug 2010 09:45:00 GMT</pubDate><guid>http://www.blogjava.net/devin/archive/2010/08/17/329129.html</guid><wfw:comment>http://www.blogjava.net/devin/comments/329129.html</wfw:comment><comments>http://www.blogjava.net/devin/archive/2010/08/17/329129.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/devin/comments/commentRss/329129.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/devin/services/trackbacks/329129.html</trackback:ping><description><![CDATA[<p>这几天刚参加一个新项目，项目是使用Spring+Tomcat。在开发时，页面速度很慢，今天研究了一下，发现时因为没有使用连接池。<br />
添加如下连接池，速度明显提高很多。<br />
<br />
&lt;bean id="dataSource" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource" destroy-method="close"&gt;<br />
&nbsp; &lt;property name="driverClassName"&gt; <br />
&nbsp;&nbsp;&nbsp; &lt;value&gt;${jdbc.driver}&lt;/value&gt;<br />
&nbsp; &lt;/property&gt;<br />
&nbsp; &lt;property name="url"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;value&gt;${jdbc.url}&lt;/value&gt;<br />
&nbsp; &lt;/property&gt;<br />
&nbsp; &lt;property name="username"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;value&gt;${jdbc.username}&lt;/value&gt;<br />
&nbsp; &lt;/property&gt;<br />
&nbsp; &lt;property name="password"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;value&gt;${jdbc.password}&lt;/value&gt;<br />
&nbsp; &lt;/property&gt;<br />
&nbsp; &lt;property name="initialSize"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;value&gt;2&lt;/value&gt;<br />
&nbsp; &lt;/property&gt;<br />
&nbsp; &lt;property name="maxActive"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;value&gt;5&lt;/value&gt;<br />
&nbsp; &lt;/property&gt;<br />
&nbsp; &lt;property name="maxIdle"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;value&gt;2&lt;/value&gt;<br />
&nbsp; &lt;/property&gt;<br />
&lt;/bean&gt;</p>
<img src ="http://www.blogjava.net/devin/aggbug/329129.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/devin/" target="_blank">delvin</a> 2010-08-17 17:45 <a href="http://www.blogjava.net/devin/archive/2010/08/17/329129.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何分割内容中含有分割符的CSV</title><link>http://www.blogjava.net/devin/archive/2010/08/06/328106.html</link><dc:creator>delvin</dc:creator><author>delvin</author><pubDate>Fri, 06 Aug 2010 02:46:00 GMT</pubDate><guid>http://www.blogjava.net/devin/archive/2010/08/06/328106.html</guid><wfw:comment>http://www.blogjava.net/devin/comments/328106.html</wfw:comment><comments>http://www.blogjava.net/devin/archive/2010/08/06/328106.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/devin/comments/commentRss/328106.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/devin/services/trackbacks/328106.html</trackback:ping><description><![CDATA[今天在解析CSV中遇到一个问题，就是csv内容中含有分割符，这里假定分割符就是逗号，当然这些内容用双引号括起来了。<br />
因以前的代码是使用C++ Tr1 的regex<br />
<p>&nbsp;vector&lt;string&gt;&nbsp;&nbsp; Parser::parse(string&amp; line)<br />
&nbsp;{<br />
&nbsp;&nbsp; vector&lt;string&gt; fields;<br />
&nbsp;&nbsp; std::tr1::regex&nbsp; re(","); <br />
&nbsp;&nbsp;if( &amp;line !=&nbsp; NULL) <br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sregex_token_iterator i(line.begin(), line.end(), re, -1); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sregex_token_iterator j; <br />
&nbsp;&nbsp;&nbsp;while (i != j) <br />
&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;fields.push_back(*i++);<br />
&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;return fields;</p>
<p>&nbsp;}<br />
<br />
查了资料，修改成如下代码就可以<br />
</p>
<p>&nbsp;vector&lt;string&gt;&nbsp;&nbsp; Parser::parse(string&amp; line)<br />
&nbsp;{<br />
&nbsp;&nbsp; vector&lt;string&gt; fields;<br />
&nbsp;&nbsp; std::tr1::regex&nbsp; re("<span style="color: red">(?!\".*),(?!.*\")");&nbsp;</span><br />
&nbsp;&nbsp;if( &amp;line !=&nbsp; NULL) <br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sregex_token_iterator i(line.begin(), line.end(), re, -1); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sregex_token_iterator j; <br />
&nbsp;&nbsp;&nbsp;while (i != j) <br />
&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;fields.push_back(*i++);<br />
&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;return fields;</p>
<p>&nbsp;}</p>
<img src ="http://www.blogjava.net/devin/aggbug/328106.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/devin/" target="_blank">delvin</a> 2010-08-06 10:46 <a href="http://www.blogjava.net/devin/archive/2010/08/06/328106.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JPA cache(转载)</title><link>http://www.blogjava.net/devin/archive/2010/07/22/326837.html</link><dc:creator>delvin</dc:creator><author>delvin</author><pubDate>Thu, 22 Jul 2010 06:38:00 GMT</pubDate><guid>http://www.blogjava.net/devin/archive/2010/07/22/326837.html</guid><wfw:comment>http://www.blogjava.net/devin/comments/326837.html</wfw:comment><comments>http://www.blogjava.net/devin/archive/2010/07/22/326837.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/devin/comments/commentRss/326837.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/devin/services/trackbacks/326837.html</trackback:ping><description><![CDATA[<h2 class="title">JPA Caching</h2>
<style>
#edit-taxonomy-6-wrapper{display:none} /*feed category*/
</style>
<style>
#edit-taxonomy-4-wrapper{display:none} /*comm homepage*/
</style>
<div class="blog-node node">
<div id="blog-submitted">Posted by <a href="/blog/7773" jquery1279780260492="39">caroljmcdonald</a> on August 21, 2009 at 12:58 PM PDT</div>
<div class="content">
<h1>JPA Caching</h1>
<h2>JPA Level 1 caching </h2>
JPA has 2 levels of caching. The first level of caching is the persistence context. <br />
<img alt="" src="http://blogs.sun.com/carolmcdonald/resource/lev1lev2.jpg" /><br />
The JPA Entity Manager maintains a set of Managed Entities in the Persistence Context. <br />
<img alt="" src="http://blogs.sun.com/carolmcdonald/resource/img26.jpg" /><br />
The Entity Manager guarantees that within a single Persistence Context, for any particular database row, there will be only one object instance. However the same entity could be managed in another User's transaction, so you should use either optimistic or pessimistic locking&nbsp; as explained in <a href="http://blogs.sun.com/carolmcdonald/entry/jpa_2_0_concurrency_and" target="_blank" jquery1279780260492="40">JPA 2.0 Concurrency and locking</a><br />
<img alt="" src="http://blogs.sun.com/carolmcdonald/resource/img57.jpg" /><br />
The code below shows that a find on a managed entity with the same id and class as another in the same persistence context , will return the same instance. <br />
<br />
<table style="text-align: left; width: 100%" border="0" cellspacing="2" cellpadding="2">
    <tbody>
        <tr>
            <td style="vertical-align: top"><code>@Stateless public ShoppingCartBean implements ShoppingCart {<br />
            <br />
            &nbsp;@PersistenceContext EntityManager entityManager;<br />
            <br />
            &nbsp;public OrderLine createOrderLine(Product product,Order order) {<br />
            &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; OrderLine orderLine = new OrderLine(order, product);<br />
            &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; entityManager.persist(<span style="color: rgb(0,102,0); font-weight: bold">orderLine</span>);&nbsp;&nbsp;<span style="color: rgb(51,51,255); font-weight: bold"> //Managed</span><br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OrderLine <span style="color: rgb(204,0,0); font-weight: bold">orderLine2</span> =entityManager.find(OrderLine,<br />
            &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(0,102,0); font-weight: bold">orderLine.getId()</span>));<br />
            &nbsp;&nbsp;&nbsp;<span style="font-weight: bold">&nbsp;&nbsp;&nbsp;&nbsp; (</span><span style="color: rgb(0,102,0); font-weight: bold">orderLine</span><span style="font-weight: bold"> == <span style="color: rgb(204,0,0)">orderLine2</span>)&nbsp;</span><span style="color: rgb(51,51,255); font-weight: bold">&nbsp; // TRUE</span><br />
            &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return (orderLine);<br />
            &nbsp;&nbsp;&nbsp; }<br />
            <br />
            }<br />
            </code></td>
        </tr>
    </tbody>
</table>
<br />
The diagram below shows the life cycle of an Entity in relation to the Persistent Context. <br />
<img alt="" src="http://blogs.sun.com/carolmcdonald/resource/img28.jpg" /> <br />
The code below illustrates the life cycle of an Entity. A reference to a container managed EntityManager is injected using the persistence context annotation. A new order entity is created and the entity has the state of new. Persist is called, making this a managed entity. because it is a stateless session bean it is by default using container managed transactions , when this transaction commits , the order is made persistent in the database. When the orderline entity is returned at the end of the transaction it is a detached entity.<br />
<img alt="" src="http://blogs.sun.com/carolmcdonald/resource/img29.jpg" /><br />
The Persistence Context can be either Transaction Scoped-- the Persistence Context 'lives' for the length of the transaction, or Extended-- the Persistence Context spans multiple transactions. With a Transaction scoped Persistence Context, Entities are "Detached" at the end of a transaction. <br />
<img alt="" src="http://blogs.sun.com/carolmcdonald/resource/img48.jpg" /><br />
As shown below, to persist the changes on a detached entity, you call the EntityManager's merge() operation, which returns an updated managed entity, the entity updates will be persisted to the database at the end of the transaction. <br />
<img alt="" src="http://blogs.sun.com/carolmcdonald/resource/img49.jpg" /><br />
An Extended Persistence Context spans multiple transactions, and the set of Entities in the Persistence Context stay Managed. This can be useful in a work flow scenario where a "conversation" with a user spans multiple requests. <br />
<img alt="" src="http://blogs.sun.com/carolmcdonald/resource/img51.jpg" /><br />
The code below shows an example of a Stateful Session EJB with an Extended Persistence Context in a use case scenario to add line Items to an Order. After the Order is persisted in the createOrder method, it remains managed until the EJB remove method is called. In the addLineItem method , the Order Entity can be updated because it is managed, and the updates will be persisted at the end of the transaction.<br />
<br />
<img alt="" src="http://blogs.sun.com/carolmcdonald/resource/img52.jpg" /><br />
The example below contrasts updating the Order using a transaction scoped Persistence Context verses an extended Persistence context. With the transaction scoped persistence context, an Entity Manager find must be done to look up the Order, this returns a Managed Entity which can be updated. With the Extended Persistence Context the find is not necessary. The performance advantage of not doing a database read to look up the Entity, must be weighed against the disadvantages of memory consumption for caching, and the risk of cached entities being updated by another transaction.&nbsp; Depending on the application and the risk of contention among concurrent transactions this may or may not give better performance / scalability. <br />
<img alt="" src="http://blogs.sun.com/carolmcdonald/resource/img54.jpg" /><br />
<h2>JPA second level (L2) caching </h2>
JPA second level (L2) caching shares entity state across various persistence contexts.<br />
<img style="width: 468px; height: 283px" alt="" src="http://blogs.sun.com/carolmcdonald/resource/lev1lev2.jpg" /><br />
<br />
JPA 1.0 did not specify support of a second level cache, however, most of the persistence providers provided support for second level cache(s). JPA 2.0 specifies support for basic cache operations with the new Cache API, which is accessible from the EntityManagerFactory, shown below:<br />
<br />
<img alt="" src="http://blogs.sun.com/carolmcdonald/resource/img73.jpg" /><br />
If L2 caching is enabled, entities not found in persistence context, will be loaded from L2 cache, if found.<br />
<img alt="" src="http://blogs.sun.com/carolmcdonald/resource/img69.jpg" /><br />
The advantages of L2 caching are:<br />
<ul>
    <li>avoids database access for already loaded entities
    <li>faster for reading frequently accessed&nbsp; unmodified entities<br />
    </li>
</ul>
The disadvantages of L2 caching are:<br />
<ul>
    <li>memory consumption for large amount of objects
    <li>Stale data for updated objects
    <li>Concurrency for write (optimistic lock exception, or pessimistic lock)
    <li>Bad scalability for frequent or concurrently updated entities<br />
    </li>
</ul>
<br />
You should configure L2 caching for entities that are: <br />
<ul>
    <li>read often
    <li>modified infrequently
    <li>Not critical if stale </li>
</ul>
You should protect any data that can be concurrently modified with a locking strategy: <br />
<ul>
    <li>Must handle optimistic lock failures on flush/commit
    <li>configure expiration, refresh policy to minimize lock failures </li>
</ul>
The Query cache is useful for queries that are run frequently with the same parameters, for not modified tables.<br />
<br />
<h3>The EclipseLink JPA persistence provider caching Architecture</h3>
The&nbsp; EclipseLink caching Architecture is shown below. <br />
<br />
<img alt="" src="http://blogs.sun.com/carolmcdonald/resource/img74.jpg" /><br />
Support for second level cache in EclipseLink is turned on by default, entities read are L2 cached. You can disable the L2 cache. EclipseLink caches entities in L2, Hibernate caches entity id and state in L2. You can configure caching by Entity type or Persistence Unit with the following configuration parameters:
<ul>
    <li>Cache isolation, type, size, expiration, coordination, invalidation,refreshing
    <li>Coordination (cluster-messaging)
    <li>Messaging: JMS, RMI, RMI-IIOP, &#8230;
    <li>Mode: SYNC, SYNC+NEW, INVALIDATE, NONE </li>
</ul>
The example below shows configuring the L2 cache for an entity using the @Cache annotation<br />
<img alt="" src="http://blogs.sun.com/carolmcdonald/resource/img76.jpg" /><br />
<h3>The Hibernate JPA persistence provider caching Architecture</h3>
The Hibernate JPA persistence provider caching architecture is different than EclipseLink: it is not configured by default, it does not cache enities just id and state, and you can plug in different L2 caches. The diagram below shows the different L2 cache types that you can plug into Hibernate. <br />
<img alt="" src="http://blogs.sun.com/carolmcdonald/resource/img77.jpg" /><br />
The configuration of the cache depends on the type of caching plugged in. The example below shows configuring the hibernate L2 cache for an entity using the @Cache annotation<br />
<img alt="" src="http://blogs.sun.com/carolmcdonald/resource/img78.jpg" /><br />
<h3>For More Information:</h3>
<a href="http://eclipse.dzone.com/articles/introducing-eclipselink?page=0,1" target="_blank" jquery1279780260492="41">Introducing EclipseLink </a><br />
<a href="http://wiki.eclipse.org/Category:JPA" target="_blank" jquery1279780260492="42">EclipseLink JPA User Guide </a><br />
<a href="http://docs.jboss.org/hibernate/stable/core/reference/en/html/performance.html#performance-cache" target="_blank" jquery1279780260492="43">Hibernate Second Level Cache </a><br />
<a href="http://www.devx.com/dbzone/Article/29685/1954" target="_blank" jquery1279780260492="44">Speed Up Your Hibernate Applications with Second-Level Caching </a><br />
<a href="http://www.javalobby.org/java/forums/t48846.html" target="_blank" jquery1279780260492="45">Hibernate caching </a><br />
<a href="http://developers.sun.com/learning/javaoneonline/j1sessn.jsp?sessn=TS-5214&amp;yr=2009&amp;track=javaee" target="_blank" jquery1279780260492="46">Java Persistence API 2.0: What's New ?</a><br />
<a href="http://www.apress.com/book/view/1430219548" target="_blank" jquery1279780260492="47">Beginning Java&#8482; EE 6 Platform with GlassFish&#8482; 3</a><br />
<a href="http://www.apress.com/book/view/1590596455" target="_blank" jquery1279780260492="48">Pro EJB 3: Java Persistence API</a> (JPA 1.0)<br />
<br />
<br />
<br />
<br />
<br />
</div>
<div class="links">&#187;
<ul class="links inline">
    <li class="blog_usernames_blog first"><a title="Read caroljmcdonald's latest blog entries." href="/blogs/caroljmcdonald" jquery1279780260492="49">caroljmcdonald's blog</a>
    <li class="comment_forbidden"><span><a href="/user/login?destination=comment%2Freply%2F257035%23comment-form" jquery1279780260492="50">Login</a> or <a href="/user/register?destination=comment%2Freply%2F257035%23comment-form" jquery1279780260492="51">register</a> to post comments</span> </li>
    <li class="statistics_counter"><span>11164 visits</span>
    <li class="print_html last"><a class="print-page" title="Display a printer-friendly version of this page." href="/print/257035" rel="nofollow" jquery1279780260492="52">Printer-friendly version</a> </li>
</ul>
</div>
<div class="taxonomy">Related Topics &gt;&gt; <a href="/blogs/topic/46" jquery1279780260492="53">Blogs</a> &nbsp; &nbsp; &nbsp; </div>
</div>
<div id="comment-header">Comments</div>
<div id="comment-header2">Comments are listed in date ascending order (oldest first)</div>
<div id="comments"><a id="comment-14752" jquery1279780260492="54"></a>
<div class="comment comment-published clear-block">
<h3><a class="active" href="/blog/archive/2009/08/21/jpa-caching#comment-14752" jquery1279780260492="55">Why gettting null EntityManager</a></h3>
<div class="submitted">Submitted by veeraj21 on Thu, 2010-05-06 12:42. </div>
<div class="content">eclep.jpa.DataSource org.wadsworth.check.dto.FacDto public abstract class BaseDao { @PersistenceContext(unitName = "eclepJTA") private EntityManager entityContext; @PersistenceUnit(unitName = "eclepJTA") private EntityManagerFactory emf; public void check(){ System.out.println("&lt; </div>
</div>
</div>
<img src ="http://www.blogjava.net/devin/aggbug/326837.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/devin/" target="_blank">delvin</a> 2010-07-22 14:38 <a href="http://www.blogjava.net/devin/archive/2010/07/22/326837.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>rebel.allow_bytecode_proxy作用</title><link>http://www.blogjava.net/devin/archive/2010/07/21/326735.html</link><dc:creator>delvin</dc:creator><author>delvin</author><pubDate>Wed, 21 Jul 2010 06:18:00 GMT</pubDate><guid>http://www.blogjava.net/devin/archive/2010/07/21/326735.html</guid><wfw:comment>http://www.blogjava.net/devin/comments/326735.html</wfw:comment><comments>http://www.blogjava.net/devin/archive/2010/07/21/326735.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/devin/comments/commentRss/326735.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/devin/services/trackbacks/326735.html</trackback:ping><description><![CDATA[在使用JRebel过程中发现，当代码中使用了javaassit或Cglib等增强字节码类库时，在IDE中调试时很容易进入那些代理的代码，而这些代码没有<br />
源码对应，无法调试，并且自己写的代码也很难调试，在启动java过程中只要设置-Drebel.allow_bytecode_proxy=true可以不进入那些代理的代码。
<img src ="http://www.blogjava.net/devin/aggbug/326735.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/devin/" target="_blank">delvin</a> 2010-07-21 14:18 <a href="http://www.blogjava.net/devin/archive/2010/07/21/326735.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java中noverify选项的作用</title><link>http://www.blogjava.net/devin/archive/2010/07/20/326618.html</link><dc:creator>delvin</dc:creator><author>delvin</author><pubDate>Tue, 20 Jul 2010 03:35:00 GMT</pubDate><guid>http://www.blogjava.net/devin/archive/2010/07/20/326618.html</guid><wfw:comment>http://www.blogjava.net/devin/comments/326618.html</wfw:comment><comments>http://www.blogjava.net/devin/archive/2010/07/20/326618.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/devin/comments/commentRss/326618.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/devin/services/trackbacks/326618.html</trackback:ping><description><![CDATA[今天在用JRebel时，发现启动Java虚拟机时，很多JRebel参考资料说都要加上-noverify选项。记得以前没有看到过这个选项，就顺便学习了一下。<br />
<br />
noverify就是关闭检验bytecode，就是为了提高性能。在使用javaagent时，用这个选项，就可以关闭修改后的bytecode不用校验，提高了速度。
<img src ="http://www.blogjava.net/devin/aggbug/326618.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/devin/" target="_blank">delvin</a> 2010-07-20 11:35 <a href="http://www.blogjava.net/devin/archive/2010/07/20/326618.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB（EJB1和EJB2）到底有什么问题</title><link>http://www.blogjava.net/devin/archive/2010/07/16/326325.html</link><dc:creator>delvin</dc:creator><author>delvin</author><pubDate>Fri, 16 Jul 2010 08:35:00 GMT</pubDate><guid>http://www.blogjava.net/devin/archive/2010/07/16/326325.html</guid><wfw:comment>http://www.blogjava.net/devin/comments/326325.html</wfw:comment><comments>http://www.blogjava.net/devin/archive/2010/07/16/326325.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/devin/comments/commentRss/326325.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/devin/services/trackbacks/326325.html</trackback:ping><description><![CDATA[<p><br />
EJB俨然成为了一个任人打扮的小姑娘。现在你只要和一个国内Java开发人员交流，基本都能听到他们说EJB的缺点，即使他没有使用过。<br />
为此我花了点时间，试图分析下EJB的优点和缺点，以及EJB对Java技术社区的贡献。<br />
<br />
我使用了EJB有6年时间，从接触Java就开始学习EJB,使用过EJB1，EJB2和EJB3。<br />
<br />
我总结的EJB(EJB1和EJB2)存在的问题有：</p>
<strong>目标定位不清<br />
编成模型复杂<br />
开发和移植困难<br />
部署描述符陷阱<br />
类加载陷阱<br />
测试困难<br />
破坏面向对象设计<br />
部署慢<br />
运行时需要EJB容器，代价高<br />
维护困难<br />
学习曲线大<br />
</strong><br />
下面我们逐一分析<br />
<strong>一 目标定位不清<br />
</strong>假如你看过EJB早期规范，你会发现，规范中队EJB的目标定位有11项之多。为了分析方便，我引用了EJB2.1版本中有关EJB目标定义的内容（注：序号是我加上的）。<br />
The Enterprise JavaBeans (EJB) architecture has the following goals:<br />
&nbsp;1）The Enterprise JavaBeans architecture will be the standard component architecture for build-<br />
ing distributed object-oriented business applications in the Java programming language.<br />
&nbsp;2）The Enterprise JavaBeans architecture will support the development, deployment, and use of<br />
web services.<br />
3）The Enterprise JavaBeans architecture will make it easy to write applications: Application<br />
developers will not have to understand low-level transaction and state management details,<br />
multi-threading, connection pooling, or other complex low-level APIs.<br />
4）&nbsp;Enterprise JavaBeans applications will follow the Write Once, Run Anywhere? philosophy of<br />
the Java programming language. An enterprise bean can be developed once, and then<br />
deployed on multiple platforms without recompilation or source code modi?cation.<br />
5）&nbsp;The Enterprise JavaBeans architecture will address the development, deployment, and runtime<br />
aspects of an enterprise application&#8217;s life cycle.<br />
6）&nbsp;The Enterprise JavaBeans architecture will define the contracts that enable tools from multiple<br />
vendors to develop and deploy components that can interoperate at runtime.<br />
7）The Enterprise JavaBeans architecture will make it possible to build applications by combin-<br />
ing components developed using tools from different vendors.<br />
8）&nbsp;The Enterprise JavaBeans architecture will provide interoperability between enterprise beans<br />
and Java 2 Platform, Enterprise Edition (J2EE) components as well as non-Java programming<br />
language applications.<br />
9）&nbsp;The Enterprise JavaBeans architecture will be compatible with existing server platforms. Ven-<br />
dors will be able to extend their existing products to support Enterprise JavaBeans.<br />
10）&nbsp;The Enterprise JavaBeans architecture will be compatible with other Java programming lan-<br />
guage APIs.<br />
11）The Enterprise JavaBeans architecture will be compatible with the CORBA protocols<br />
<br />
从这些目标中我们可以发现，几乎没有目标是针对开发人员效率的。从这次目标中我们就可以隐约的感到EJB不是对开发者友好的技术。<br />
从这些目标中，我们可以发现EJB的雄心过于庞大，而EJB出现的时代，还不足以在一个规范中解决这些问题。从EJB后来被人诟病最多的实体Bean，只是EJB的一小部分，但恰恰就这点就要了EJB的命。<br />
<br />
EJB目标中把本不应该放在一起的东西给放在了一起，比如分布式和实体映射。而且错误的假定了使用分布式的场合。按照Spring创始人的说法<br />
，分布式只有20%的应用要用，而80%是不需要的。<br />
我们现在知道EJB目标不清楚，那我们免不了要问，当初Sun为什么要这样定位EJB？<br />
也许除了EJB早期规范组的人，没有人真正清楚为什么，我们此处只能留到以后事后诸葛亮下（注：此处我以后会用一片文章来分析产生的原因）。<br />
<br />
二 <strong>编成模型复杂</strong><br />
<p>EJB组成复杂：<br />
&nbsp;一个EJB有好几个东西组成，具体有主接口 ，远程/本地接口，Bean类，部署描述符<br />
虽然开发社区发展了Xdoclet技术，但也只是解决了一部分问题。用Xdoclet，编译时需要产生代码，当EJB多时，这是很耗时的。<br />
<br />
有过开发经验的人都知道要是修改一个小东西需要修改几个文件的话，那工作效率是上不去的，另外在考虑到EJB的需要部署，启动服务器的时间，修改EJB简直是痛苦啊。这样必然导致开发周期长。<br />
&nbsp; 编写（定义接口，&nbsp; 实现Bean，&nbsp;编写部署描述符）-》打包部署-》&nbsp;&nbsp;&nbsp;&nbsp; 启动服务器-》测试。</p>
<p>早期开发中，我们还遵守规范中按角色编程的要求，导致角色多，沟通成本高，比如Bean开发者开发Bean，部署员打包部署，系统管理者管理服务器。<br />
<br />
<br />
<br />
</p>
三 <strong>移植困难（特别是Entity Bean）</strong><br />
规范中说的编写一次，到处部署的承诺，基本是一句空话。结果变成了编写一次，到处重写。特别是实体Bean，基本上迁移一个服务器，就相当于用HIbernate重新的工作量，还不考虑测试的困难性。规范中对实体映射定义的太过于宽泛，导致每个厂商都需要自己的ORM实现，引入&nbsp;特定厂商的部署描述符，又因为J2EE中除web外，类加载的定义没有明确，导致产生特定厂商的类加载机制和打包方式，还有就是特定厂商的服务查找方式。<br />
<br />
四 <strong>部署描述符陷阱<br />
</strong>&nbsp;1）EJB采用了当时流行的使用Xml作为粘合剂，并且实现厂商都引入了自己的配置文件。结果导致编写过多的配置文件。以JBoss为例要写要写三个配置文件。XML配置文件复杂，手工编写比较困难，早期IDE中可视化编写XML效率有不高，导致开发人员开发效率大大降低。更痛苦的是修改后，不能及时生效。大家想象一下，如果你有多个EJB，修改一个需要重新部署和启动服务器，那是怎样的浪费时间。以我曾经的一个项目为例，约有100个EJB，部署和重启JBoss需要几分钟，重要不是浪费时间，而是那种挫折感。<br />
&nbsp;2）标准的ejb-jar.xml部署描述符把一些重要的信息（比如指定EJB的JNDI名字和配置实例池）都留给容器提供商，<br />
我们一般都需要一个额外，特定于容器的的部署描述符，比如weblogic-ejb-jar.xml。这样导致编写和移植的困难。<br />
<br />
五 <strong>类加载陷阱（类加载器复杂，并且不清晰）<br />
</strong><br />
J2EE规范（Java EE）对EAR中web和ejb的加载没有明确定义。比如一个EAR有多个EJB，每个EJB都依赖一些其他类库，那么对这些被依赖的类库到底是怎么被加载的，类的可见性怎么样，规范没有规定。这样每个厂商都有自己的一套东西，导致不同服务上，要用不同的打包方式。<br />
<strong><br />
</strong>六&nbsp;&nbsp; <strong>测试困难<br />
</strong>J2EE测试难是有目共睹的，其中EJB测试困难时出了名的。测试困难的原因时，EJB运行需要容器插入什么服务，而启动服务器是很高昂的代价。<br />
后来虽然开发社区采用Mock等技术试图解决这个问题，但从开发实践来说，还是有难度的。<br />
<br />
<span style="color: red">注</span>: 以下几点问题，还需要详细分析，由于时间问题，暂时只是列出来。<br />
七&nbsp;&nbsp; <strong>破坏面向对象设计<br />
</strong>八 &nbsp;<strong>开发周期长，部署慢<br />
</strong>九 &nbsp;<strong>运行时需要EJB容器，代价高<br />
</strong>十 <strong>&nbsp;维护困难<br />
</strong><br />
但说实话EJB也是有贡献，当然它的贡献更多是理念层次，在实现层面很失败。另外，也正是他的失误，在批判EJB的基础上发展起Spring，给开发人员带来一股新风。<br />
<img src ="http://www.blogjava.net/devin/aggbug/326325.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/devin/" target="_blank">delvin</a> 2010-07-16 16:35 <a href="http://www.blogjava.net/devin/archive/2010/07/16/326325.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从EJB得到的启示</title><link>http://www.blogjava.net/devin/archive/2010/07/16/325862.html</link><dc:creator>delvin</dc:creator><author>delvin</author><pubDate>Fri, 16 Jul 2010 07:36:00 GMT</pubDate><guid>http://www.blogjava.net/devin/archive/2010/07/16/325862.html</guid><wfw:comment>http://www.blogjava.net/devin/comments/325862.html</wfw:comment><comments>http://www.blogjava.net/devin/archive/2010/07/16/325862.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/devin/comments/commentRss/325862.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/devin/services/trackbacks/325862.html</trackback:ping><description><![CDATA[&nbsp;当我们回顾EJB从红火场面，到最后被很多开发人员抛弃的历程，我们可以获得很多启示。<br />
<br />
一 大厂商提倡的技术，并不都是好的，要敢于怀疑规范本身和大厂商<br />
当年，EJB凭借Sun，IBM等大厂家的支持，在市场上呼风唤雨，可以说是集三千宠信于一身。<br />
但慢慢的开发人员发现，EJB的很难用，开发效率低下。但由于EJB是大厂商支持，大多数开发人员刚开始都还没有对EJB进行怀疑，而是只是怀疑自己的技术水平。但随着时间的推移，开发社区中慢慢有怀疑的声音出现，但那些技术厂家，还在鼓吹什么EJB的大规模集群等特性，而对开发人员提出的问题视而不见。这时，有些优秀的开发人员已经行动起来，他们对那些规范厂商已经不抱什么幻想，随着Spring和Hibernate的不断发展，规范组发现自己真的错了，他们最终不得不向这些开源框架靠近。<br />
<br />
二 技术的使用者才是判定技术好坏的最终标准<br />
<br />
在其他行业，我们都明白一个浅显的道理。那就是，客户是上帝，客户具有最终发言权。顺着这个思路，我们这些普通开发人员不正是Sun，IBM，Microsoft的客户吗？为什么我们一直以来都是听他们给我们布道呢？ 通过EJB的惨痛教训，在我使用某项技术之前，不再轻信那些大厂的承诺。<br />
<br />
兄弟姐妹们，大胆怀疑那些大厂的技术吧! 不要对只要是那些厂家提供的技术就盲目轻信？ 使用新技术，请从怀疑开始，要不然你会失望的！<br />
<br />
三 开源社区已经成长为一个可以和技术大厂抗衡的力量<br />
<br />
EJB的发展充分表明了，那些大厂唬人的东西是不可靠的。开源社区已经是一个不可小视的力量。<br />
<br />
四 当你感觉某项技术不好时，请去改变他吧 
<img src ="http://www.blogjava.net/devin/aggbug/325862.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/devin/" target="_blank">delvin</a> 2010-07-16 15:36 <a href="http://www.blogjava.net/devin/archive/2010/07/16/325862.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在团队工作应该具有的习惯（软件）-团队工作之三</title><link>http://www.blogjava.net/devin/articles/326308.html</link><dc:creator>delvin</dc:creator><author>delvin</author><pubDate>Fri, 16 Jul 2010 06:54:00 GMT</pubDate><guid>http://www.blogjava.net/devin/articles/326308.html</guid><wfw:comment>http://www.blogjava.net/devin/comments/326308.html</wfw:comment><comments>http://www.blogjava.net/devin/articles/326308.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/devin/comments/commentRss/326308.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/devin/services/trackbacks/326308.html</trackback:ping><description><![CDATA[在上文<a href="http://www.blogjava.net/devin/articles/326303.html">团队和小组的区别-团队工作之二 </a>中我们简单阐明了团队的特征。那么在这么我们就想问一个顺理成章的问题，若我在一个团队中工作，应该需要养成哪些习惯来提升团队工作？<br />
<br />
下面我简单谈一下个人感受，由于我本人并不是团队工作研究的专家，也不是什么伟大团队的成员，因此我的话可能没有什么过深的道理，也因为这一点，可能更易于实践。<br />
<br />
1.了解团队的目标和使命<br />
<br />
这一点之所以重要，是因为团队目标和使命是团队得以成立或存在的根本原因。有些新人对自己的个人目标比较清楚，但对自己所处的团队目标不清楚，导致其看不到很多事和机会。一个最聪明的人，若不清楚团队目标的话，在团队中被淘汰的可能性比较大。<br />
假若你不是成心要被团队淘汰，那就请了解你的团队目标吧。<br />
<br />
2.定位自己的角色<br />
<br />
团队工作讲究技能互补，优势互补，为此你需要清楚自己的优势是什么，团队中差什么技能？若你具有其他人没有的技能和优势，那么就不会被并集给并掉。一个成熟了团队都有一个相对规定的角色，你要分析清楚团队中需要什么角色，你适合什么角色，早日定好自己的角色，并按此角色去行事。<br />
<br />
3.学会帮助别人<br />
在团队中，没有严格的谁应该做什么。因管理要求，需要有任务划分，指派给具体人，你也应该明白，若别人的任务完成不好，对你也是有影响的。为此，对需要时刻关注团队中其他人在做什么，能不能提供帮组。大家明白，篮球比赛中没有个人胜利者，只有球队胜利者。最好的球员，若球队不赢球，那都没有什么价值，总不能说我打的好，我们球队不行。在开发工作中，有时也是这样的。<br />
<br />
4.设法通过自己的努力提升团队<br />
我们经常说有木桶短板效应。但我想说，反过来也有长板效应。有些工作，可以通过团队中最优秀的人来做，提高这方面的水准，这也是团队的目的之一。为此，我们需要设法提升自己，来提升团队。<br />
<br />
5.积极主动去影响团队<br />
有些新人，因为担心别人说不听话（这是中国教育的严重失误啊，先痛心下！），就报着别人说什么我做什么。在会上征求意见时，也是说我听领导的。慢慢的，别人不在关注他的意见，自己也越来越没有意见。我们说影响团队，不要仅仅理解为影响什么大方向，也可以是影响一件具体事和做法。<br />
<br />
6.减少对他人不必要的干扰<br />
我经常对新加入项目的人说，我们开发工作，有时类似于治病工作。需要注意治好之前，先要确保不是治坏。不要因为自己的加入，不但没有工作量，还影响其他人的工作，比如提交不能编译的代码，撰写不合格的文档。<br />
<br />
 <img src ="http://www.blogjava.net/devin/aggbug/326308.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/devin/" target="_blank">delvin</a> 2010-07-16 14:54 <a href="http://www.blogjava.net/devin/articles/326308.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>团队和小组的区别-团队工作之二</title><link>http://www.blogjava.net/devin/articles/326303.html</link><dc:creator>delvin</dc:creator><author>delvin</author><pubDate>Fri, 16 Jul 2010 06:18:00 GMT</pubDate><guid>http://www.blogjava.net/devin/articles/326303.html</guid><wfw:comment>http://www.blogjava.net/devin/comments/326303.html</wfw:comment><comments>http://www.blogjava.net/devin/articles/326303.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/devin/comments/commentRss/326303.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/devin/services/trackbacks/326303.html</trackback:ping><description><![CDATA[<p>我们现在在日常生活和工作中，经常听到人说我们的团队这样，那样的情况。但根据我的观察，能称为团队的不多，只不过又一次显示了中国人喜欢使用时髦名词的习惯（关于这一点，有很多可说，在此不展开），也是不喜欢思考，喜欢随大流，怕别人嘲笑跟不上潮流的一个反应。<br />
<br />
很多人口中的团队，不过是小组的别称罢了，有时候连小组都不是，只不过是一帮乌黑之众罢了。<br />
<br />
各位看官，为了不被那些满嘴跑名词的人忽悠，我们有必要思考下团队是什么，团队和小组的区别，优秀团队的特质。<br />
<br />
团队特征：具有一致的目标，角色和技能互补，互相发扬长处和避免短处。<br />
<br />
团队有一组人组成，但仅有一组人还不能称为团队，成为团队还需要有共同目标，具有某些共同的价值观，知道互相要取长补短，在一起有加法效应，互相帮助，激发潜能。<br />
<br />
正因为有这些特征，我才敢说很多人所谓的团队，不过是一组人罢了。我们太喜欢内斗了，而团队最不要的就是内斗，而这些民族特性是不会轻易改变的，是民族的基因，也许表面上80后或90后和以前的年代人不同，但实际上在这些民族性上没有多大改变。<br />
<br />
我们见过了太多的单打独斗的故事，所谓的团队故事也只是某人成功后的一种说辞。<br />
<br />
请问，你现在是在团队的状态中工作，还是停留在小组的阶段呢？ 你真的相信你的领导口中的团队吗？ 各位需要我们去思考啊，不能让那些忽悠人的人经常忽悠我们啊，虽然由于历史问题，中国人不怎么会思考，但好歹也要思考下，不能让那些满嘴跑火车的人上台啊。</p>
<img src ="http://www.blogjava.net/devin/aggbug/326303.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/devin/" target="_blank">delvin</a> 2010-07-16 14:18 <a href="http://www.blogjava.net/devin/articles/326303.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>任务概念模型-工作流之二 （未完）</title><link>http://www.blogjava.net/devin/articles/326284.html</link><dc:creator>delvin</dc:creator><author>delvin</author><pubDate>Fri, 16 Jul 2010 03:47:00 GMT</pubDate><guid>http://www.blogjava.net/devin/articles/326284.html</guid><wfw:comment>http://www.blogjava.net/devin/comments/326284.html</wfw:comment><comments>http://www.blogjava.net/devin/articles/326284.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/devin/comments/commentRss/326284.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/devin/services/trackbacks/326284.html</trackback:ping><description><![CDATA[<br />
1.目的和意义<br />
<br />
在实现工作流系统过程中，我们发现工作流系统中如何自动产生任务，如何分派，如何完成，如何和其他任务集成是一个复杂的问题。<br />
<br />
要想能解决这些复杂的问题，没有一个完整的概念模型，在开发过程中就会出现需要的功能彼此冲突，顾得了这个就顾不了那个，程序员就会处于顾此失彼的状态。而这些问题的解决需要在逻辑层面，也就是概念层面，而不能延迟到实现层面，及编码层面。<br />
<br />
有了任务概念模型，我们从模型就可以判断它的处理能力和功能。<br />
<br />
2.任务模型需要考虑的层面<br />
<br />
从<a title="现实任务分析" href="http://www.blogjava.net/devin/articles/306405.html" target="_blank">现实任务分析-工作流系统之一</a> 这篇文章中，我们可以发现，即使一个简单的流程涉及的任务也是很复杂的，需要考虑的方面非常多。我们只有对这些层面进行深入的分析才能设计出一个较好的任务概念模型。<br />
下面我们具体分析任务涉及的各个方面，并提出在模型中如何表达。大体分为：<br />
&nbsp;<br />
&nbsp;任务产生<br />
&nbsp;任务传递<br />
&nbsp;任务状态<br />
任务关系&nbsp; <br />
2.1 任务产生<br />
在现实中任务的产生非常复杂。自己可以给自己创建任务，比如，我想去看刚上映的电影，我就给自己周么设定一个任务，去买电影票。还有些任务是从其他人那儿分派来的，有些任务是有其他任务分拆来的。若在软件系统中，有些任务是本软件系统产生（自动或手工），有些任务是有其他系统产生的。在工作流系统中，经常就遇到工作流系统本身产生的任务和从其他系统创建的任务问题，而客户希望在他的任务列表都一样的显示出来，并能处理。<br />
&nbsp;通过上面简单的描述，我们应该能感觉到任务产生的复杂性。为了对任务产生进行抽象，我们引入两个概念，任务来源和任务产生方式。<br />
任务来源用来表达任务是从哪里来的，比如来自工作流系统，来自张三，来自行政部。任务来源不限于就是人。在现实中，我们经常遇到某个部门的人给你下达任务，这个任务虽然是那个具体的人给你下达的，但实际上应该属于那个部门下达的，即使没有他，其他人在那个岗位也会下达，那个人只是一个代理人，毕竟部门不能说话。<br />
任务产生方式表达任务是怎么产生的，这个已经有点考虑到软件系统了。在现实中，没有什么手工和自动产生任务的区分。这种区分是把任务处理引入软件系统以后的事。 
  <img src ="http://www.blogjava.net/devin/aggbug/326284.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/devin/" target="_blank">delvin</a> 2010-07-16 11:47 <a href="http://www.blogjava.net/devin/articles/326284.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>