中软JAVA面试

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

中软JAVA面试
方法2 server.transfer 速度快,只需要一次postback ,然而……他必须是在同一个站点下,因为它是server的一个方法。

另外,他能跃过登录爱护。

你能够写个小程序试试:设计一个由页面一到页面二的跳转,但要进入到页面二需要登录,forms认证,但如果跳转语句使用tr ansfer的话,那就可不能弹出登录页面了。

那个方法的重定向要求是发生在服务器端,因此扫瞄器的url地址仍旧保留的是原页面的地址!
方法3 sever.execute 那个方法要紧是用在页面设计上面,而且他必须是跳转同一站点下的页面。

那个方法是需要将一个页面的输出结果插入到另一个aspx页面的时候使用,大部分是在表格中,将某一个页面类似于嵌套的方式存在于另一页面。

(此方法成效类似于JSP中的<jsp:include>标签成效)
总结:
当需要把用户跳转到另一台服务器上的页面的时候使用redirect
当需要把用户跳转到非aspx页面时候,如html 使用redirect
需要把查询字符串作为url一部分的时候保留传给服务器的时候,因为其他2种方法不能做到2次postback,把数据先带回服务器使用redirect 需要aspx页面间的转换(不涉及登录)使用transfer
当需要把aspx页面的输出结果插入到另一个aspx页面的时候使用exe cute方法。

所以,不记得了还有一个超链接!所以那个就不需要讲太多了。

他是在当需要用户来决定什么时候跳转页面,就使用超链接。

顺便提一下,如何使用redirect方法在查询字符串中使用汉字,因为经
常的情形是显现乱码,缘故是url不支持汉字。

那个时候需要转换:string message =server.urlencode("欢迎来到赛跑专栏");
先转换,再使用查询字符串
response.redirect("webform2.aspx?msg="+message);
各位javaeye的朋友们,我那个地点有个咨询题要求你们的帮忙,感谢。

我期望能够配置spring治理hibernate事务,当一个service调用多dao的时候,全部save成功才commit,能够如何实现?
这是配置文件
Java代码
<bean id="transactionManager"class="org.springframework.orm.hiber nate3.HibernateTransactionManager"/>
<bean id="accountManagerTarget"class="com.vas.brd.service.impl.Ac countManagerImpl">
<property name="userOrderDAO"><ref local="userOrderDAO"/> </property>
</bean>
<bean id="accountManager"class="org.springframework.transaction.in terceptor.TransactionProxyFactoryBean">
<property name="transactionManager"><ref local="transactionMa nager"/></property>
<property name="target"><ref local="accountManagerTarget"/></ property>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</pro p>
<prop key="remove*">PROPAGATION_REQUIRED</pr op>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
/************************************************************ *******************/
<bean id="transactionManager" class="org.springframework.orm.hibernat e3.HibernateTransactionManager" /><bean id="accountManagerTarget" class ="com.vas.brd.service.impl.AccountManagerImpl"> <property name="userOr derDAO"><ref local="userOrderDAO"/></property></bean><bean id="accou ntManager" class="org.springframework.transaction.interceptor.TransactionPro xyFactoryBean"> <property name="transactionManager"><ref local="transa ctionManager"/></property> <property name="target"><ref local="account ManagerTarget"/></property> <property name="transactionAttributes"> < props> <prop key="save*">PROPAGATION_REQUIRED</prop> <prop key="remove*">PROPAGATION_REQUIRED</prop> <prop key="*">P ROPAGATION_REQUIRED</prop> </props> </property></bean>/***** ****************************************************************
**********/
sevice就没写了
Java代码
public class AccountManagerImpl implements AccountManage
r{
public SyncResponseInfo saveKnSyncData(){
//1
dao.saveObject2(object1);
//2
dao.saveObject1(object2));
}
}
Spring io
第一想讲讲IoC(Inversion of Control,操纵倒转)。

这是spring的核心,贯穿始终。

所谓IoC,关于spring框架来讲,确实是由spring来负责操纵对象的生命周期和对象间的关系。

这是什么意思呢,举个简单的例子,我们是如何找女朋友的?常见的情形是,我们到处去看哪里有长得漂亮身材又好的mm,然后打听她们的爱好爱好、qq号、电话号、ip号、iq号………,
想方法认识她们,投其所好送其所要,然后嘿嘿……那个过程是复杂深奥的,我们必须自己设计和面对每个环节。

