﻿<?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-J++ = Java + ?-随笔分类-frameworks</title><link>http://www.blogjava.net/killvin/category/8033.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 03:53:09 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 03:53:09 GMT</pubDate><ttl>60</ttl><item><title>并发问题及控制手段 </title><link>http://www.blogjava.net/killvin/archive/2006/04/06/39542.html</link><dc:creator>killvin</dc:creator><author>killvin</author><pubDate>Thu, 06 Apr 2006 02:57:00 GMT</pubDate><guid>http://www.blogjava.net/killvin/archive/2006/04/06/39542.html</guid><description><![CDATA[
		<div class="postTitle">
				<strong>
						<a href="http://www.cnblogs.com/zhenyulu/articles/208799.html ">
								<font color="#000000">http://www.cnblogs.com/zhenyulu/articles/208799.html</font>
						</a>
				</strong>
		</div>
		<div class="postText">
				<h1>第2章 并发问题及控制手段</h1>
				<p>什么是并发问题？假设有这么一家书吧，顾客可以到那里喝茶读书。顾客拿着选好要读的图书到柜台登记，然后找个地方去阅读，临走时将图书归还店家。有一天，一个顾客相中了一本书后正要拿去登记，另一个顾客的手也抓住了这仅有的一本书，并发问题出现了。两个顾客要读同一本书，互不相让，这让店主伤透了脑筋。这个案例仅仅是众多并发问题中的一个微小部分，但从中我们可以看出并发问题主要出现在多个用户对有限资源进行访问的时候，如果解决不好会直接影响系统的有效、正常运行。数据库是一个共享的资源，并发问题的出现是必不可免的，如何识别并发类型并加以控制是这一章重点要讲述的内容。</p>
				<p>本章将分成两大部分，一部分主要讲Visual FoxPro中并发控制机制。VFP中并发控制相对简单，数据加锁的形式比较单一，非常适合作为初步了解并发问题的切入点。第二部分以SQL Server 2000、ADO.NET以及C#为主要工具，深入了解并发一致性问题、封锁协议、事务隔离等内容，难度相对较深。象一些更为深入的并发控制手段，例如多粒度封锁和意象锁等内容在本章中将不做深入讨论，感兴趣可以参考相关书籍。</p>
				<p> </p>
				<p>[实在不好意思COPY别人的成果，不过这篇文章出奇的精彩，将并发操作的来龙去脉说的清清楚楚，也是我正要找的，比JAVAEYE上面所谓的专家叫嚷着什么"悲观锁"、"乐观锁"而不解是原因要强的多！值得收藏]</p>
		</div>
