Skip to content

Categories:

SSH开发心得

前段时间开发一个J2EE的Web项目,使用SSH(Struts+Spring+hibernate)框架。开发过程中遇到一个相当郁闷的问题,困扰了我好几天。这里我跟大家分享一下。

问题是这样的:我用Spring的声明式事务管理来管理事务,当出现异常时能回滚事务。于是我做了一个测试,在一个方法里,我先添加了一条数据,然后再删除一条数据,在删除数据的时候我让它强行抛出异常,这时刚添加的那条数据应该回滚掉,可是我查看了一下数据库,发现数据已经插入,根本没有回滚,这是怎么回事呢?我的第一个反应就是Spring配置文件可能出问题了。

以下是我的Spring的事务管理的配置方式:

	<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
	<propertyname="sessionFactory"ref="sessionFactory"/>
	</bean>
 
	<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
	<!--事务拦截器bean需要依赖注入一个事务管理器-->
	<property name="transactionManager"ref="transactionManager"/>
	<property name="transactionAttributes">
	<!--下面定义事务传播属性-->
	<props>
	<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
	<prop key="*">PROPAGATION_REQUIRED,-Exception</prop>
	</props>
	</property>
	</bean>
		<!--定义BeanNameAutoProxyCreator-->
		<bean
		class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
			<!--指定对满足哪些beanname的bean自动生成业务代理-->
			<property name="beanNames">
				<!--下面是所有需要自动创建事务代理的bean-->
				<list>
					<value>*Bo</value>
				</list>
				<!--此处可增加其他需要自动创建事务代理的bean-->
			</property>
			<!--下面定义BeanNameAutoProxyCreator所需的事务拦截器-->
			<property name="interceptorNames">
				<list>
					<!--此处可增加其他新的Interceptor-->
					<value>transactionInterceptor</value>
				</list>
			</property>
		</bean>

带着这个问题,我到网络上查了很多关于Spring配置事务的资料,也做了很多次修改,但问题仍然存在。我开始怀疑难道是Spring配置方式根本就是正确的。那这样的话问题到底出在哪里呢?为什么抛出异常后事务没有回滚呢?

快接近崩溃边缘的我还是硬着头皮继续在网络上求教,突然在一篇文章里看到这样一句话“Mysql表的MyISAM类型不支持事务处理,InnoDB类型提供事务支持”。我马上查了一下数据库的表类型,发现我的表就是MyISAM类型的,太兴奋了,难道就这样搞定了?于是我马上将表类型改成InnoDB,重启测试,问题解决。兴奋之余总结一下:原因就是我一直以为是Spring配置文件出问题了,却一直忽略了其他的情况。最后,将Mysql这两种表类型的详细对比跟大家分享一下。

InnoDB和MyISAM是MySQL最常用的表类型,各有各的优缺点,选用哪个视具体应用场景而定。

MyIASM:基于传统的IASM类型,ISAM是Indexed Sequential Access Method(有索引的顺序访问方法)的缩写,IASM是存储记录和文件的标准方法。与其他存储引擎比较,MyISAM具有检查和修复表的大多数工具。MyISAM表可以被压缩,而且它们支持全文搜索。它们不是事务安全的,而且也不支持外键。如果事物回滚将造成不完全回滚,不具有原子性。如果执行大量的SELECT,MyISAM是更好的选择。MyISAM对IASM有如下扩展:

二进制层次的可移植性。

NULL列索引。

对变长行比ISAM表有更少的碎片。

支持大文件。

更好的索引压缩。

更好的键码统计分布。

更好和更快的auto_increment处理。

InnoDB:它是事务安全的,与BDB类型具有相同的特性。它们支持外键。InnoDB表速度很快,具有比BDB还丰富的特性,因此如果需要一个事务安全的存储引擎,建议使用它。如果你的数据执行大量的INSERT或UPDATE,出于性能与事务方面的考虑,应该使用InnoDB类型的表。