传统的程序开发也是如此,在一个对象中,如果要使用另外的对象,就必须得到它(自己new一个,或者从JNDI中查询一个),使用完之后还要将对象销毁(例如Connection等),对象始终会和其他的接口或类藕合起来。

IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。

这一点是通过DI(Dependency Injection,依靠注入)来实现的。

例如对象A需要操作数据库,往常我们总是要在A中自己编写代码来获得一个Connection对象,有了spring我们就只需要告诉spring,A中需要一个Connection,至于那个Connection如何构造,何时构造,A不需要明白。

在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,如此就完成了对各个对象之间关系的操纵。

A需要依靠Connection才能正常运行,而那个Connection是由spring注入到A中的,依靠注入的名字就这么来的。

那么DI是如何实现的呢?Java 1.3之后一个重要特点是反射(reflection),它承诺程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring确实是通过反射来实现注入的。

关于反射的有关资料请查阅java doc。

懂得了IoC和DI的概念后,一切都将变得简单明了,剩下的工作只是在spring的框架中堆积木而已。

*Object类的方法:
*clone()
*equals()
*finalize()
*hashCode()
*toString()
*
*1、equals()方法:
*^equals方法强调比较的值的是否相等
*==强调对象的地址是否相同
*^s1和s2的值都储存在对内存中
*s3和s4的值都储存在占内存的字符串缓冲池中,缓存池的分配原则是按值是否相同来分配。

*^如果值相同则分在一起,指向他们的引用的has hCode()值也相同。

如果不同,则不分在一起,也就不==了。

*因此s3和s4是相同的两个引用,而s5和他们俩内存地址不同,hashCode值所以也不同了
*
*2、finalize()方法:
*由于在Object()类的以下所有子类中的对象差不多上在java的垃圾回收前自动调用此Object类(父类)的此finalize方法。

*因此能够重写如此运行的过程能够看的更清晰。

*
*3、hashCode()方法:
*^hashCode()方法的返回值调用它的对象的十进
制哈希码
*(不同的对象必有不同的hashCode 返回值,然而如果两个引用的值相同则hashCode返回值相同,
*因为引用不是对象,不是new出来的。

)
*^总结:两个对象或者引用的hashCode()是否相同,确实是看这些对象或引用的地址是否相同,
*hashCode()方法只看地址。

*^Integer类的静态方法toHexString方法作用是将十进制整型数转化成十六进制数
*
*4、toString()方法:
*^toString方法功能是以字符串形式返回当前对象的有关信息。

*^其返回值是调用它的对象的类名加十六进制哈希码。

*
*/
java中的对象名例如String s
s确实是对象名
它的值是个地址类似C++的指针
如果你用==去判定确实是判定它们的地址是不是一样
用equlas判定是判定对象的内容是否一样
String s1="abc";
String s2=new String(s1);
s1.equals(s2) 是true
s1==s2 是false
因为它们对象的内容是一样的可不是同一个对象
== 就表示判定它们是不是同一个对象
你有一本语文书我有一本语文书尽管内容一样,可我的书不是你的书
这是两本书
关键字: lazy
延迟加载:
延迟加载机制是为了幸免一些无谓的性能开销而提出来的,所谓延迟加载确实是当在真正需要数据的时候,才真正执行数据加载操作。

在H ibernate中提供了对实体对象的延迟加载以及对集合的延迟加载,另外在H ibernate3中还提供了对属性的延迟加载。

下面我们就分别介绍这些种类的延迟加载的细节。

A、实体对象的延迟加载:
如果想对实体对象使用延迟加载,必须要在实体的映射配置文件中进行相应的配置,如下所示:
<hibernate-mapping>
<class name=”er”table=”user”lazy=”true”>……
</class>
</hibernate-mapping>
通过将class的lazy属性设置为true,来开启实体的延迟加载特性。

如果我们运行下面的代码:
User user=(User)session.load(User.class,”1”);(1)
System.out.println(user.getName());(2)
当运行到(1)处时,Hibernate并没有发起对数据的查询,如果我们现在通过一些调试工具(例如JBuilder2005的Debug工具),观看现在user对象的
内存快照,我们会惊奇的发觉,现在返回的可能是User$EnhancerByCGLI B$$bede8986类型的对象,而且其属性为null,这是如何回事?还记得前面我曾讲过session.load()方法,会返回实体对象的代理类对象,那个地点所返回的对象类型确实是User对象的代理类对象。