<img src ="http://www.blogjava.net/killvin/aggbug/39542.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killvin/" target="_blank">killvin</a> 2006-04-06 10:57 <a href="http://www.blogjava.net/killvin/archive/2006/04/06/39542.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>About unsaved-value [resource : javaeye] </title><link>http://www.blogjava.net/killvin/archive/2006/03/02/33297.html</link><dc:creator>killvin</dc:creator><author>killvin</author><pubDate>Thu, 02 Mar 2006 12:45:00 GMT</pubDate><guid>http://www.blogjava.net/killvin/archive/2006/03/02/33297.html</guid><description><![CDATA[<SPAN class=postbody>当你显式的使用session.save()或者session.update()操作一个对象的时候，实际上是用不到<SPAN style="COLOR: #ffa34f"><B>unsaved-value</B></SPAN>的。某些情况下(父子表关联保存)，当你在程序中并没有显式的使用save或者update一个持久对象，那么Hibernate需要判断被操作的对象究竟是一个已经持久化过的持久对象，是一个尚未被持久化过的内存临时对象。例如： <BR><BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B>java代码:&nbsp;<IMG style="CURSOR: hand" onclick="copycode('code2123680030')" src="http://forum.javaeye.com/copy.gif" border=0></B></SPAN></TD></TR>
<TR>
<TD class=code>
<DIV style="FONT-FAMILY: 'Courier New', Courier, monospace"><BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">1&nbsp;</SPAN>&nbsp;Session session = ...; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">2&nbsp;</SPAN>&nbsp;Transaction tx = ...; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">3&nbsp;</SPAN>&nbsp; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">4&nbsp;</SPAN>&nbsp;Parent parent = <SPAN style="COLOR: #000000">(</SPAN>Parent<SPAN style="COLOR: #000000">)</SPAN> session.<SPAN style="COLOR: #000000">load</SPAN><SPAN style="COLOR: #000000">(</SPAN>Parent.<SPAN style="COLOR: #000000">class</SPAN>, id<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">5&nbsp;</SPAN>&nbsp; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">6&nbsp;</SPAN>&nbsp;Child child = <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>new</SPAN> Child<SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">7&nbsp;</SPAN>&nbsp;child.<SPAN style="COLOR: #000000">setParent</SPAN><SPAN style="COLOR: #000000">(</SPAN>parent<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">8&nbsp;</SPAN>&nbsp;child.<SPAN style="COLOR: #000000">setName</SPAN><SPAN style="COLOR: #000000">(</SPAN>"sun"<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">9&nbsp;</SPAN>&nbsp; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">10</SPAN>&nbsp;parent.<SPAN style="COLOR: #000000">addChild</SPAN><SPAN style="COLOR: #000000">(</SPAN>child<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">11</SPAN>&nbsp;s.<SPAN style="COLOR: #000000">update</SPAN><SPAN style="COLOR: #000000">(</SPAN>parent<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">12</SPAN>&nbsp; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">13</SPAN>&nbsp;s.<SPAN style="COLOR: #000000">flush</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">14</SPAN>&nbsp;tx.<SPAN style="COLOR: #000000">commit</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">15</SPAN>&nbsp;s.<SPAN style="COLOR: #000000">close</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">)</SPAN>;</DIV><BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR>在上例中，程序并没有显式的session.save(child); 那么Hibernate需要知道child究竟是一个临时对象，还是已经在数据库中有的持久对象。如果child是一个新创建的临时对象(本例中就是这种情况)，那么Hibernate应该自动产生session.save(child)这样的操作，如果child是已经在数据库中有的持久对象，那么Hibernate应该自动产生session.update(child)这样的操作。 <BR><BR>因此我们需要暗示一下Hibernate，究竟child对象应该对它自动save还是update。在上例中，显然我们应该暗示Hibernate对child自动save，而不是自动update。那么Hibernate如何判断究竟对child是save还是update呢？它会取一下child的主键属性 child.getId() ，这里假设id是 java.lang.Integer类型的。如果取到的Id值和hbm映射文件中指定的unsave-value相等，那么Hibernate认为child是新的内存临时对象，发送save，如果不相等，那么Hibernate认为child是已经持久过的对象，发送update。 <BR><BR><SPAN style="COLOR: #ffa34f"><B>unsaved-value</B></SPAN>="null" (默认情况，适用于大多数对象类型主键 Integer/Long/String/...) <BR><BR>当Hibernate取一下child的Id，取出来的是null(在上例中肯定取出来的是null)，和<SPAN style="COLOR: #ffa34f"><B>unsaved-value</B></SPAN>设定值相等，发送save(child) <BR><BR>当Hibernate取一下child的id，取出来的不是null，那么和<SPAN style="COLOR: #ffa34f"><B>unsaved-value</B></SPAN>设定值不相等，发送update(child) <BR><BR>例如下面的情况： <BR><BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B>java代码:&nbsp;<IMG style="CURSOR: hand" onclick="copycode('code283016354')" src="http://forum.javaeye.com/copy.gif" border=0></B></SPAN></TD></TR>
<TR>
<TD class=code>
<DIV style="FONT-FAMILY: 'Courier New', Courier, monospace"><BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">1&nbsp;</SPAN>&nbsp;Session session = ...; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">2&nbsp;</SPAN>&nbsp;Transaction tx = ...; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">3&nbsp;</SPAN>&nbsp; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">4&nbsp;</SPAN>&nbsp;Parent parent = <SPAN style="COLOR: #000000">(</SPAN>Parent<SPAN style="COLOR: #000000">)</SPAN> session.<SPAN style="COLOR: #000000">load</SPAN><SPAN style="COLOR: #000000">(</SPAN>Parent.<SPAN style="COLOR: #000000">class</SPAN>, id<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">5&nbsp;</SPAN>&nbsp;Child child = <SPAN style="COLOR: #000000">(</SPAN>Child<SPAN style="COLOR: #000000">)</SPAN> session.<SPAN style="COLOR: #000000">load</SPAN><SPAN style="COLOR: #000000">(</SPAN>Child.<SPAN style="COLOR: #000000">class</SPAN>, childId<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">6&nbsp;</SPAN>&nbsp; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">7&nbsp;</SPAN>&nbsp;child.<SPAN style="COLOR: #000000">setParent</SPAN><SPAN style="COLOR: #000000">(</SPAN>parent<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">8&nbsp;</SPAN>&nbsp;child.<SPAN style="COLOR: #000000">setName</SPAN><SPAN style="COLOR: #000000">(</SPAN>"sun"<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">9&nbsp;</SPAN>&nbsp; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">10</SPAN>&nbsp;parent.<SPAN style="COLOR: #000000">addChild</SPAN><SPAN style="COLOR: #000000">(</SPAN>child<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">11</SPAN>&nbsp;s.<SPAN style="COLOR: #000000">update</SPAN><SPAN style="COLOR: #000000">(</SPAN>parent<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">12</SPAN>&nbsp; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">13</SPAN>&nbsp;s.<SPAN style="COLOR: #000000">flush</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">14</SPAN>&nbsp;tx.<SPAN style="COLOR: #000000">commit</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">15</SPAN>&nbsp;s.<SPAN style="COLOR: #000000">close</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">)</SPAN>;</DIV><BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR>child已经在数据库中有了，是一个持久化的对象，不是新创建的，因此我们希望Hibernate发送update(child)，在该例中，Hibernate取一下child.getId()，和unsave-value指定的null比对一下，发现不相等，那么发送update(child)。 <BR><BR>BTW: parent对象不需要操心，因为程序显式的对parent有load操作和update的操作，不需要Hibernate自己来判断究竟是save还是update了。我们要注意的只是child对象的操作。另外<SPAN style="COLOR: #ffa34f"><B>unsaved-value</B></SPAN>是定义在Child类的主键属性中的。 <BR><BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B>java代码:&nbsp;<IMG style="CURSOR: hand" onclick="copycode('code238960156')" src="http://forum.javaeye.com/copy.gif" border=0></B></SPAN></TD></TR>
<TR>
<TD class=code>
<DIV style="FONT-FAMILY: 'Courier New', Courier, monospace"><BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">1</SPAN>&nbsp;&lt;<SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>class</SPAN> name="Child" table="child"&gt; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">2</SPAN>&nbsp;&lt;id column="id" name="id" type="integer" <SPAN style="COLOR: #ffa34f"><B>unsaved-value</B></SPAN>="<SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>null</SPAN>"&gt; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">3</SPAN>&nbsp;&nbsp; &lt;generator <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>class</SPAN>="identity"/&gt; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">4</SPAN>&nbsp;&lt;/id&gt; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">5</SPAN>&nbsp;... <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">6</SPAN>&nbsp;&lt;/<SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>class</SPAN>&gt;</DIV><BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR>如果主键属性不是对象型，而是基本类型，如int/long/double/...，那么你需要指定一个数值型的<SPAN style="COLOR: #ffa34f"><B>unsaved-value</B></SPAN>，例如： <BR><BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B>java代码:&nbsp;<IMG style="CURSOR: hand" onclick="copycode('code187609985')" src="http://forum.javaeye.com/copy.gif" border=0></B></SPAN></TD></TR>
<TR>
<TD class=code>
<DIV style="FONT-FAMILY: 'Courier New', Courier, monospace"><BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">1</SPAN>&nbsp;unsaved-<SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>null</SPAN>="<SPAN style="COLOR: #000000" ?>0</SPAN>"</DIV><BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR>在此提醒大家，很多人以为对主键属性定义为int/long，比定义为Integer/Long运行效率来得高，认为基本类型不需要进行对象的封装和解构操作，因此喜欢把主键定义为int/long的。但实际上，Hibernate内部总是把主键转换为对象型进行操作的，就算你定义为int/long型的，Hibernate内部也要进行一次对象构造操作，返回给你的时候，还要进行解构操作，效率可能反而低也说不定。因此大家一定要扭转一个观点，在Hibernate中，主键属性定义为基本类型，并不能够比定义为对象型效率来的高，而且也多了很多麻烦，因此建议大家使用对象型的Integer/Long定义主键。 <BR><BR><SPAN style="COLOR: #ffa34f"><B>unsaved-value</B></SPAN>="none"和 <BR><SPAN style="COLOR: #ffa34f"><B>unsaved-value</B></SPAN>="any" <BR><BR>主主要用在主键属性不是通过Hibernate生成，而是程序自己setId()的时候。 <BR><BR>在这里多说一句，强烈建议使用Hibernate的id generator，或者你可以自己扩展Hibernate的id generator，特别注意不要使用有实际含义的字段当做主键来用！例如用户类User，很多人喜欢用用户登陆名称做为主键，这是一个很不好的习惯，当用户类和其他实体类有关联关系的时候，万一你需要修改用户登陆名称，一改就需要改好几张表中的数据。偶合性太高，而如果你使用无业务意义的id generator，那么修改用户名称，就只修改user表就行了。 <BR><BR>由这个问题引申出来，如果你严格按照这个原则来设计数据库，那么你基本上是用不到手工来setId()的，你用Hibernate的id generator就OK了。因此你也不需要了解当 <BR><BR><SPAN style="COLOR: #ffa34f"><B>unsaved-value</B></SPAN>="none"和 <BR><SPAN style="COLOR: #ffa34f"><B>unsaved-value</B></SPAN>="any" <BR><BR>究竟有什么含义了。如果你非要用assigned不可，那么继续解释一下： <BR><BR><SPAN style="COLOR: #ffa34f"><B>unsaved-value</B></SPAN>="none" 的时候，由于不论主键属性为任何值，都不可能为none，因此Hibernate总是对child对象发送update(child) <BR><BR><SPAN style="COLOR: #ffa34f"><B>unsaved-value</B></SPAN>="any" 的时候，由于不论主键属性为任何值，都肯定为any，因此Hibernate总是对child对象发送save(child) <BR><BR>大多数情况下，你可以避免使用assigned，只有当你使用复合主键的时候不得不手工setId()，这时候需要你自己考虑究竟怎么设置<SPAN style="COLOR: #ffa34f"><B>unsaved-value</B></SPAN>了，根据你自己的需要来定。 <BR><BR>BTW: Gavin King强烈不建议使用composite-id，强烈建议使用UserType。 <BR><BR>因此，如果你在系统设计的时候，遵循如下原则： <BR><BR><SPAN style="COLOR: red">1、使用Hibernate的id generator来生成无业务意义的主键，不使用有业务含义的字段做主键，不使用assigned。 <BR><BR>2、使用对象类型(String/Integer/Long/...)来做主键，而不使用基础类型(int/long/...)做主键 <BR><BR>3、不使用composite-id来处理复合主键的情况，而使用UserType来处理该种情况。</SPAN> <BR><BR>那么你永远用的是<SPAN style="COLOR: #ffa34f"><B>unsaved-value</B></SPAN>="null" ，不可能用到any/none/..了。</SPAN><BR><img src ="http://www.blogjava.net/killvin/aggbug/33297.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killvin/" target="_blank">killvin</a> 2006-03-02 20:45 <a href="http://www.blogjava.net/killvin/archive/2006/03/02/33297.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Update &amp; SavaOrUpdate [author : robbine resource : Javaeye] </title><link>http://www.blogjava.net/killvin/archive/2006/03/02/33296.html</link><dc:creator>killvin</dc:creator><author>killvin</author><pubDate>Thu, 02 Mar 2006 12:44:00 GMT</pubDate><guid>http://www.blogjava.net/killvin/archive/2006/03/02/33296.html</guid><description><![CDATA[<SPAN class=postbody>先来点概念： <BR><BR>在Hibernate中，最核心的概念就是对PO的状态管理。一个PO有三种状态： <BR><BR>1、未被持久化的VO <BR>此时就是一个内存对象VO，由JVM管理生命周期 <BR><BR>2、已被持久化的PO，并且在Session生命周期内 <BR>此时映射数据库数据，由数据库管理生命周期 <BR><BR>3、曾被持久化过，但现在和Session已经detached了，以VO的身份在运行 <BR>这种和Session已经detached的PO还能够进入另一个Session，继续进行PO状态管理，此时它就成为PO的第二种状态了。<SPAN style="COLOR: red">这种PO实际上是跨了Session进行了状态维护的。</SPAN> <BR><BR>在传统的JDO1.x中，PO只有前面两种状态，一个PO一旦脱离PM，就丧失了状态了，不再和数据库数据关联，成为一个纯粹的内存VO，它即使进入一个新的PM，也不能恢复它的状态了。 <BR><BR>Hibernate强的地方就在于，一个PO脱离Session之后，还能保持状态，再进入一个新的Session之后，就恢复状态管理的能力，但此时状态管理需要使用session.update或者session.<SPAN style="COLOR: #ffa34f"><B>saveOrUpdate</B></SPAN>，这就是Hibernate Reference中提到的“requires a slightly different programming model ” <BR><BR>现在正式进入本话题： <BR><BR><SPAN style="COLOR: red">简单的来说，update和<SPAN style="COLOR: #ffa34f"><B>saveOrUpdate</B></SPAN>是用来对跨Session的PO进行状态管理的。</SPAN> <BR><BR>假设你的PO不需要跨Session的话，那么就不需要用到，例如你打开一个Session，对PO进行操作，然后关闭，之后这个PO你也不会再用到了，那么就不需要用update。 <BR><BR>因此，我们来看看上例： <BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B>java代码:&nbsp;<IMG style="CURSOR: hand" onclick="copycode('code1331230956')" src="http://forum.javaeye.com/copy.gif" border=0></B></SPAN></TD></TR>
<TR>
<TD class=code>
<DIV style="FONT-FAMILY: 'Courier New', Courier, monospace"><BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">1</SPAN>&nbsp;Foo foo=sess.<SPAN style="COLOR: #000000">load</SPAN><SPAN style="COLOR: #000000">(</SPAN>Foo.<SPAN style="COLOR: #000000">class</SPAN>,id<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">2</SPAN>&nbsp;foo.<SPAN style="COLOR: #000000">setXXX</SPAN><SPAN style="COLOR: #000000">(</SPAN>xxx<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">3</SPAN>&nbsp;sess.<SPAN style="COLOR: #000000">flush</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">4</SPAN>&nbsp;sess.<SPAN style="COLOR: #000000">commit</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">)</SPAN>;</DIV><BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR>PO对象foo的操作都在一个Session生命周期内完成，因此不需要显式的进行sess.update(foo)这样的操作。Hibernate会自动监测到foo对象已经被修改过，因此就向数据库发送一个update的sql。当然如果你非要加上sess.update(foo)也不会错，只不过这样做没有任何必要。 <BR><BR>而跨Session的意思就是说这个PO对象在Session关闭之后，你还把它当做一个VO来用，后来你在Session外面又修改了它的属性，然后你又想打开一个Session，把VO的属性修改保存到数据库里面，那么你就需要用update了。 <BR><BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B>java代码:&nbsp;<IMG style="CURSOR: hand" onclick="copycode('code2024909580')" src="http://forum.javaeye.com/copy.gif" border=0></B></SPAN></TD></TR>
<TR>
<TD class=code>
<DIV style="FONT-FAMILY: 'Courier New', Courier, monospace"><BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">1&nbsp;</SPAN>&nbsp;<SPAN style="COLOR: #6666ff">// in the first session </SPAN><BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">2&nbsp;</SPAN>&nbsp;Cat cat = <SPAN style="COLOR: #000000">(</SPAN>Cat<SPAN style="COLOR: #000000">)</SPAN> firstSession.<SPAN style="COLOR: #000000">load</SPAN><SPAN style="COLOR: #000000">(</SPAN>Cat.<SPAN style="COLOR: #000000">class</SPAN>, catId<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">3&nbsp;</SPAN>&nbsp;Cat potentialMate = <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>new</SPAN> Cat<SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">4&nbsp;</SPAN>&nbsp;firstSession.<SPAN style="COLOR: #000000">save</SPAN><SPAN style="COLOR: #000000">(</SPAN>potentialMate<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">5&nbsp;</SPAN>&nbsp; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">6&nbsp;</SPAN>&nbsp;<SPAN style="COLOR: #6666ff">// in a higher tier of the application </SPAN><BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">7&nbsp;</SPAN>&nbsp;cat.<SPAN style="COLOR: #000000">setMate</SPAN><SPAN style="COLOR: #000000">(</SPAN>potentialMate<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">8&nbsp;</SPAN>&nbsp; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">9&nbsp;</SPAN>&nbsp;<SPAN style="COLOR: #6666ff">// later, in a new session </SPAN><BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">10</SPAN>&nbsp;secondSession.<SPAN style="COLOR: #000000">update</SPAN><SPAN style="COLOR: #000000">(</SPAN>cat<SPAN style="COLOR: #000000">)</SPAN>;&nbsp; <SPAN style="COLOR: #6666ff">// update cat </SPAN><BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">11</SPAN>&nbsp;secondSession.<SPAN style="COLOR: #000000">update</SPAN><SPAN style="COLOR: #000000">(</SPAN>mate<SPAN style="COLOR: #000000">)</SPAN>; <SPAN style="COLOR: #6666ff">// update mate</SPAN> <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">12</SPAN>&nbsp;</DIV><BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR>cat和mate对象是在第一个session中取得的，在第一个session关闭之后，他们就成了PO的第三种状态，和Session已经detached的PO，此时他们的状态信息仍然被保留下来了。当他们进入第二个session之后，立刻就可以进行状态的更新。但是由于对cat的修改操作：cat.setMate(potentialMate); 是在Session外面进行的，Hibernate不可能知道cat对象已经被改过了，第二个Session并不知道这种修改，因此一定要显式的调用secondSession.update(cat); 通知Hibernate，cat对象已经修改了，你必须发送update的sql了。 <BR><BR>所以update的作用就在于此，它只会被用于当一个PO对象跨Session进行状态同步的时候才需要写。而一个PO对象当它不需要跨Session进行状态管理的时候，是不需要写update的。 <BR><BR>再谈谈<SPAN style="COLOR: #ffa34f"><B>saveOrUpdate</B></SPAN>的用场： <BR><BR><SPAN style="COLOR: #ffa34f"><B>saveOrUpdate</B></SPAN>和update的区别就在于在跨Session的PO状态管理中，Hibernate对PO采取何种策略。 <BR><BR>例如当你写一个DAOImpl的时候，让cat对象增加一个mate，如下定义： <BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B>java代码:&nbsp;<IMG style="CURSOR: hand" onclick="copycode('code1259948931')" src="http://forum.javaeye.com/copy.gif" border=0></B></SPAN></TD></TR>
<TR>
<TD class=code>
<DIV style="FONT-FAMILY: 'Courier New', Courier, monospace"><BR><IMG onclick="showhide('code1165615075line0')" height=7 src="http://forum.javaeye.com/code.gif" weight="7"><SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">1</SPAN>&nbsp;<SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>public</SPAN> <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>void</SPAN> addMate<SPAN style="COLOR: #000000">(</SPAN>Cat cat, Mate mate<SPAN style="COLOR: #000000">)</SPAN> <SPAN style="COLOR: #000000">{</SPAN> 
<DIV id=code1165615075line0s style="DISPLAY: none">...}</DIV>
<DIV id=code1165615075line0>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">2</SPAN>&nbsp;&nbsp; &nbsp; Session session = ...; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">3</SPAN>&nbsp;&nbsp; &nbsp; Transacton tx = ...; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">4</SPAN>&nbsp;&nbsp; &nbsp; session.<SPAN style="COLOR: #000000">update</SPAN><SPAN style="COLOR: #000000">(</SPAN>cat<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">5</SPAN>&nbsp;&nbsp; &nbsp; cat.<SPAN style="COLOR: #000000">addMate</SPAN><SPAN style="COLOR: #000000">(</SPAN>mate<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">6</SPAN>&nbsp;&nbsp; &nbsp; tx.<SPAN style="COLOR: #000000">commit</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">7</SPAN>&nbsp;&nbsp; &nbsp; session.<SPAN style="COLOR: #000000">close</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">8</SPAN>&nbsp;<SPAN style="COLOR: #000000">}</SPAN>;</DIV><BR></DIV></TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR>显然你是需要把Hibernate的操作封装在DAO里面的，让业务层的程序员和Web层的程序员不需要了解Hibernate，直接对DAO进行调用。 <BR><BR>此时问题就来了：上面的代码运行正确有一个必要的前提，那就是方法调用参数cat对象必须是一个已经被持久化过的PO，也就是来说，它应该首先从数据库查询出来，然后才能这样用。但是业务层的程序员显然不知道这种内部的玄妙，如果他的业务是现在增加一个cat，然后再增加它的mate，他显然会这样调用，new一个cat对象出来，然后就addMate： <BR><BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B>java代码:&nbsp;<IMG style="CURSOR: hand" onclick="copycode('code1502014122')" src="http://forum.javaeye.com/copy.gif" border=0></B></SPAN></TD></TR>
<TR>
<TD class=code>
<DIV style="FONT-FAMILY: 'Courier New', Courier, monospace"><BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">1</SPAN>&nbsp;Cat cat = <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>new</SPAN> Cat<SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">2</SPAN>&nbsp;cat.<SPAN style="COLOR: #000000">setXXX</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">3</SPAN>&nbsp;daoimpl.<SPAN style="COLOR: #000000">addMate</SPAN><SPAN style="COLOR: #000000">(</SPAN>cat,mate<SPAN style="COLOR: #000000">)</SPAN>;</DIV><BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR>但是请注意看，这个cat对象只是一个VO，它没有被持久化过，它还不是PO，它没有资格调用addMate方法，因此调用addMate方法不会真正往数据库里面发送update的sql，这个cat对象必须先被save到数据库，在真正成为一个PO之后，才具备addMate的资格。 <BR><BR>你必须这样来操作： <BR><BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B>java代码:&nbsp;<IMG style="CURSOR: hand" onclick="copycode('code1799803324')" src="http://forum.javaeye.com/copy.gif" border=0></B></SPAN></TD></TR>
<TR>
<TD class=code>
<DIV style="FONT-FAMILY: 'Courier New', Courier, monospace"><BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">1</SPAN>&nbsp;Cat cat = <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>new</SPAN> Cat<SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">2</SPAN>&nbsp;cat.<SPAN style="COLOR: #000000">setXXX</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">3</SPAN>&nbsp;daoimpl.<SPAN style="COLOR: #000000">addCat</SPAN><SPAN style="COLOR: #000000">(</SPAN>cat<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">4</SPAN>&nbsp;daoimpl.<SPAN style="COLOR: #000000">addMate</SPAN><SPAN style="COLOR: #000000">(</SPAN>cat, mate<SPAN style="COLOR: #000000">)</SPAN>;</DIV><BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR>先持久化cat，然后才能对cat进行其他的持久化操作。因此要求业务层的程序员必须清楚cat对象处于何种状态，到底是第一种，还是第三种。如果是第一种，就要先save，再addMate；如果是第三种，就直接addMate。 <BR><BR>但是最致命的是，如果整个软件分层很多，业务层的程序员他拿到这个cat对象也可能是上层Web应用层传递过来的cat，他自己也不知道这个cat究竟是VO，没有被持久化过，还是已经被持久化过，那么他根本就没有办法写程序了。 <BR><BR>所以这样的DAOImpl显然是有问题的，它会对业务层的程序员造成很多编程上的陷阱，业务层的程序员必须深刻的了解他调用的每个DAO对PO对象进行了何种状态管理，必须深刻的了解他的PO对象在任何时候处于什么确切的状态，才能保证编程的正确性，显然这是做不到的，但是有了<SPAN style="COLOR: #ffa34f"><B>saveOrUpdate</B></SPAN>，这些问题就迎刃而解了。 <BR><BR>现在你需要修改addMate方法： <BR><BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B>java代码:&nbsp;<IMG style="CURSOR: hand" onclick="copycode('code254924526')" src="http://forum.javaeye.com/copy.gif" border=0></B></SPAN></TD></TR>
<TR>
<TD class=code>
<DIV style="FONT-FAMILY: 'Courier New', Courier, monospace"><BR><IMG onclick="showhide('code1322561958line0')" height=7 src="http://forum.javaeye.com/code.gif" weight="7"><SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">1</SPAN>&nbsp;<SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>public</SPAN> <SPAN style="FONT-WEIGHT: bold; COLOR: #990066" ?>void</SPAN> addMate<SPAN style="COLOR: #000000">(</SPAN>Cat cat, Mate mate<SPAN style="COLOR: #000000">)</SPAN> <SPAN style="COLOR: #000000">{</SPAN> 
<DIV id=code1322561958line0s style="DISPLAY: none">...}</DIV>
<DIV id=code1322561958line0>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">2</SPAN>&nbsp;&nbsp; &nbsp; Session session = ...; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">3</SPAN>&nbsp;&nbsp; &nbsp; Transacton tx = ...; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">4</SPAN>&nbsp;&nbsp; &nbsp; session.<SPAN style="COLOR: #000000"><SPAN style="COLOR: #ffa34f"><B>saveOrUpdate</B></SPAN></SPAN><SPAN style="COLOR: #000000">(</SPAN>cat<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">5</SPAN>&nbsp;&nbsp; &nbsp; cat.<SPAN style="COLOR: #000000">addMate</SPAN><SPAN style="COLOR: #000000">(</SPAN>mate<SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">6</SPAN>&nbsp;&nbsp; &nbsp; tx.<SPAN style="COLOR: #000000">commit</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">7</SPAN>&nbsp;&nbsp; &nbsp; session.<SPAN style="COLOR: #000000">close</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">)</SPAN>; <BR>&nbsp;<SPAN style="FONT-WEIGHT: normal; COLOR: black; FONT-STYLE: normal">8</SPAN>&nbsp;<SPAN style="COLOR: #000000">}</SPAN>;</DIV><BR></DIV></TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR>如上，如果业务层的程序员传进来的是一个已经持久化过的PO对象，那么Hibernate会更新cat对象(假设业务层的程序员在Session外面修改过cat的属性)，如果传进来的是一个新new出来的对象，那么向数据库save这个PO对象。 <BR><BR>BTW: Hibernate此时究竟采取更新cat对象，还是save cat对象，取决于unsave-value的设定。 <BR><BR>这样，业务层的程序员就不必再操心PO的状态问题了，对于他们来说，不管cat是new出来的对象，只是一个VO也好；还是从数据库查询出来的的PO对象也好，全部都是直接addMate就OK了： <BR><BR></SPAN><img src ="http://www.blogjava.net/killvin/aggbug/33296.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killvin/" target="_blank">killvin</a> 2006-03-02 20:44 <a href="http://www.blogjava.net/killvin/archive/2006/03/02/33296.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>StrutsFileUpload </title><link>http://www.blogjava.net/killvin/archive/2006/03/02/33295.html</link><dc:creator>killvin</dc:creator><author>killvin</author><pubDate>Thu, 02 Mar 2006 12:43:00 GMT</pubDate><guid>http://www.blogjava.net/killvin/archive/2006/03/02/33295.html</guid><description><![CDATA[今天同事问我Struts如何解决文件上传的问题，一时间没有想起来，就到google查了一下，果然在Struts Wiki上就有非常详细的解释，抄录如下，详细的请看（http://wiki.apache.org/struts/StrutsFileUpload）<BR><BR><BR><BR>StrutsFileUpload<BR>File Upload - Simple Example<BR>HTML<BR>This isn't specific to Struts, but gives a simple example of the HTML required to upload a single file. <BR><BR>Two things are needed in the html page. Firstly, the form needs to specify an enctype of multipart/form-data and secondly an form control of type file. <BR><BR>JSP<BR>The above HTML can be generated using the Struts tags in the following way <BR><BR>&lt;html:form action="/uploadMyFile.do" enctype="multipart/form-data"&gt;<BR><BR>Select File: &lt;html:file property="myFile"&gt; <BR><BR>&lt;html:submit value="Upload File"/&gt;<BR><BR>&lt;/html:form&gt;<BR><BR>ActionForm<BR>The ActionForm needs a property of type FormFile. <BR><BR>Regular ActionForms<BR>import org.apache.struts.upload.FormFile;<BR><BR>public class MyActionForm extends ActionForm {<BR><BR>private FormFile myFile;<BR><BR>public void setMyFile(FormFile myFile) {<BR>this.myFile = myfile;<BR>}<BR><BR>public FormFile getMyFile() {<BR>return myFile;<BR>}<BR>}<BR><BR>Dyna ActionForms<BR>In the struts-config.xml <BR><BR>&lt;form-bean name="myForm" type="org.apache.struts.action.DynaActionForm"&gt;<BR>&lt;form-property name="myFile" type="org.apache.struts.upload.FormFile"/&gt;<BR>&lt;/form-bean&gt;<BR><BR>Whats Needed in the Action<BR>Nothing special really, just retrieve the FormFile from the ActionForm, as you would any other property, and process it as you like. You can get the file name, size and file contents from the FormFile. <BR><BR>public ActionForward execute(ActionMapping mapping,<BR>ActionForm form,<BR>HttpServletRequest request,<BR>HttpServletResponse response) throws Exception {<BR><BR>MyActionForm myForm = (MyActionForm)form;<BR><BR>// Process the FormFile<BR>FormFile myFile = myForm.getMyFile();<BR>String contentType = myFile.getContentType();<BR>String fileName = myFile.getFileName();<BR>int fileSize = myFile.getFileSize();<BR>byte[] fileData = myFile.getFileData();<BR>... <BR>}<BR><BR>File Upload Configuration<BR>The following parameters can be set in the &lt;controller&gt; element of the struts-config.xml to configure file upload: <BR><BR>bufferSize - The size (in bytes) of the input buffer used when processing file uploads. Default is 4096. <BR><BR>maxFileSize - The maximum size (in bytes) of a file to be accepted as a file upload. Can be expressed as a number followed by a "K", "M", or "G", which are interpreted to mean kilobytes, megabytes, or gigabytes, respectively. Default is 250M. <BR><BR>multipartClass - The fully qualified Java class name of the multipart request handler class to be used with this module. Defaults is org.apache.struts.upload.CommonsMultipartRequestHandler. <BR><BR>tempDir - Temporary working directory to use when processing file uploads. <BR><BR>Above taken from the Configuration section in the User Guide. <BR><BR>Plugging in an Alternative File Upload Mechanism<BR>By default Struts uses Commons File Upload. <BR><BR>Alternative implementations can be plugged as long as they implement the org.apache.struts.upload.MultipartRequestHandler interface and Struts configured to use that implementation by specifying it in the multipartClass parameter in the &lt;controller&gt; element of the struts-config.xml <BR><BR>Fair Warning: The MultipartRequestHandler interface is almost certain to change in a Struts 1.3 or higher release. <BR><img src ="http://www.blogjava.net/killvin/aggbug/33295.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killvin/" target="_blank">killvin</a> 2006-03-02 20:43 <a href="http://www.blogjava.net/killvin/archive/2006/03/02/33295.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>