以下是InnoDB与MyISAM细节和具体实现的差别:

InnoDB有它自己的缓冲池,能缓冲数据和索引,InnoDB把数据和索引存放在表空间里面,可能包含好几个文件,在MyISAM中,表被存放在单独的文件中,InnoDB表的大小只受限于操作系统文件的大小,一般为2GB。InnoDB不支持FULLTEXT类型的索引。

InnoDB支持行锁,提供和Oracle一样的一致性的不加锁读取,能增加并发读的用户数量并提高性能,不会增加锁的数量。另外,InnoDB表的行锁也不是绝对的,如果在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表,例如update table set num=1 where name like“%aaa%”。

InnoDB中不保存表的具体行数,也就是说,执行selectcount(*)fromtable时,InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。要注意的是,当count(*)语句包含where条件时,两种表的操作是一样的。

对于AUTO_INCREMENT类型的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中,可以和其他字段一起建立联合索引。

DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的删除。

LOAD TABLE FROM MASTER操作对InnoDB是不起作用的,解决方法是首先把InnoDB表改成MyISAM表,导入数据后再改成InnoDB表,但是对于使用的额外的InnoDB特性(例如外键)的表不适用。

任何一种表类型都不是万能的,只能针对具体的应用场景来选择合适的表类型,这样才能最大限度地发挥MySQL的性能。

Posted in java.

Tagged with .


J2EE开发三件宝: Domain Model(域建模)、patterns(模式)和framework(框架)。

J2EE可以说指Java在数据库信息系统上实现,数据库信息系统从早期的dBase、到Delphi/VB等C/S结构,发展到B/S(Browser浏览器/Server服务器)结构,而J2EE主要是指B/S结构的实现。

J2EE是一个虚的大的概念,J2EE标准主要有三种子技术标准:WEB技术、EJB技术和JMS,谈到J2EE应该说最终要落实到这三个子概念上。

这三种技术的每个技术在应用时都涉及两个部分:容器部分和应用部分,Web容器也是指Jsp/Servlet容器,你如果要开发一个Web应用,无论是编译或运行,都必须要有Jsp/Servlet库或API支持(除了JDK/J2SE以外)。

Web技术中除了Jsp/Servlet技术外,还需要JavaBeans或Java Class实现一些功能或者包装携带数据,所以Web技术最初裸体简称为Jsp/Servlet+JavaBeans系统。

衡量J2EE应用系统设计开发水平高低的标准就是:解耦性;你的应用系统各个功能是否能够彻底脱离?是否不相互依赖,也只有这样,才能体现可维护性、可拓展性的软件设计目标。

了达到这个目的,诞生各种框架概念,J2EE框架标准将一个系统划分为WEB和EJB主要部分,当然我们有时不是以这个具体技术区分,而是从设计上抽象为表现层、服务层和持久层,这三个层次从一个高度将J2EE分离开来,实现解耦目的。

因此,我们实际编程中,也要将自己的功能向这三个层次上靠,做到大方向清楚,泾渭分明,但是没有技术上约束限制要做到这点是很不容易的,因此我们还是必须借助J2EE具体技术来实现

使用服务层框架可以将JavaBeans从Jsp/Servlet中分离出来,而使用表现层框架则可以将Jsp中剩余的JavaBeans完全分离,这部分JavaBeans主要负责显示相关,一般是通过标签库(taglib)实现,不同框架有不同自己的标签库,Struts是应用比较广泛的一种表现层框架。

这样,表现层和服务层的分离是通过两种框架达到目的,剩余的就是持久层框架了,通过持久层的框架将数据库存储从服务层中分离出来是其目的,持久层框架有两种方向:直接自己编写JDBC等SQL语句(如iBatis);使用O/R Mapping技术实现的Hibernate和JDO技术;当然还有EJB中的实体Bean技术。

持久层框架目前呈现百花齐放,各有优缺点的现状,所以正如表现层框架一样,目前没有一个框架被指定为标准框架。