在Hibernate中通过使用CGLI B,来实现动态构造一个目标对象的代理类对象,同时在代理类对象中包含目标对象的所有属性和方法,而且所有属性均被赋值为null。

通过调试器显示的内存快照,我们能够看出现在真正的User对象,是包含在代理对象的CGLIB$CALBACK_0.target属性中,当代码运行到(2)处时,现在调用u ser.getName()方法,这时通过CGLIB给予的回调机制,实际上调用CGLIB $CALBACK_0.getName()方法,当调用该方法时,Hibernate会第一检查CG LIB$CALBACK_0.target属性是否为null,如果不为空,则调用目标对象的getName方法,如果为空,则会发起数据库查询,生成类似如此的SQL语句:select * from user where id=’1’;来查询数据,并构造目标对象,同时将它赋值到CGLIB$CALBACK_0.target属性中。

如此,通过一个中间代理对象,Hibernate实现了实体的延迟加载,只有当用户真正发起获得实体对象属性的动作时,才真正会发起数据库查询操作。

因此实体的延迟加载是用通过中间代理类完成的,因此只有sessi on.load()方法才会利用实体延迟加载,因为只有session.load()方法才会返回实体类的代理类对象。

B、集合类型的延迟加载:
在Hibernate的延迟加载机制中,针对集合类型的应用,意义是最为重大的,因为这有可能使性能得到大幅度的提升,为此Hibernate进行了大量的努力,其中包括对JDK Collection的独立实现,我们在一对多关联中,定义的用来容纳关联对象的Set集合,并不是java.util.Set类型或其子类型,而是net.sf.hibernate.collection.Set类型,通过使用自定义集合类的实现,Hi bernate实现了集合类型的延迟加载。

为了对集合类型使用延迟加载,我们必须如下配置我们的实体类的关于关联的部分:
<hibernate-mapping>
<class name=”er”table=”user”>
…..
<set name=”addresses”table=”address”lazy=”true”inverse=”t rue”>
<key column=”user_id”/>
<one-to-many class=”com.neusoft.entity.Arrderss”/>
</set>
</class>
</hibernate-mapping>
通过将<set>元素的lazy属性设置为true来开启集合类型的延迟加载特性。

我们看下面的代码:
User user=(User)session.load(User.class,”1”);
Collection addset=user.getAddresses();(1)
Iterator it=addset.iterator();(2)
while(it.hasNext()){
Address address=(Address)it.next();
System.out.println(address.getAddress());
}
当程序执行到(1)处时,这时并可不能发起对关联数据的查询来加载关联数据,只有运行到(2)处时,真正的数据读取操作才会开始,这时Hiberna te会按照缓存中符合条件的数据索引,来查找符合条件的实体对象。

那个地点我们引入了一个全新的概念——数据索引,下面我们第一将接一下什么是数据索引。

在Hibernate中对集合类型进行缓存时,是分两部分进行缓存的,第一缓存集合中所有实体的id列表,然后缓存实体对象,这些实体对象的id列表,确实是所谓的数据索引。

当查找数据索引时,如果没有找到对应的数据索引,这时就会一条select SQL的执行,获得符合条件的数据,并构造实体对象集合和数据索引,然后返回实体对象的集合,同时将实体对象和数据索引纳入Hibernate的缓存之中。

另一方面,如果找到对应的数据索引,则从数据索引中取出id列表,然后按照id在缓存中查找对应的实体,如果找到就从缓存中返回,如果没有找到,在发起select S
QL查询。

在那个地点我们看出了另外一个咨询题,那个咨询题可能会对性能产生阻碍,这确实是集合类型的缓存策略。

如果我们如下配置集合类型:<hibernate-mapping>
<class name=”er”table=”user”>…..
<set name=”addresses”table=”address”lazy=”true”inverse=”t rue”>
<cache usage=”read-only”/>
<key column=”user_id”/>
<one-to-many class=”com.neusoft.entity.Arrderss”/>
</set>
</class>
</hibernate-mapping>
那个地点我们应用了<cache usage=”read-only”/>配置,如果采纳这种策略来配置集合类型,Hibernate将只会对数据索引进行缓存,而可不能对集合中的实体对象进行缓存。