以本公司来说,完全是基于以上几点的考虑采用了如下架构:

表现层:Struts

持久层:Hibernate

服务层:Business Object

Struts完全体现了MVC思想,将一个应用分成三个基本部分:Model(模型)、View(视图)和Controller(控制器),这三个部分以最少的耦合协同工作,从而提高应用的可扩展性及可维护性。在数据库端使用了Hibernate,它使得与关系数据库打交道变得十分轻松,就像您的数据库中包含每天使用的普通Java对象一样,同时不必考虑如何把它们从神秘的数据库表中取出(或放回到数据库表中)。它解放了您,使您可以专注于应用程序的对象和功能,而不必担心如何保存它们或稍后如何找到它们。

最后,你的J2EE应用系统如果采取上面提到的表现层、服务层和持久层的框架实现,基本你也可以在无需深刻掌握设计模式的情况下开发出一个高质量的应用系统了。

还要注意的是: 开发出一个高质量的J2EE系统还需要正确的业务需求理解,那么域建模提供了一种比较切实可行的正确理解业务需求的方法,相关详细知识可从UML角度结合理解。

当然,如果你想设计自己的行业框架,那么第一步从设计模式开始吧,因为设计模式提供你一个实现JavaBeans或类之间解耦参考实现方法,当你学会了系统基本单元JavaBean或类之间解耦时,那么系统模块之间的解耦你就可能掌握,进而你就可以实现行业框架的提炼了,这又是另外一个发展方向了。

以上理念可以总结为一句话:

J2EE开发三件宝: Domain Model(域建模)、patterns(模式)和framework(框架)。

Posted in java.


win下比较靠谱的rails源

安装rails时候,install默认地址是rubyforge.org,速度会让你郁闷到飞起,大家用下面这个命令吧:

gem install rails –include-dependencies –source http://gems.rubyonrails.org

Posted in ruby.

Tagged with .


soap:php使用nusoap调用.NET接口的方法

//soap为你的nusoap存放路径,nusoap.php为主要接口文件
include('soap/nusoap.php');
 
//目标地址
$url = 'http://www.oseschool.com/ValidateAccount.aspx'
 
//发送请求的参数设定
$parms = array ('userName' => 'test', 'password' => '123456' );
 
//实例化一个soap请求,直接调用soap方法
$client = new SoapClient ( $url, array('parameters' =>$parms));
 
//返回结果
$result = $result->ValidateAccountResult;

这边的ValidateAccountResult是.net接口中定义好的返回结果。

也可以使用$result = $client->__call(”ValidateAccountResult”,array(’parameters’ =>$parms));来接收。

nusoap是一个PHP扩展类,无须安装,他可以让我们很简单的创建和使用soap webservice。

nusoap是开源的,目前最高版本0.7.3,支持SOAP 1.1, WSDL 1.1 和HTTP 1.0/1.1.,项目在sourceforge上,下载地址:按这里

Posted in php.

Tagged with , .


java获取文件夹下所有子文件夹

import java.io.File;
public class travelAllFile {
	public static void main(String[] args) {
		String path ="E:/a";
		File f = new File(path);
		if(f.isDirectory()){
			new travelAllFile().getFileName(f);
		}
 
	}
	//递归查找函数,参数为file对象
	public void getFileName(File f){
		//File 数组
		File[] files = f.listFiles();
 
		for (int i = 0; i &lt; files.length; i++) {
			//递归出子目录
			if(files[i].isDirectory()){
				System.out.println("子目录是:"+files[i].getName());
				getFileName(files[i]);
			//递归出子文件
			}else{
				System.out.println(files[i].getName());
			}
 
		}
	}
}

isDirectory()方法可以判断当前是否为文件夹

Posted in java.

Tagged with .


Hello world!

这里是信永国际技术人员的部落格,关于信永国际你可以按此链接查看,同时,我们也是信永国际软件工程师培训学校的IT教师,总的说来,我们是一群死程序员.

Posted in undefind.