如上配置我们运行下面的代码:User user=(User)session.load(User.class,”1”);
Collection addset=user.getAddresses();
Iterator it=addset.iterator();
while(it.hasNext()){
Address address=(Address)it.next();
System.out.println(address.getAddress());
}
System.out.println(“Second query……”);
User user2=(User)session.load(User.class,”1”);
Collection it2=user2.getAddresses();
while(it2.hasNext()){
Address address2=(Address)it2.next();
System.out.println(address2.getAddress());
}
运行这段代码,会得到类似下面的输出:
Select * from user where id=’1’;
Select * from address where user_id=’1’;
Tianjin
Dalian
Second query……
Select * from address where id=’1’;
Select * from address where id=’2’;
Tianjin
Dalian
我们看到,当第二次执行查询时,执行了两条对address表的查询操作,什么原因会如此?这是因为当第一次加载实体后,按照集合类型缓存策略的配置,只对集合数据索引进行了缓存,而并没有对集合中的实体对象进行缓存,因此在第二次再次加载实体时,Hibernate找到了对应实体的数据索引,然而按照数据索引,却无法在缓存中找到对应的实体,因此Hiberna te按照找到的数据索引发起了两条select SQL的查询操作,那个地点造成了对性能的白费,如何样才能幸免这种情形呢?我们必须对集合类型中的实体也指定缓存策略,因此我们要如下对集合类型进行配置:<hibernate-mapping>
<class name=”er”table=”user”>…..
<set name=”addresses”table=”address”lazy=”true”inverse=”t rue”>
<cache usage=”read-write”/>
<key column=”user_id”/>
<one-to-many class=”com.neusoft.entity.Arrderss”/>
</set>
</class>
现在Hibernate会对集合类型中的实体也进行缓存,如果按照那个配置再次运行上面的代码,将会得到类似如下的输出:
Select * from user where id=’1’;
Select * from address where user_id=’1’;
Tianjin
Dalian
Second query……
Tianjin
Dalian
这时将可不能再有按照数据索引进行查询的SQL语句,因为现在能够直截了当从缓存中获得集合类型中存放的实体对象。

C、属性延迟加载:
在Hibernate3中,引入了一种新的特性——属性的延迟加载,那个机制又为猎取高性能查询提供了有力的工具。

在前面我们讲大数据对象读取时,在User对象中有一个resume字段,该字段是一个java.sql.Clob类型,包含了用户的简历信息,当我们加载该对象时,我们不得不每一次都要加载那个字段,而不论我们是否确实需要它,而且这种大数据对象的读取本身会带来专门大的性能开销。

在Hibernate2中,我们只有通过我们前面讲过的面性能的粒度细分,来分解User类,来解决那个咨询题(请参照那一节的论述),然而在Hibernate3中,我们能够通过属性延迟加载机制,来使我们获得只有当我们真正需要操作那个字段时,才去读取那个字段数据的能力,为此我们必须如下配置我们的实体类:
<hibernate-mapping>
<class name=”er”table=”user”>
……
<property name=”resume”type=”java.sql.Clob”column=”resume”lazy=”true”/>
</class>
通过对<property>元素的lazy属性设置true来开启属性的延迟加载,在Hibernate3中为了实现属性的延迟加载,使用了类增强器来对实体类的Cla ss文件进行强化处理,通过增强器的增强,将CGLIB的回调机制逻辑,加入实体类,那个地点我们能够看出属性的延迟加载,依旧通过CGLIB来实现的。

CGLIB是Apache的一个开源工程,那个类库能够操纵java类的字节码,按照字节码来动态构造符合要求的类对象。

按照上面的配置我们运行下面的代码:
String sql=”from User user where =’zx’”;
Query query=session.createQuery(sql);(1)
List list=query.list();
for(int i=0;i<list.size();i++){
User user=(User)list.get(i);
System.out.println(user.getName());
System.out.println(user.getResume());(2)
}
当执行到(1)处时,会生成类似如下的SQL语句:
Select id,age,name from user where name=’zx’;
这时Hibernate会检索User实体中所有非延迟加载属性对应的字段数据,当执行到(2)处时,会生成类似如下的SQL语句:
Select resume from user where id=’1’;
这时会发起对resume字段数据真正的读取操作。

相关文档
最新文档